Commit ce85abba authored by Johnny Jazeix's avatar Johnny Jazeix Committed by Bruno Coudoin
Browse files

core, combobox.

Add a GCCombobox which has same look on all platforms.
DialogActivityConfig needs the currentActivity to restore focus given to comboboxes.
Combobox contains both the button and a label (displayed besides and on the listheader) and needs a background (which is where we display the list and should be a fullscreen viewed widget).
Fix locale changing on gletters activities.
parent e3c5203a
......@@ -60,7 +60,8 @@ ActivityBase {
signal start
signal stop
property string locale: "$LOCALE"
// system locale by default
property string locale: "system"
Component.onCompleted: {
dialogActivityConfig.getInitialConfiguration()
......@@ -112,6 +113,7 @@ ActivityBase {
DialogActivityConfig {
id: dialogActivityConfig
currentActivity: activity
content: Component {
Item {
property alias localeBox: localeBox
......@@ -130,16 +132,12 @@ ActivityBase {
Flow {
spacing: 5
width: dialogActivityConfig.width
ComboBox {
GCComboBox {
id: localeBox
style: GCComboBoxStyle {}
model: langs.languages
background: dialogActivityConfig
width: 250 * ApplicationInfo.ratio
}
GCText {
text: qsTr("Select your locale")
fontSize: mediumSize
wrapMode: Text.WordWrap
label: qsTr("Select your locale")
}
}
/* TODO handle this:
......@@ -167,8 +165,11 @@ ActivityBase {
var oldLocale = background.locale;
var newLocale = dialogActivityConfig.configItem.availableLangs[dialogActivityConfig.loader.item.localeBox.currentIndex].locale;
// Remove .UTF-8
newLocale = newLocale.substring(0, newLocale.indexOf('.'))
if(newLocale.indexOf('.') != -1) {
newLocale = newLocale.substring(0, newLocale.indexOf('.'))
}
dataToSave = {"locale": newLocale}
background.locale = newLocale;
// Restart the activity with new information
......@@ -180,7 +181,11 @@ ActivityBase {
function setDefaultValues() {
var localeUtf8 = background.locale + ".UTF-8";
var localeUtf8 = background.locale;
if(background.locale != "system") {
localeUtf8 += ".UTF-8";
}
for(var i = 0 ; i < dialogActivityConfig.configItem.availableLangs.length ; i ++) {
if(dialogActivityConfig.configItem.availableLangs[i].locale === localeUtf8) {
dialogActivityConfig.loader.item.localeBox.currentIndex = i;
......
......@@ -72,15 +72,16 @@ function start(items_, uppercaseOnly_, _mode) {
mode = _mode;
currentLevel = 0;
currentSubLevel = 0;
var locale = items.locale == "system" ? "$LOCALE" : items.locale
items.wordlist.loadFromFile(GCompris.ApplicationInfo.getLocaleFilePath(
items.ourActivity.dataSetUrl + "default-"+items.locale+".json"));
items.ourActivity.dataSetUrl + "default-"+locale+".json"));
// If wordlist is empty, we try to load from short locale and if not present again, we switch to default one
var localeUnderscoreIndex = items.locale.indexOf('_')
var localeUnderscoreIndex = locale.indexOf('_')
// probably exist a better way to see if the list is empty
if(items.wordlist.maxLevel == 0 && localeUnderscoreIndex > 0) {
var localeShort = items.locale.substring(0, localeUnderscoreIndex)
var localeShort = locale.substring(0, localeUnderscoreIndex)
items.wordlist.useDefault = true
items.wordlist.loadFromFile(GCompris.ApplicationInfo.getLocaleFilePath(
items.ourActivity.dataSetUrl + "default-"+localeShort+".json"));
......@@ -377,6 +378,7 @@ function nextSubLevel() {
}
function playLetter(letter) {
items.audioVoices.append(GCompris.ApplicationInfo.getAudioFilePath("voices/"+items.locale+"/alphabet/"
var locale = items.locale == "system" ? "$LOCALE" : items.locale
items.audioVoices.append(GCompris.ApplicationInfo.getAudioFilePath("voices/"+locale+"/alphabet/"
+ Core.getSoundFilenamForChar(letter)))
}
......@@ -167,16 +167,12 @@ Item {
Flow {
spacing: 5
width: parent.width
ComboBox {
GCComboBox {
id: fontBox
style: GCComboBoxStyle {}
model: fonts
width: 250 * ApplicationInfo.ratio
}
GCText {
text: qsTr("Font selector")
fontSize: mediumSize
wrapMode: Text.WordWrap
background: dialogActivityConfig
label: qsTr("Font selector")
}
}
Flow {
......@@ -210,18 +206,13 @@ Item {
Flow {
spacing: 5
width: parent.width
ComboBox {
GCComboBox {
id: languageBox
style: GCComboBoxStyle {}
model: dialogConfig.languages
width: 300 * ApplicationInfo.ratio
background: dialogActivityConfig
onCurrentIndexChanged: voicesRow.localeChanged();
}
GCText {
text: qsTr("Language selector")
fontSize: mediumSize
wrapMode: Text.WordWrap
label: qsTr("Language selector")
}
}
......@@ -462,7 +453,7 @@ Item {
if (ApplicationSettings.locale != dialogConfig.languages[languageBox.currentIndex].locale) {
ApplicationSettings.locale = dialogConfig.languages[languageBox.currentIndex].locale
if (!DownloadManager.haveLocalResource(
DownloadManager.getVoicesResourceForLocale(ApplicationSettings.locale)))
DownloadManager.getVoicesResourceForLocale(ApplicationInfo.localeShort)))
{
// ask for downloading new voices
Core.showMessageDialog(main,
......@@ -471,13 +462,13 @@ Item {
qsTr("Yes"), function() {
// yes -> start download
if (DownloadManager.downloadResource(
DownloadManager.getVoicesResourceForLocale(ApplicationSettings.locale)))
DownloadManager.getVoicesResourceForLocale(ApplicationInfo.localeShort)))
var downloadDialog = Core.showDownloadDialog(main, {});
},
qsTr("No"), null,
null
);
} else // check for udpates or/and register new voices
} else // check for updates or/and register new voices
DownloadManager.updateResource(
DownloadManager.getVoicesResourceForLocale(ApplicationSettings.locale))
}
......
......@@ -456,6 +456,8 @@ ActivityBase {
DialogActivityConfig {
id: dialogActivityConfig
currentActivity: menuActivity
content: Component {
ConfigurationItem {
id: configItem
......
......@@ -110,6 +110,7 @@ ActivityBase {
DialogActivityConfig {
id: dialogActivityConfig
currentActivity: activity
content: Component {
Item {
property alias modeBox: modeBox
......@@ -123,16 +124,12 @@ ActivityBase {
id: flow
spacing: 5
width: dialogActivityConfig.width
ComboBox {
GCComboBox {
id: modeBox
style: GCComboBoxStyle {}
model: availableModes
width: 250 * ApplicationInfo.ratio
}
GCText {
text: qsTr("Select your mode")
fontSize: mediumSize
wrapMode: Text.WordWrap
background: dialogActivityConfig
label: qsTr("Select your mode")
}
}
}
......
......@@ -78,20 +78,26 @@ Rectangle {
/// @cond INTERNAL_DOCS
/* FIXME: still needed?: */
property bool isDialog: true
/* readonly? */
property string title: {
if(activityInfo)
/**
* type:string
* Title of the configuration dialog.
* Global configuration name is "Configuration".
* For activities, it is "activity name configuration".
*/
readonly property string title: {
if(activityName != "")
qsTr("%1 configuration").arg(activityInfo.title)
else
qsTr("Configuration")
}
property alias titleIcon: titleIcon.source
property alias active: loader.active
property alias loader: loader
property QtObject activityInfo: ActivityInfoTree.currentActivity
property ActivityBase currentActivity
/// @endcond
/**
......@@ -102,6 +108,7 @@ Rectangle {
/**
* Emitted when the config dialog has been started.
*/
signal start
/**
* Emitted when the settings are to be saved.
......@@ -117,9 +124,6 @@ Rectangle {
*/
signal loadData
signal start
signal pause
signal play
signal stop
......
/* GCompris - GCComboBox.qml
*
* Copyright (C) 2015 Johnny Jazeix <jazeix@gmail.com>
*
* Authors:
* Johnny Jazeix <jazeix@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.2
import QtQuick.Controls 1.1
import GCompris 1.0
Item {
id: gccombobox
focus: true
width: button.width
height: button.height
property Item background
property int currentIndex: -1
// The current text displayed in the combobox
property string currentText
property alias model: listview.model
// Text besides the combobox, used to describe what the combobox is for
property string label
// If model is an (js) Array, we access data using modelData and [] else qml Model, we need to use model and get().
property bool isModelArray: model.constructor === Array
// start and stop trigs the animation
signal start
signal stop
// emitted at stop animation end
signal close
onCurrentIndexChanged: {
currentText = isModelArray ? model[currentIndex].text : (model && model.get(currentIndex) ? model.get(currentIndex).text : "")
}
Flow {
width: button.width+labelText.width+10
spacing: 5 * ApplicationInfo.ratio
Rectangle {
id: button
visible: true
// Add radius to add some space between text and borders
implicitWidth: Math.max(200, currentTextBox.width+radius)
implicitHeight: 50 * ApplicationInfo.ratio
border.width: 2
border.color: "black"
radius: 10
gradient: Gradient {
GradientStop { position: 0 ; color: mouseArea.pressed ? "#87ff5c" : "#ffe85c" }
GradientStop { position: 1 ; color: mouseArea.pressed ? "#44ff00" : "#f8d600" }
}
// Current value of combobox
GCText {
id: currentTextBox
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: currentText
fontSize: mediumSize
}
MouseArea {
id: mouseArea
anchors.fill: parent
onReleased: {
popup.visible = true
}
}
}
GCText {
id: labelText
text: label
fontSize: mediumSize
wrapMode: Text.WordWrap
}
}
/* List */
Item {
id: popup
visible: false
width: parent.width
height: parent.height
parent: background
focus: visible
// Forward event to activity if key pressed is not one of the handled key
// (ctrl+F should still resize the window for example)
Keys.onPressed: background.currentActivity.Keys.onPressed(event)
Keys.onUpPressed: listview.decrementCurrentIndex()
Keys.onDownPressed: listview.incrementCurrentIndex()
Keys.onEscapePressed: {
// Keep the old value
discardChange();
hidePopUpAndRestoreFocus();
}
Keys.onEnterPressed: {
acceptChange();
hidePopUpAndRestoreFocus();
}
Keys.onReturnPressed: {
acceptChange();
hidePopUpAndRestoreFocus();
}
Keys.onSpacePressed: {
acceptChange();
hidePopUpAndRestoreFocus();
}
// Don't accept the list value, restore previous value
function discardChange() {
if(isModelArray) {
for(var i = 0 ; i < model.count ; ++ i) {
if(model[currentIndex].text === currentText) {
currentIndex = i;
break;
}
}
}
else {
for(var i = 0 ; i < model.length ; ++ i) {
if(model.get(currentIndex).text === currentText) {
currentIndex = i;
break;
}
}
}
listview.currentIndex = currentIndex;
}
// Accept the change. Updates the currentIndex and text of the button
function acceptChange() {
currentIndex = listview.currentIndex;
currentText = isModelArray ? model[currentIndex].text : (model && model.get(currentIndex) ? model.get(currentIndex).text : "")
}
function hidePopUpAndRestoreFocus() {
popup.visible = false;
// Restore focus on previous activity for keyboard input
background.currentActivity.forceActiveFocus();
}
Rectangle {
id: listBackground
anchors.fill: parent
radius: 10
color: "grey"
Rectangle {
id : headerDescription
width: listview.width
height: listview.elementHeight
GCText {
text: label
fontSize: mediumSize
wrapMode: Text.WordWrap
anchors.horizontalCenter: parent.horizontalCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
popup.acceptChange();
popup.hidePopUpAndRestoreFocus();
}
}
}
ListView {
id: listview
readonly property int elementHeight: 40 * ApplicationInfo.ratio
contentHeight: isModelArray ? elementHeight*model.count : elementHeight*model.length
width: listBackground.width
height: listBackground.height-headerDescription.height
currentIndex: gccombobox.currentIndex
flickableDirection: Flickable.VerticalFlick
clip: true
anchors.top: headerDescription.bottom
delegate: Component {
Rectangle {
width: listBackground.width
height: listview.elementHeight
color: ListView.isCurrentItem ? "darkcyan" : "beige"
border.width: ListView.isCurrentItem ? 3 : 2
radius: 5
Image {
id: isSelectedIcon
visible: parent.ListView.isCurrentItem
source: "qrc:/gcompris/src/core/resource/apply.svg"
fillMode: Image.PreserveAspectFit
anchors.right: textValue.left
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: 10
sourceSize.width: (listview.elementHeight*0.8) * ApplicationInfo.ratio
}
GCText {
id: textValue
text: isModelArray ? modelData.text : model.text
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
currentIndex = index
popup.acceptChange();
popup.hidePopUpAndRestoreFocus();
}
}
}
}
}
}
}
}
/* GCompris - GCComboBoxStyle.qml
*
* Copyright (C) 2014 Bruno Coudoin <bruno.coudoin@gcompris.net>
*
* Authors:
* Bruno Coudoin <bruno.coudoin@gcompris.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.1
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import GCompris 1.0
/**
* Provides styling for GCompris ComboBoxes.
* @ingroup components
*
* @inherit QtQuick.Controls.Styles.ComboBoxStyle
*/
ComboBoxStyle {
background: Rectangle {
implicitWidth: 200
implicitHeight: 50 * ApplicationInfo.ratio
border.width: control.activeFocus ? 4 : 2
border.color: "black"
radius: 10
gradient: Gradient {
GradientStop { position: 0 ; color: control.pressed ? "#87ff5c" : "#ffe85c" }
GradientStop { position: 1 ; color: control.pressed ? "#44ff00" : "#f8d600" }
}
}
label: Item {
anchors.fill: parent
GCText {
text: control.currentText
wrapMode: Text.WordWrap
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment