diff --git a/src/qml/DownloadPage.qml b/src/qml/DownloadPage.qml index 49ac500..d21d9ff 100644 --- a/src/qml/DownloadPage.qml +++ b/src/qml/DownloadPage.qml @@ -1,119 +1,122 @@ /* * Copyright 2018 Andreas Cord-Landwehr * * 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 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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 . */ import QtQuick 2.1 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.1 as QQC2 import org.kde.kirigami 2.0 as Kirigami import org.kde.newstuff 1.0 as KNS Kirigami.Page { id: root title: i18n("Download Training Material") + background: Rectangle { + color: "#ffffff" + } Component { id: courseDownloadItem Kirigami.AbstractListItem { id: listItem height: 50 width: parent.width text: model.name readonly property var status: model.status onStatusChanged: { g_resourceManager.loadCourseResources(); } checkable: false RowLayout { id: layout spacing: Kirigami.Units.smallSpacing*2 Kirigami.Icon { height: Kirigami.Units.iconSizes.smallMedium; width: height; SequentialAnimation on opacity { loops: Animation.Infinite; running: model.status == KNS.ItemsModel.InstallingStatus || model.status == KNS.ItemsModel.UpdatingStatus NumberAnimation { to: 0; duration: 500; } NumberAnimation { to: 1; duration: 500; } onRunningChanged: { if (!running) parent.opacity = 1; } } source: { // use complete list of KNS status messages if (model.status == KNS.ItemsModel.InvalidStatus) return "emblem-error"; if (model.status == KNS.ItemsModel.DownloadableStatus) return "vcs-added"; if (model.status == KNS.ItemsModel.InstalledStatus) return "vcs-normal"; if (model.status == KNS.ItemsModel.UpdateableStatus) return "vcs-update-required"; if (model.status == KNS.ItemsModel.DeletedStatus) return "vcs-added"; if (model.status == KNS.ItemsModel.InstallingStatus) return "vcs-locally-modified"; if (model.status == KNS.ItemsModel.UpdatingStatus) return "vcs-locally-modified"; return "emblem-error"; } } QQC2.Label { id: labelItem Layout.fillWidth: true text: listItem.text color: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || listItem.pressed) ? listItem.activeTextColor : listItem.textColor elide: Text.ElideRight font: listItem.font } QQC2.Button { visible: (model.status == KNS.ItemsModel.UpdateableStatus) ? true : false; text: i18n("update") onClicked: newStuffModel.installItem(model.index) } QQC2.Button { visible: (model.status == KNS.ItemsModel.DownloadableStatus || model.status == KNS.ItemsModel.DeletedStatus) ? true : false; text: i18n("install") onClicked: newStuffModel.installItem(model.index) } QQC2.Button { visible: (model.status == KNS.ItemsModel.InstalledStatus || model.status == KNS.ItemsModel.UpdateableStatus) ? true : false; text: i18n("remove") onClicked: newStuffModel.uninstallItem(model.index) } } } } ColumnLayout { ListView { id: listView width: root.width - 40 height: 50 * listView.count delegate: courseDownloadItem model: KNS.ItemsModel { id: newStuffModel; engine: newStuffEngine.engine; } KNS.Engine { id: newStuffEngine; configFile: ":/artikulate/config/artikulate.knsrc"; onMessage: console.log("KNS Message: " + message); onIdleMessage: console.log("KNS Idle: " + message); onBusyMessage: console.log("KNS Busy: " + message); onErrorMessage: console.log("KNS Error: " + message); } } } } diff --git a/src/qml/ProfileSettingsPage.qml b/src/qml/ProfileSettingsPage.qml index f78989f..561322d 100644 --- a/src/qml/ProfileSettingsPage.qml +++ b/src/qml/ProfileSettingsPage.qml @@ -1,130 +1,133 @@ /* * Copyright 2013-2018 Andreas Cord-Landwehr * * 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 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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 . */ import QtQuick 2.1 import QtQuick.Controls 2.0 as QQC2 import org.kde.kirigami 2.0 as Kirigami import QtQuick.Layouts 1.2 import artikulate 1.0 Kirigami.Page { id: root Layout.fillWidth: true title: i18n("Configure Profile") + background: Rectangle { + color: "#ffffff" + } readonly property Learner profile: g_profileManager.activeProfile signal deletionRequest() actions { main: Kirigami.Action { id: editorAction text: i18n("Edit") iconName: "document-edit" checkable: true } } actions.contextualActions: [ Kirigami.Action { iconName: "insert-image" text: i18n("Select Image") onTriggered: { g_profileManager.openImageFileDialog() } }, Kirigami.Action { iconName: "edit-clear" text: i18n("Clear Image") onTriggered: { g_profileManager.activeProfile.clearImage() } }, Kirigami.Action { text: i18n("Delete User") iconName: "edit-delete" enabled: root.state == "editor" && g_profileManager.profileCount > 1 //TODO handle this situation gracefully by allowing removal of last profile onTriggered: deletionRequest() } ] // image MouseArea { id: image height: 120 width: height anchors { top: parent.top right: parent.right topMargin: 30 leftMargin: 30 } ProfileUserImageItem { anchors.centerIn: parent profile: root.profile } onClicked: g_profileManager.openImageFileDialog() } Text { id: learnerNameText anchors { horizontalCenter: parent.horizontalCenter top: image.bottom topMargin: 30 } height: paintedHeight font.pointSize: theme.fontPointSize * 1.2 text: root.profile != null ? root.profile.name : "" } QQC2.TextField { id: learnerNameTextEdit anchors { horizontalCenter: parent.horizontalCenter top: image.bottom topMargin: 30 } visible: false width: parent.width placeholderText: i18n("Name") text: learnerNameText.text onTextChanged: { root.profile.name = text g_profileManager.sync(root.profile) } } states: [ State { name: "editor" when: editorAction.checked PropertyChanges { target: learnerNameTextEdit visible: true } } ] } diff --git a/src/qml/TrainingPage.qml b/src/qml/TrainingPage.qml index 7158902..d4e6638 100644 --- a/src/qml/TrainingPage.qml +++ b/src/qml/TrainingPage.qml @@ -1,164 +1,168 @@ /* * Copyright 2013-2019 Andreas Cord-Landwehr * Copyright 2013 Magdalena Konkiewicz * * 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 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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 . */ import QtQuick 2.5 import QtQuick.Shapes 1.10 import QtQuick.Controls 2.3 as QQC2 -import org.kde.kirigami 2.0 as Kirigami2 +import org.kde.kirigami 2.7 as Kirigami import artikulate 1.0 -Kirigami2.Page { +Kirigami.Page { id: root readonly property color colorTask: "#1dbf4e" readonly property color colorAnswer: "#7e48a5" + background: Rectangle { + color: "#ffffff" + } + title: { var titleString = ""; if (g_trainingSession.unit === null) { titleString += i18n("Category: no category selected"); } else { titleString += i18n("Category: ") + g_trainingSession.unit.title } if (g_trainingSession.unit !== null && g_trainingSession.course !== null) { titleString += " / " + g_trainingSession.course.i18nTitle } return titleString } actions { - main: Kirigami2.Action { + main: Kirigami.Action { text: i18n("Next") tooltip: i18n("Mark current phrase as completed and proceed with next one.") iconName: "dialog-ok" onTriggered: g_trainingSession.accept() } - right: Kirigami2.Action { + right: Kirigami.Action { text: i18n("Skip") tooltip: i18n("Skip current phrase and proceed with next one.") iconName: "go-next" enabled: g_trainingSession.hasNext onTriggered: g_trainingSession.skip() } } Rectangle { id: trainingTextRect width: Math.min(0.7 * parent.width, parent.width - 80) height: Math.max(200, phraseText.implicitHeight) anchors { left: parent.left top: parent.top leftMargin: 20 topMargin: 20 } color: root.colorTask Shape { id: taskTriangle width: 50 height: 40 anchors { top: parent.bottom horizontalCenter: parent.horizontalCenter horizontalCenterOffset: parent.width / 10 } ShapePath { fillColor: colorTask strokeColor: colorTask PathLine { x: 0; y: 0 } PathLine { x: taskTriangle.width; y: taskTriangle.height } PathLine { x: taskTriangle.width; y: 0 } } } QQC2.TextArea { id: phraseText anchors.fill: parent objectName: "phraseText" text: (g_trainingSession.phrase !== null) ? g_trainingSession.phrase.text : "" font.pointSize: 24 wrapMode: Text.WordWrap readOnly: true background: Item {} horizontalAlignment: Text.AlignHCenter verticalAlignment: TextEdit.AlignVCenter } SoundPlayer { id: buttonNativePlay anchors { top: taskTriangle.bottom topMargin: 20 horizontalCenter: taskTriangle.right } text: i18n("Play original") fileUrl: g_trainingSession.phrase === null ? "" : g_trainingSession.phrase.soundFileUrl } } Rectangle { id: trainingUserRect width: 200 height: 0.65 * width anchors { right: parent.right top: trainingTextRect.bottom rightMargin: 20 topMargin: 154 } color: root.colorAnswer Shape { id: answerTriangle width: 50 height: 40 anchors { bottom: parent.top horizontalCenter: parent.horizontalCenter horizontalCenterOffset: -parent.width / 10 } ShapePath { fillColor: root.colorAnswer strokeColor: root.colorAnswer PathLine { x: 0; y: 0 } PathLine { x: 0; y: taskTriangle.height } PathLine { x: taskTriangle.width; y: taskTriangle.height } } } SoundRecorder { id: recorder anchors { bottom: answerTriangle.top bottomMargin: 20 horizontalCenter: answerTriangle.left } text: i18n("Record yourself") } SoundPlayer { id: player anchors { centerIn: parent } text: i18n("Play yourself") fileUrl: recorder.outputFileUrl } } }