Commit 8c51695a authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Initial UI port of trainer to Kirigami2

Rebuild the main UI logic based on the Kirigami 2 framework to provide
a common look and feel with other KDE applications and remove code
duplication.
parent a307f6e5
###
# Copyright 2013-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
# Copyright 2013-2016 Andreas Cord-Landwehr <cordlandwehr@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
......@@ -50,13 +50,14 @@ find_package(Qt5 5.5 REQUIRED COMPONENTS
QuickWidgets
Test
)
find_package(KF5 REQUIRED COMPONENTS
find_package(KF5 5.36 REQUIRED COMPONENTS
Archive
Config
Crash
I18n
NewStuff
XmlGui
Kirigami2
)
# options
......
/*
* Copyright 2013-2016 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2013-2017 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -19,37 +19,94 @@
*/
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import QtQml.Models 2.2
import QtQuick.Controls 2.0 as QQC2
import org.kde.kirigami 2.0 as Kirigami2
import artikulate 1.0
ApplicationWindow {
Kirigami2.ApplicationWindow {
id: root
visible: true
minimumWidth: 800
minimumHeight: 600
function changePage(pageItem) {
root.pageStack.clear();
root.pageStack.push(pageItem);
root.pageStack.push(pageItem);
}
header: Kirigami2.ApplicationHeader {
}
globalDrawer: Kirigami2.GlobalDrawer {
title: "Artikulate"
titleIcon: "artikulate"
actions: [
Kirigami2.Action {
text: i18n("Welcome")
iconName: "artikulate"
onTriggered: {
root.pageStack.clear();
root.pageStack.push(welcomePageComponent);
}
},
Kirigami2.Action {
text: i18n("Training")
iconName: "document-open"
onTriggered: {
root.pageStack.clear();
root.pageStack.push(trainingItemsPageComponent);
root.pageStack.push(trainingPageComponent);
}
},
Kirigami2.Action {
text: i18n("Download Training")
iconName: "get-hot-new-stuff"
onTriggered: triggerDownloadCourses()
},
Kirigami2.Action {
text: i18n("User Profile")
iconName: "user-properties"
onTriggered: {
root.pageStack.clear();
root.pageStack.push(profileSettingsPageComponent);
}
},
Kirigami2.Action {
text: i18n("Configure Artikulate...")
iconName: "settings-configure"
onTriggered: triggerSettingsDialog()
},
Kirigami2.Action {
text: i18n("Help")
iconName: "help-about"
Kirigami2.Action {
text: i18n("Artikulate Handbook")
iconName: "help-contents"
onTriggered: triggerAction("help_contents")
}
Kirigami2.Action {
text: i18n("Report Bug")
iconName: "tools-report-bug"
onTriggered: triggerAction("help_report_bug")
}
Kirigami2.Action {
text: i18n("About Artikulate")
iconName: "artikulate"
onTriggered: triggerAction("help_about_app")
}
Kirigami2.Action {
text: i18n("About KDE")
iconName: "help-about"
onTriggered: triggerAction("help_about_kde")
}
}
]
}
signal triggerDownloadCourses();
signal triggerEditProfile();
signal triggerSettingsDialog();
signal triggerAction(string actionName);
signal switchMenuBarVisibility();
onTriggerEditProfile: {
editProfileDialog.open()
}
Item {
id: theme
property string backgroundColor: "#ffffff"
property int smallIconSize: 18
property int smallMediumIconSize: 22
property int mediumIconSize: 32
property int fontPointSize: 11
property int spacing: 15
}
property Learner learner: g_profileManager.activeProfile
property ResourceManager resourceManager: g_resourceManager
......@@ -58,145 +115,23 @@ ApplicationWindow {
resourceManager: g_resourceManager
}
// main menu bar
menuBar: MainMenuBar {
id: topMenu
// note: this is access to internal API, but the only way to unset/hide the menu bar
__contentItem.visible: kcfg_ShowMenuBar
}
pageStack.initialPage: welcomePageComponent
// pages
Component {
id: welcomeScreen
NewUserWelcome { }
id: welcomePageComponent
WelcomePage { }
}
Component {
id: trainingScreen
RowLayout {
id: mainRow
Layout.fillHeight: true
spacing: theme.spacing
TreeView {
id: phraseTree
implicitWidth: Math.floor(root.width * 0.3)
Layout.fillHeight: true
TableViewColumn {
title: i18n("Categories")
role: "text"
}
model: PhraseModel {
id: phraseModel
course: g_trainingSession.course
}
selection: ItemSelectionModel {
model: phraseTree.model
}
itemDelegate: Item {
property bool isUnit: phraseModel.isUnit(styleData.index)
Component {
id: unitRowBackground
Rectangle {anchors.fill: parent; color: "steelblue"}
id: trainingPageComponent
TrainingPage { }
}
Component {
id: phraseProgress
Row {
property int progress: isUnit ? 0 : phraseModel.phrase(styleData.index).progress
Repeater {
model: 3
Icon {
width: 16
height: width
icon: progress > index ? "rating" : "rating-unrated"
}
}
}
}
Loader {
anchors.fill: parent
sourceComponent: isUnit ? unitRowBackground : null
}
Row {
Text {
width: phraseTree.width - 130 //TODO check if this is really a reasonable value
anchors {
verticalCenter: parent.verticalCenter
topMargin: 5
bottomMargin: 5
}
color: {
if (isUnit) {
return "white";
}
return styleData.textColor
}
elide: Text.ElideRight
text: " " + styleData.value
font.bold: isUnit
}
Loader {
sourceComponent: isUnit ? null : phraseProgress
}
}
}
onClicked: {
g_trainingSession.phrase = phraseModel.phrase(index)
}
Connections {
target: g_trainingSession
onPhraseChanged: {
phraseTree.expand(phraseModel.indexUnit(g_trainingSession.phrase.unit))
phraseTree.selection.setCurrentIndex(
phraseModel.indexPhrase(g_trainingSession.phrase),
ItemSelectionModel.ClearAndSelect)
}
}
}
TrainerSessionScreen {
id: trainerMain
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: Math.floor(main.width * 0.7) - 30
Layout.fillHeight: true
}
}
}
MainToolBar {
id: mainToolBar
}
ColumnLayout {
id: main
spacing: theme.spacing
anchors {
fill: parent
topMargin: mainToolBar.height + theme.spacing
leftMargin: theme.spacing
rightMargin: theme.spacing
bottomMargin: theme.spacing
}
Loader {
Layout.fillHeight: true
sourceComponent: {
g_trainingSession.language == null
? welcomeScreen
: trainingScreen
}
}
}
//TODO change to loader for arbitrary dialogs
//TODO add margin for main menu
SheetDialog {
id: editProfileDialog
anchors {
fill: main
}
content: ProfileSettingsItem {
anchors.fill: parent
id: trainingItemsPageComponent
TrainingItemsPage { }
}
Component {
id: profileSettingsPageComponent
ProfileSettingsPage { }
}
}
/*
* Copyright 2015-2016 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.5
import QtQuick.Controls 1.2
MenuBar {
id: root
Menu {
title: i18n("File")
MenuItem {
text: i18n("Edit User")
iconName: "user-properties"
onTriggered: triggerEditProfile()
}
MenuSeparator { }
MenuItem {
text: i18n("Quit")
iconName: "application-exit"
shortcut: StandardKey.Quit
onTriggered: triggerAction("file_quit")
}
}
Menu {
title: i18n("Settings")
MenuItem {
text: i18n("Download Courses")
iconName: "get-hot-new-stuff"
onTriggered: triggerDownloadCourses()
}
MenuSeparator { }
// TODO requires proper support of KKeySequenceWidget's settings
// MenuItem {
// text: i18n("Configure Shortcuts...")
// iconName: "configure-shortcuts"
// onTriggered: triggerAction("options_configure_keybinding")
// }
MenuItem {
text: i18n("Configure Artikulate...")
iconName: "settings-configure"
onTriggered: triggerSettingsDialog()
}
MenuSeparator { }
MenuItem {
text: i18n("Show Menubar")
iconName: "show-menu"
checkable: true
checked: kcfg_ShowMenuBar
onTriggered: {
switchMenuBarVisibility()
}
}
}
Menu {
title: i18n("Help")
MenuItem {
text: i18n("Artikulate Handbook")
iconName: "help-contents"
shortcut: StandardKey.HelpContents
onTriggered: triggerAction("help_contents")
}
MenuSeparator { }
MenuItem {
text: i18n("Report Bug")
iconName: "tools-report-bug"
onTriggered: triggerAction("help_report_bug")
}
MenuSeparator { }
MenuItem {
text: i18n("About Artikulate")
iconName: "artikulate"
onTriggered: triggerAction("help_about_app")
}
MenuItem {
text: i18n("About KDE")
iconName: "help-about"
onTriggered: triggerAction("help_about_kde")
}
}
}
/*
* Copyright 2013-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.2
import artikulate 1.0
ToolBar{
RowLayout {
anchors.fill: parent
Layout.fillWidth: true
Layout.preferredHeight: langIcon.height
spacing: 20
Icon {
id: langIcon
icon: "language-artikulate"
width: 48
height: 48
}
ComboBox {
id: comboLanguage
Layout.minimumWidth: 200
model: LanguageModel {
id: languageModel
resourceModel: LanguageResourceModel {
resourceManager: g_resourceManager
}
}
textRole: "title"
onCurrentIndexChanged: {
if (languageModel.language(currentIndex)) {
g_trainingSession.language = languageModel.language(currentIndex)
}
}
}
ComboBox {
id: comboCourse
enabled: {
courseFilterModel.filteredCount == 0 ? false : true
}
Layout.minimumWidth: 200
model: CourseFilterModel {
id: courseFilterModel
view: {
kcfg_UseContributorResources
? CourseFilterModel.AllResources
: CourseFilterModel.OnlyGetHotNewStuffResources
}
courseModel: CourseModel {
id: courseModel
resourceManager: g_resourceManager
language: g_trainingSession.language
onLanguageChanged: {
if (courseFilterModel.course(0)) {
g_trainingSession.course = courseFilterModel.course(0)
}
}
}
}
textRole: "title"
onCurrentIndexChanged: {
if (courseFilterModel.course(currentIndex)) {
g_trainingSession.course = courseFilterModel.course(currentIndex)
}
}
}
// horizontal fill
Item { Layout.fillWidth: true }
ToolButton {
Layout.alignment: Qt.AlignRight
iconName: "application-menu"
menu: Menu {
id: recentFilesMenu
MenuItem {
text: i18n("Download Courses")
iconName: "get-hot-new-stuff"
onTriggered: triggerDownloadCourses()
}
MenuSeparator { }
MenuItem {
text: i18n("Edit User")
iconName: "user-properties"
onTriggered: triggerEditProfile()
}
MenuSeparator { }
// TODO requires proper support of KKeySequenceWidget's settings
// MenuItem {
// text: i18n("Configure Shortcuts...")
// iconName: "configure-shortcuts"
// onTriggered: triggerAction("options_configure_keybinding")
// }
MenuItem {
text: i18n("Configure Artikulate...")
iconName: "settings-configure"
onTriggered: triggerSettingsDialog()
}
MenuSeparator { }
Menu {
title: i18n("Help")
MenuItem {
text: i18n("Artikulate Handbook")
iconName: "help-contents"
shortcut: StandardKey.HelpContents
onTriggered: triggerAction("help_contents")
}
MenuSeparator { }
MenuItem {
text: i18n("Report Bug")
iconName: "tools-report-bug"
onTriggered: triggerAction("help_report_bug")
}
MenuSeparator { }
MenuItem {
text: i18n("About Artikulate")
iconName: "artikulate"
onTriggered: triggerAction("help_about_app")
}
MenuItem {
text: i18n("About KDE")
iconName: "help-about"
onTriggered: triggerAction("help_about_kde")
}
}
MenuSeparator { }
MenuItem {
text: i18n("Show Menubar")
iconName: "show-menu"
checkable: true
checked: kcfg_ShowMenuBar
onTriggered: {
switchMenuBarVisibility()
}
}
MenuSeparator { }
MenuItem {
text: i18n("Quit")
iconName: "application-exit"
shortcut: StandardKey.Quit
onTriggered: triggerAction("file_quit")
}
}
}
}
}
/*
* Copyright 2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
import artikulate 1.0
Item {
id: root
Layout.fillWidth: true
Layout.fillHeight: true
height: 50
ColumnLayout {
id: row
Text {
text: i18n("Welcome to Artikulate!")
font.pointSize: 24
}
Text {
text: i18n("There are no courses installed on this system.")
}
Text {
text: i18n("You can install them now from the Internet:")
}
Button {
text: i18n("Download Courses")
iconName: "get-hot-new-stuff"
onClicked: triggerDownloadCourses()
}
}
}