diff --git a/src/activities/menu/ConfigurationItem.qml b/src/activities/menu/ConfigurationItem.qml
index f8937a0543..f3beb76c01 100644
--- a/src/activities/menu/ConfigurationItem.qml
+++ b/src/activities/menu/ConfigurationItem.qml
@@ -213,6 +213,15 @@ Item {
}
}
+ GCDialogCheckBox {
+ id: enableExitDialogBox
+ text: qsTr("Enable activity Exit confirmation dialog")
+ checked: isExitDialogEnabled
+ onCheckedChanged: {
+ isExitDialogEnabled = checked;
+ }
+ }
+
GCDialogCheckBox {
id: enableFullscreenBox
text: qsTr("Fullscreen")
@@ -547,6 +556,7 @@ Item {
property bool showLockedActivities: ApplicationSettings.showLockedActivities
property bool isAudioVoicesEnabled: ApplicationSettings.isAudioVoicesEnabled
property bool isAudioEffectsEnabled: ApplicationSettings.isAudioEffectsEnabled
+ property bool isExitDialogEnabled: ApplicationSettings.isExitDialogEnabled
property bool isFullscreen: ApplicationSettings.isFullscreen
property bool isVirtualKeyboard: ApplicationSettings.isVirtualKeyboard
property bool isAutomaticDownloadsEnabled: ApplicationSettings.isAutomaticDownloadsEnabled
@@ -565,6 +575,9 @@ Item {
isAudioEffectsEnabled = ApplicationSettings.isAudioEffectsEnabled
enableAudioEffectsBox.checked = isAudioEffectsEnabled
+ isExitDialogEnabled = ApplicationSettings.isExitDialogEnabled
+ enableExitDialogBox.checked = isExitDialogEnabled
+
isFullscreen = ApplicationSettings.isFullscreen
enableFullscreenBox.checked = isFullscreen
@@ -612,6 +625,7 @@ Item {
ApplicationSettings.showLockedActivities = showLockedActivities
ApplicationSettings.isAudioVoicesEnabled = isAudioVoicesEnabled
ApplicationSettings.isAudioEffectsEnabled = isAudioEffectsEnabled
+ ApplicationSettings.isExitDialogEnabled = isExitDialogEnabled
ApplicationSettings.isFullscreen = isFullscreen
ApplicationSettings.isVirtualKeyboard = isVirtualKeyboard
ApplicationSettings.isAutomaticDownloadsEnabled = isAutomaticDownloadsEnabled
diff --git a/src/activities/menu/Menu.qml b/src/activities/menu/Menu.qml
index 36fdc4309a..114561ea59 100644
--- a/src/activities/menu/Menu.qml
+++ b/src/activities/menu/Menu.qml
@@ -47,6 +47,9 @@ ActivityBase {
id: activity
focus: true
activityInfo: ActivityInfoTree.rootMenu
+ // set to true when returned to home from a dialog.
+ property bool returnFromDialog: false
+
onBack: {
pageView.pop(to);
// Restore focus that has been taken by the loaded activity
@@ -58,17 +61,33 @@ ActivityBase {
if(pageView.depth === 1 && !ApplicationSettings.isKioskMode) {
Core.quit(main);
}
- else {
+ // When a dialog box is closed.
+ else if(returnFromDialog || !ApplicationSettings.isExitDialogEnabled) {
+ returnFromDialog = false;
pageView.pop();
// Restore focus that has been taken by the loaded activity
if(pageView.currentItem == activity)
focus = true;
}
+ // A confirmation dialog to quit the current activity is popped.
+ else {
+ Core.showMessageDialog(parent,
+ qsTr("Do you want to leave current activity?"),
+ qsTr("Yes"), function() { pageView.pop();
+ // Restore focus that has been taken by the loaded activity
+ if(pageView.currentItem == activity)
+ focus = true; },
+ qsTr("No"), null,
+ null );
+ }
}
- onDisplayDialog: pageView.push(dialog)
-
+ onDisplayDialog: {
+ returnFromDialog = true;
+ pageView.push(dialog)
+ }
onDisplayDialogs: {
+ returnFromDialog = true;
var toPush = new Array();
for (var i = 0; i < dialogs.length; i++) {
toPush.push({item: dialogs[i]});
@@ -215,12 +234,12 @@ ActivityBase {
model: sections
width: horizontal ? main.width : sectionCellWidth
height: {
- if(horizontal)
- return sectionCellHeight
- else if(activity.currentTag === "search" && ApplicationSettings.isVirtualKeyboard)
- return sectionCellHeight * (sections.length+1)
- else
- return main.height - bar.height
+ if(horizontal)
+ return sectionCellHeight
+ else if(activity.currentTag === "search" && ApplicationSettings.isVirtualKeyboard)
+ return sectionCellHeight * (sections.length+1)
+ else
+ return main.height - bar.height
}
x: ApplicationSettings.sectionVisible ? section.initialX : -sectionCellWidth
y: ApplicationSettings.sectionVisible ? section.initialY : -sectionCellHeight
@@ -491,9 +510,9 @@ ActivityBase {
visible: false
anchors.fill: activitiesGrid
gradient: Gradient {
- GradientStop { position: 0.0; color: "#FFFFFFFF" }
- GradientStop { position: 0.92; color: "#FFFFFFFF" }
- GradientStop { position: 0.96; color: "#00FFFFFF"}
+ GradientStop { position: 0.0; color: "#FFFFFFFF" }
+ GradientStop { position: 0.92; color: "#FFFFFFFF" }
+ GradientStop { position: 0.96; color: "#00FFFFFF"}
}
}
layer.enabled: ApplicationInfo.useOpenGL
@@ -622,37 +641,37 @@ ActivityBase {
}
}
function populate() {
- var tmplayout = [];
- var row = 0;
- var offset = 0;
- var cols;
- while(offset < letter.length-1) {
- if(letter.length <= 100) {
- cols = Math.ceil((letter.length-offset) / (3 - row));
- }
- else {
- cols = background.horizontal ? (Math.ceil((letter.length-offset) / (15 - row)))
- :(Math.ceil((letter.length-offset) / (22 - row)))
- if(row == 0) {
- tmplayout[row] = new Array();
- tmplayout[row].push({ label: keyboard.backspace });
- tmplayout[row].push({ label: keyboard.space });
- row ++;
- }
- }
-
- tmplayout[row] = new Array();
- for (var j = 0; j < cols; j++)
- tmplayout[row][j] = { label: letter[j+offset] };
- offset += j;
- row ++;
- }
- if(letter.length <= 100) {
- tmplayout[0].push({ label: keyboard.space });
- tmplayout[row-1].push({ label: keyboard.backspace });
- }
- keyboard.layout = tmplayout
- }
+ var tmplayout = [];
+ var row = 0;
+ var offset = 0;
+ var cols;
+ while(offset < letter.length-1) {
+ if(letter.length <= 100) {
+ cols = Math.ceil((letter.length-offset) / (3 - row));
+ }
+ else {
+ cols = background.horizontal ? (Math.ceil((letter.length-offset) / (15 - row)))
+ :(Math.ceil((letter.length-offset) / (22 - row)))
+ if(row == 0) {
+ tmplayout[row] = new Array();
+ tmplayout[row].push({ label: keyboard.backspace });
+ tmplayout[row].push({ label: keyboard.space });
+ row ++;
+ }
+ }
+
+ tmplayout[row] = new Array();
+ for (var j = 0; j < cols; j++)
+ tmplayout[row][j] = { label: letter[j+offset] };
+ offset += j;
+ row ++;
+ }
+ if(letter.length <= 100) {
+ tmplayout[0].push({ label: keyboard.space });
+ tmplayout[row-1].push({ label: keyboard.backspace });
+ }
+ keyboard.layout = tmplayout
+ }
}
Bar {
@@ -678,6 +697,7 @@ ActivityBase {
dialogActivityConfig.loader.item.loadFromConfig()
displayDialog(dialogActivityConfig)
}
+ onExitClicked: home()
}
DialogAbout {
diff --git a/src/core/ActivityBase.qml b/src/core/ActivityBase.qml
index 4e38ad42ed..e47047534c 100644
--- a/src/core/ActivityBase.qml
+++ b/src/core/ActivityBase.qml
@@ -178,14 +178,14 @@ Item {
Keys.onPressed: {
if (event.modifiers === Qt.ControlModifier &&
event.key === Qt.Key_Q) {
- // Ctrl+Q exit the application
- Core.quit(main);
+ // Ctrl+Q exit the application without displaying confirmation dialog.
+ Core.quit(main, true);
} else if (event.modifiers === Qt.ControlModifier &&
- event.key === Qt.Key_B) {
+ event.key === Qt.Key_B) {
// Ctrl+B toggle the bar
ApplicationSettings.isBarHidden = !ApplicationSettings.isBarHidden;
} else if (event.modifiers === Qt.ControlModifier &&
- event.key === Qt.Key_F) {
+ event.key === Qt.Key_F) {
// Ctrl+F toggle fullscreen
ApplicationSettings.isFullscreen = !ApplicationSettings.isFullscreen
} else if (event.modifiers === Qt.ControlModifier &&
diff --git a/src/core/ApplicationSettings.cpp b/src/core/ApplicationSettings.cpp
index 781044645a..63d5bd1787 100644
--- a/src/core/ApplicationSettings.cpp
+++ b/src/core/ApplicationSettings.cpp
@@ -55,6 +55,7 @@ static const QString PREVIOUS_WIDTH_KEY = "previousWidth";
static const QString SHOW_LOCKED_ACTIVITIES_KEY = "showLockedActivities";
static const QString ENABLE_AUDIO_VOICES_KEY = "enableAudioVoices";
static const QString ENABLE_AUDIO_EFFECTS_KEY = "enableAudioEffects";
+static const QString ENABLE_EXIT_DIALOG_KEY = "enableExitDialog";
static const QString VIRTUALKEYBOARD_KEY = "virtualKeyboard";
static const QString LOCALE_KEY = "locale";
static const QString FONT_KEY = "font";
@@ -99,6 +100,7 @@ ApplicationSettings::ApplicationSettings(QObject *parent): QObject(parent),
// general group
m_config.beginGroup(GENERAL_GROUP_KEY);
m_isAudioEffectsEnabled = m_config.value(ENABLE_AUDIO_EFFECTS_KEY, true).toBool();
+ m_isExitDialogEnabled = m_config.value(ENABLE_EXIT_DIALOG_KEY, true).toBool();
m_isFullscreen = m_config.value(FULLSCREEN_KEY, true).toBool();
m_previousHeight = m_config.value(PREVIOUS_HEIGHT_KEY, screenSize.height()).toUInt();
m_previousWidth = m_config.value(PREVIOUS_WIDTH_KEY, screenSize.width()).toUInt();
@@ -170,7 +172,8 @@ ApplicationSettings::ApplicationSettings(QObject *parent): QObject(parent),
connect(this, &ApplicationSettings::showLockedActivitiesChanged, this, &ApplicationSettings::notifyShowLockedActivitiesChanged);
connect(this, &ApplicationSettings::audioVoicesEnabledChanged, this, &ApplicationSettings::notifyAudioVoicesEnabledChanged);
connect(this, &ApplicationSettings::audioEffectsEnabledChanged, this, &ApplicationSettings::notifyAudioEffectsEnabledChanged);
- connect(this, &ApplicationSettings::fullscreenChanged, this, &ApplicationSettings::notifyFullscreenChanged);
+ connect(this, &ApplicationSettings::exitDialogEnabledChanged, this, &ApplicationSettings::notifyExitDialogEnabledChanged);
+ connect(this, &ApplicationSettings::fullscreenChanged, this, &ApplicationSettings::notifyFullscreenChanged);
connect(this, &ApplicationSettings::previousHeightChanged, this, &ApplicationSettings::notifyPreviousHeightChanged);
connect(this, &ApplicationSettings::previousWidthChanged, this, &ApplicationSettings::notifyPreviousWidthChanged);
connect(this, &ApplicationSettings::localeChanged, this, &ApplicationSettings::notifyLocaleChanged);
@@ -255,6 +258,12 @@ void ApplicationSettings::notifyAudioEffectsEnabledChanged()
qDebug() << "notifyAudioEffects: " << m_isAudioEffectsEnabled;
}
+void ApplicationSettings::notifyExitDialogEnabledChanged()
+{
+ updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_EXIT_DIALOG_KEY, m_isExitDialogEnabled);
+ qDebug() << "exit dialog Visibilty set to : " << m_isExitDialogEnabled;
+}
+
void ApplicationSettings::notifyLocaleChanged()
{
updateValueInConfig(GENERAL_GROUP_KEY, LOCALE_KEY, m_locale);
diff --git a/src/core/ApplicationSettings.h b/src/core/ApplicationSettings.h
index e681f56bb2..276721aad0 100644
--- a/src/core/ApplicationSettings.h
+++ b/src/core/ApplicationSettings.h
@@ -81,6 +81,11 @@ class ApplicationSettings : public QObject
*/
Q_PROPERTY(bool isAudioEffectsEnabled READ isAudioEffectsEnabled WRITE setIsAudioEffectsEnabled NOTIFY audioEffectsEnabledChanged)
+ /**
+ * Whether activity exit confirmation dialog should be displayed.
+ */
+ Q_PROPERTY(bool isExitDialogEnabled READ isExitDialogEnabled WRITE setIsExitDialogEnabled NOTIFY exitDialogEnabledChanged)
+
/**
* Whether GCompris should run in fullscreen mode.
*/
@@ -285,6 +290,12 @@ class ApplicationSettings : public QObject
emit audioEffectsEnabledChanged();
}
+ bool isExitDialogEnabled() const { return m_isExitDialogEnabled; }
+ void setIsExitDialogEnabled(const bool newMode) {
+ m_isExitDialogEnabled = newMode;
+ emit exitDialogEnabledChanged();
+ }
+
bool isFullscreen() const { return m_isFullscreen; }
void setFullscreen(const bool newMode) {
if(m_isFullscreen != newMode) {
@@ -472,6 +483,7 @@ protected slots:
Q_INVOKABLE void notifyShowLockedActivitiesChanged();
Q_INVOKABLE void notifyAudioVoicesEnabledChanged();
Q_INVOKABLE void notifyAudioEffectsEnabledChanged();
+ Q_INVOKABLE void notifyExitDialogEnabledChanged();
Q_INVOKABLE void notifyFullscreenChanged();
Q_INVOKABLE void notifyPreviousHeightChanged();
Q_INVOKABLE void notifyPreviousWidthChanged();
@@ -541,6 +553,7 @@ public slots:
void showLockedActivitiesChanged();
void audioVoicesEnabledChanged();
void audioEffectsEnabledChanged();
+ void exitDialogEnabledChanged();
void fullscreenChanged();
void previousHeightChanged();
void previousWidthChanged();
@@ -579,6 +592,7 @@ public slots:
bool m_showLockedActivities;
bool m_isAudioVoicesEnabled;
bool m_isAudioEffectsEnabled;
+ bool m_isExitDialogEnabled;
bool m_isFullscreen;
quint32 m_previousHeight;
quint32 m_previousWidth;
diff --git a/src/core/Bar.qml b/src/core/Bar.qml
index e695b6818f..d66e33b58d 100644
--- a/src/core/Bar.qml
+++ b/src/core/Bar.qml
@@ -177,6 +177,14 @@ Item {
*/
signal homeClicked
+ /**
+ * Emitted when the exit button was clicked.
+ *
+ * Should always be connected to the ActivityBase.home signal and thus
+ * exits the GCompris after showing exit dialog.
+ */
+ signal exitClicked
+
/// @cond INTERNAL_DOCS
/*
@@ -384,7 +392,7 @@ Item {
BarButton {
source: "qrc:/gcompris/src/core/resource/bar_exit.svg";
sourceSize.width: fullButton * barZoom
- onClicked: Core.quit(bar.parent.parent);
+ onClicked: bar.exitClicked()
}
}
Component {
diff --git a/src/core/GCDialog.qml b/src/core/GCDialog.qml
index 5d458ac540..a678bd0006 100644
--- a/src/core/GCDialog.qml
+++ b/src/core/GCDialog.qml
@@ -98,8 +98,14 @@ Item {
fill: parent
}
- onStart: opacity = 1
- onStop: opacity = 0
+ onStart: {
+ opacity = 1
+ forceActiveFocus();
+ }
+ onStop: {
+ opacity = 0
+ parent.currentItem.forceActiveFocus();
+ }
onClose: destroy()
Behavior on opacity { NumberAnimation { duration: 200 } }
@@ -158,7 +164,7 @@ Item {
fontSize: regularSize
color: "black"
// @FIXME This property breaks the wrapping
-// horizontalAlignment: Text.AlignHCenter
+ // horizontalAlignment: Text.AlignHCenter
// need to remove the anchors (left and right) else sometimes text is hidden on the side
width: instruction.width - 2*flick.anchors.margins
wrapMode: TextEdit.WordWrap
diff --git a/src/core/core.js b/src/core/core.js
index 8485504856..c3827d1cb0 100644
--- a/src/core/core.js
+++ b/src/core/core.js
@@ -95,12 +95,12 @@ function showMessageDialog(parent, informativeText,
closeCallback) {
//console.debug("Core.showMessageDialog: parent=" + parent + " backtrace="); console.trace();
var qmlStr =
- 'import QtQuick 2.6\n'
- + 'GCDialog {\n'
- + ' message: "' + informativeText + '"\n'
- + ' button1Text: "' + button1Text + '"\n'
- + ' button2Text: "' + button2Text + '"\n'
- + ' }\n';
+ 'import QtQuick 2.6\n'
+ + 'GCDialog {\n'
+ + ' message: "' + informativeText + '"\n'
+ + ' button1Text: "' + button1Text + '"\n'
+ + ' button2Text: "' + button2Text + '"\n'
+ + ' }\n';
var dialog = null;
try {
@@ -156,7 +156,7 @@ function showDownloadDialog(parent, properties) {
downloadDialogComponent = Qt.createComponent("qrc:/gcompris/src/core/DownloadDialog.qml");
if (downloadDialogComponent.status != Qml.Component.Ready) {
throw new Error("Error creating DownloadDialog component: "
- + downloadDialogComponent.errorString());
+ + downloadDialogComponent.errorString());
downloadDialogComponent = null;
}
}
@@ -187,13 +187,13 @@ function checkForVoices(parent)
{
if (!GCompris.DownloadManager.areVoicesRegistered()) {
showMessageDialog(parent,
- qsTr("Missing sound files!") + '\n'
- + qsTr("This activity uses language sound files, that are not yet installed on your system.")
- + '\n'
- + qsTr("For downloading the needed sound files go to the preferences dialog."),
- "", null,
- "", null,
- null);
+ qsTr("Missing sound files!") + '\n'
+ + qsTr("This activity uses language sound files, that are not yet installed on your system.")
+ + '\n'
+ + qsTr("For downloading the needed sound files go to the preferences dialog."),
+ "", null,
+ "", null,
+ null);
}
}
@@ -202,12 +202,12 @@ var aboutToQuit = false;
* Central function for quitting GCompris.
*
* Should be used everywhere instead of Qt.quit(), warning in case of running
- * downloadloads and showing a confirmation dialog on mobile devices.
+ * downloadloads and showing a confirmation dialog on closing GCompris.
* Call Qt.quit() itself upon confirmation.
*
* @param parent QML parent object used for the dynamic dialog.
*/
-function quit(parent)
+function quit(parent, forcedQuit)
{
if (aboutToQuit) // don't execute concurrently
return;
@@ -218,26 +218,27 @@ function quit(parent)
if (GCompris.DownloadManager.downloadIsRunning()) {
var dialog = showDownloadDialog(parent, {
- text: qsTr("Download in progress")
- + '\n'
- + qsTr("Download in progress.
'Abort' it to quit immediately."),
- autohide: true,
- reportError: false,
- reportSuccess: false,
- backgroundButtonVisible: false
- });
+ text: qsTr("Download in progress")
+ + '\n'
+ + qsTr("Download in progress.
'Abort' it to quit immediately."),
+ autohide: true,
+ reportError: false,
+ reportSuccess: false,
+ backgroundButtonVisible: false
+ });
dialog.finished.connect(function() {Qt.quit();});
- } else if (GCompris.ApplicationInfo.isMobile) {
+ }
+ else if(forcedQuit) {
+ Qt.quit();
+ }
+ else {
// prevent the user from quitting accidentially by clicking back too often:
showMessageDialog(parent,
- qsTr("Quit?") +
- '\n' +
- qsTr("Do you really want to quit GCompris?"),
- qsTr("Yes"), function() { Qt.quit(); },
- qsTr("No"), function() { aboutToQuit = false; },
- function() { aboutToQuit = false; } );
- } else
- Qt.quit();
+ qsTr("Do you really want to quit GCompris?"),
+ qsTr("Yes"), function() { Qt.quit(); },
+ qsTr("No"), function() { aboutToQuit = false; },
+ function() { aboutToQuit = false; } );
+ }
}
function isLeftToRightLocale(locale) {