diff --git a/CMakeLists.txt b/CMakeLists.txt index dcf5c70..cf6d539 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,73 +1,72 @@ # KTouch CMakeLists.txt file # # KDE Application Version, managed by release script set (KDE_APPLICATIONS_VERSION_MAJOR "19") set (KDE_APPLICATIONS_VERSION_MINOR "07") set (KDE_APPLICATIONS_VERSION_MICRO "70") set (KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}") cmake_minimum_required(VERSION 3.0) project(ktouch VERSION ${KDE_APPLICATIONS_VERSION}) find_package(ECM 1.0.0 REQUIRED NO_MODULE) find_package(KF5DocTools) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(KDEInstallDirs) include(ECMAddTests) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(ECMOptionalAddSubdirectory) include(ECMSetupVersion) include(FeatureSummary) find_package(Qt5 5.9 REQUIRED COMPONENTS Gui Qml Quick QuickWidgets QuickControls2 Sql Widgets X11Extras Xml XmlPatterns ) find_package(Qt5 CONFIG QUIET OPTIONAL_COMPONENTS QuickCompiler) find_package(KF5 REQUIRED COMPONENTS Completion Config ConfigWidgets CoreAddons Declarative DocTools I18n ItemViews KCMUtils TextWidgets WidgetsAddons WindowSystem XmlGui IconThemes ) # enable QML debugging for debug builds set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DQT_QML_DEBUG") # subdirectories to build ecm_optional_add_subdirectory(data) ecm_optional_add_subdirectory(doc) ecm_optional_add_subdirectory(src) # ecm_optional_add_subdirectory(sounds) -ecm_optional_add_subdirectory(images) ecm_optional_add_subdirectory(icons) # files to install in the ktouch project root directory install( PROGRAMS org.kde.ktouch.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) install(FILES org.kde.ktouch.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/images/CMakeLists.txt b/images/CMakeLists.txt deleted file mode 100644 index 4918ee9..0000000 --- a/images/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(image_files - accuracymeter-background.png - accuracymeter-scale.png - accuracymeter-hand.png - balloontip.svgz - charactersperminutemeter-background.png - charactersperminutemeter-scale.png - charactersperminutemeter-hand.png - elapsedtimemeter-background.png - elapsedtimemeter-minute-hand.png - elapsedtimemeter-second-hand.png - meterbox-left.png - meterbox-right.png - trainingscreen-footer.png - trainingscreen-header.png - trainingscreen-toolbar.png - trainingscreen-viewport.png - trainingscreen-viewport-shadow.png -) - -install(FILES ${image_files} DESTINATION ${DATA_INSTALL_DIR}/ktouch/images) diff --git a/images/charactersperminutemeter.svgz b/images/charactersperminutemeter.svgz deleted file mode 100644 index 3022909..0000000 Binary files a/images/charactersperminutemeter.svgz and /dev/null differ diff --git a/images/elapsedtimemeter.svgz b/images/elapsedtimemeter.svgz deleted file mode 100644 index 13809e5..0000000 Binary files a/images/elapsedtimemeter.svgz and /dev/null differ diff --git a/images/meterbox.svgz b/images/meterbox.svgz deleted file mode 100644 index e41a303..0000000 Binary files a/images/meterbox.svgz and /dev/null differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c8f70b..4c0a00b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,160 +1,162 @@ ecm_setup_version(${KDE_APPLICATIONS_VERSION} VARIABLE_PREFIX KTOUCH VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KTouchConfigVersion.cmake" ) find_package(X11) add_feature_info("X11-Xkbfile" X11_Xkbfile_FOUND "required for automatic keyboard layout detection") find_package(XCB OPTIONAL_COMPONENTS XCB XKB) add_feature_info("XCB-XKB" XCB_XKB_FOUND "required for automatic keyboard layout detection") ecm_optional_add_subdirectory(schemata) # set include directories include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${ktouch_SOURCE_DIR} ) # configure the local configuration file configure_file(ktouch_build_config.h.in ktouch_build_config.h) # set the source code files from which KTouch is compiled set(ktouch_SRCS main.cpp application.cpp mainwindow.cpp bindings/utils.cpp bindings/stringformatter.cpp declarativeitems/griditem.cpp declarativeitems/kcolorschemeproxy.cpp declarativeitems/lessonpainter.cpp declarativeitems/lessontexthighlighteritem.cpp declarativeitems/preferencesproxy.cpp declarativeitems/scalebackgrounditem.cpp declarativeitems/traininglinecore.cpp core/resource.cpp core/keyboardlayoutbase.cpp core/keyboardlayout.cpp core/abstractkey.cpp core/key.cpp core/keychar.cpp core/specialkey.cpp core/coursebase.cpp core/course.cpp core/lesson.cpp core/trainingstats.cpp core/profile.cpp core/dataindex.cpp core/dataaccess.cpp core/dbaccess.cpp core/profiledataaccess.cpp core/resourcedataaccess.cpp core/userdataaccess.cpp undocommands/coursecommands.cpp undocommands/keyboardlayoutcommands.cpp models/resourcemodel.cpp models/lessonmodel.cpp models/charactersmodel.cpp models/categorizedresourcesortfilterproxymodel.cpp models/errorsmodel.cpp models/learningprogressmodel.cpp editor/resourceeditor.cpp editor/resourceeditorwidget.cpp editor/newresourceassistant.cpp editor/resourcetypeswidget.cpp editor/newcoursewidget.cpp editor/newkeyboardlayoutwidget.cpp editor/resourcetemplatewidget.cpp editor/abstracteditor.cpp editor/courseeditor.cpp editor/keyboardlayoutcombobox.cpp editor/lessontexteditor.cpp editor/lessontexthighlighter.cpp editor/keyboardlayouteditor.cpp editor/keyboardlayouteditorview.cpp editor/keyboardlayoutpropertieswidget.cpp editor/charactersviewdelegate.cpp trainingconfigwidget.cpp colorsconfigwidget.cpp customlessoneditordialog.cpp ktouchcontext.cpp ) +qt5_add_resources(ktouch_imgs_SRCS images/images.qrc) + if (Qt5QuickCompiler_FOUND) qtquick_compiler_add_resources(ktouch_qml_SRCS qml/qml.qrc) else () qt5_add_resources(ktouch_qml_SRCS qml/qml.qrc) endif() # compile UI files ki18n_wrap_ui(ktouch_SRCS ui/colorsconfigwidget.ui ui/trainingconfigwidget.ui ui/resourceeditorwidget.ui ui/resourcetypeswidget.ui ui/newcoursewidget.ui ui/newkeyboardlayoutwidget.ui ui/resourcetemplatewidget.ui ui/courseeditor.ui ui/lessontexteditor.ui ui/keyboardlayouteditor.ui ui/keyboardlayoutpropertieswidget.ui ui/customlessoneditordialog.ui ) set (KTOUCH_BUILD_WITH_X11 X11_Xkbfile_FOUND AND XCB_XKB_FOUND AND XCB_FOUND) if (KTOUCH_BUILD_WITH_X11) add_definitions(-DKTOUCH_BUILD_WITH_X11) include_directories(${X11_Xkbfile_INCLUDE_PATH}) set(ktouch_SRCS ${ktouch_SRCS} x11_helper.cpp) else (KTOUCH_BUILD_WITH_X11) set(ktouch_SRCS ${ktouch_SRCS} keyboardlayoutmenu.cpp) endif (KTOUCH_BUILD_WITH_X11) kconfig_add_kcfg_files(ktouch_SRCS preferences.kcfgc) -add_executable(ktouch ${ktouch_SRCS} ${ktouch_qml_SRCS}) +add_executable(ktouch ${ktouch_SRCS} ${ktouch_imgs_SRCS} ${ktouch_qml_SRCS}) set(ktouch_X11_DEPS "") if (KTOUCH_BUILD_WITH_X11) set(ktouch_X11_DEPS ${X11_Xkbfile_LIB} ${X11_LIBRARIES} XCB::XCB XCB::XKB) endif (KTOUCH_BUILD_WITH_X11) #uncomment this if oxygen icons for ktouch are available target_link_libraries(ktouch LINK_PUBLIC Qt5::Qml Qt5::Quick Qt5::QuickWidgets Qt5::QuickControls2 Qt5::Sql Qt5::XmlPatterns Qt5::X11Extras KF5::Completion KF5::ConfigWidgets KF5::Declarative KF5::ItemViews KF5::XmlGui KF5::I18n KF5::KCMUtils KF5::TextWidgets KF5::WindowSystem KF5::CoreAddons KF5::IconThemes ${ktouch_X11_DEPS} ) #kde4_add_app_icon(ktouch_SRCS "${KDE4_ICON_DIR}/oxygen/*/apps/ktouch.png") #kde4_add_app_icon(ktouch_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/../icons/hi*-app-ktouch.png") install(TARGETS ktouch ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ktouch.kcfg DESTINATION ${KCFG_INSTALL_DIR}) diff --git a/images/accuracymeter-background.png b/src/images/accuracymeter-background.png similarity index 100% rename from images/accuracymeter-background.png rename to src/images/accuracymeter-background.png diff --git a/src/images/accuracymeter-background@2x.png b/src/images/accuracymeter-background@2x.png new file mode 100644 index 0000000..3532577 Binary files /dev/null and b/src/images/accuracymeter-background@2x.png differ diff --git a/images/accuracymeter-hand.png b/src/images/accuracymeter-hand.png similarity index 100% rename from images/accuracymeter-hand.png rename to src/images/accuracymeter-hand.png diff --git a/src/images/accuracymeter-hand@2x.png b/src/images/accuracymeter-hand@2x.png new file mode 100644 index 0000000..1d8f497 Binary files /dev/null and b/src/images/accuracymeter-hand@2x.png differ diff --git a/images/accuracymeter-scale.png b/src/images/accuracymeter-scale.png similarity index 100% rename from images/accuracymeter-scale.png rename to src/images/accuracymeter-scale.png diff --git a/src/images/accuracymeter-scale@2x.png b/src/images/accuracymeter-scale@2x.png new file mode 100644 index 0000000..52663bf Binary files /dev/null and b/src/images/accuracymeter-scale@2x.png differ diff --git a/images/balloontip.svgz b/src/images/balloontip.svgz similarity index 100% rename from images/balloontip.svgz rename to src/images/balloontip.svgz diff --git a/images/charactersperminutemeter-background.png b/src/images/charactersperminutemeter-background.png similarity index 100% rename from images/charactersperminutemeter-background.png rename to src/images/charactersperminutemeter-background.png diff --git a/src/images/charactersperminutemeter-background@2x.png b/src/images/charactersperminutemeter-background@2x.png new file mode 100644 index 0000000..3532577 Binary files /dev/null and b/src/images/charactersperminutemeter-background@2x.png differ diff --git a/images/charactersperminutemeter-hand.png b/src/images/charactersperminutemeter-hand.png similarity index 100% rename from images/charactersperminutemeter-hand.png rename to src/images/charactersperminutemeter-hand.png diff --git a/images/charactersperminutemeter-scale.png b/src/images/charactersperminutemeter-scale.png similarity index 100% rename from images/charactersperminutemeter-scale.png rename to src/images/charactersperminutemeter-scale.png diff --git a/src/images/charactersperminutemeter-scale@2x.png b/src/images/charactersperminutemeter-scale@2x.png new file mode 100644 index 0000000..279c821 Binary files /dev/null and b/src/images/charactersperminutemeter-scale@2x.png differ diff --git a/images/elapsedtimemeter-background.png b/src/images/elapsedtimemeter-background.png similarity index 100% rename from images/elapsedtimemeter-background.png rename to src/images/elapsedtimemeter-background.png diff --git a/src/images/elapsedtimemeter-background@2x.png b/src/images/elapsedtimemeter-background@2x.png new file mode 100644 index 0000000..f892189 Binary files /dev/null and b/src/images/elapsedtimemeter-background@2x.png differ diff --git a/images/elapsedtimemeter-minute-hand.png b/src/images/elapsedtimemeter-minute-hand.png similarity index 100% rename from images/elapsedtimemeter-minute-hand.png rename to src/images/elapsedtimemeter-minute-hand.png diff --git a/src/images/elapsedtimemeter-minute-hand@2x.png b/src/images/elapsedtimemeter-minute-hand@2x.png new file mode 100644 index 0000000..1667335 Binary files /dev/null and b/src/images/elapsedtimemeter-minute-hand@2x.png differ diff --git a/images/elapsedtimemeter-second-hand.png b/src/images/elapsedtimemeter-second-hand.png similarity index 100% rename from images/elapsedtimemeter-second-hand.png rename to src/images/elapsedtimemeter-second-hand.png diff --git a/src/images/elapsedtimemeter-second-hand@2x.png b/src/images/elapsedtimemeter-second-hand@2x.png new file mode 100644 index 0000000..29fa41a Binary files /dev/null and b/src/images/elapsedtimemeter-second-hand@2x.png differ diff --git a/src/images/images.qrc b/src/images/images.qrc new file mode 100644 index 0000000..ca4b6e1 --- /dev/null +++ b/src/images/images.qrc @@ -0,0 +1,33 @@ + + + accuracymeter-background.png + accuracymeter-hand.png + accuracymeter-scale.png + meterbox-left.png + meterbox-right.png + statusled.svgz + trainingscreen-footer.png + trainingscreen-header.png + trainingscreen-toolbar.png + trainingscreen-viewport-shadow.png + trainingscreen-viewport.png + balloontip.svgz + charactersperminutemeter-background.png + charactersperminutemeter-hand.png + charactersperminutemeter-scale.png + elapsedtimemeter-background.png + elapsedtimemeter-background@2x.png + elapsedtimemeter-minute-hand.png + elapsedtimemeter-second-hand.png + elapsedtimemeter-minute-hand@2x.png + elapsedtimemeter-second-hand@2x.png + images.qrc + meterbox-left@2x.png + meterbox-right@2x.png + accuracymeter-background@2x.png + accuracymeter-hand@2x.png + accuracymeter-scale@2x.png + charactersperminutemeter-background@2x.png + charactersperminutemeter-scale@2x.png + + diff --git a/images/meterbox-left.png b/src/images/meterbox-left.png similarity index 100% rename from images/meterbox-left.png rename to src/images/meterbox-left.png diff --git a/src/images/meterbox-left@2x.png b/src/images/meterbox-left@2x.png new file mode 100644 index 0000000..91bf079 Binary files /dev/null and b/src/images/meterbox-left@2x.png differ diff --git a/images/meterbox-right.png b/src/images/meterbox-right.png similarity index 100% rename from images/meterbox-right.png rename to src/images/meterbox-right.png diff --git a/src/images/meterbox-right@2x.png b/src/images/meterbox-right@2x.png new file mode 100644 index 0000000..ba06be2 Binary files /dev/null and b/src/images/meterbox-right@2x.png differ diff --git a/images/statusled.svgz b/src/images/statusled.svgz similarity index 100% rename from images/statusled.svgz rename to src/images/statusled.svgz diff --git a/images/accuracymeter.svgz b/src/images/templates/accuracymeter.svgz similarity index 100% rename from images/accuracymeter.svgz rename to src/images/templates/accuracymeter.svgz diff --git a/src/images/templates/charactersperminutemeter.svgz b/src/images/templates/charactersperminutemeter.svgz new file mode 100644 index 0000000..f8cc1a3 Binary files /dev/null and b/src/images/templates/charactersperminutemeter.svgz differ diff --git a/src/images/templates/elapsedtimemeter.svgz b/src/images/templates/elapsedtimemeter.svgz new file mode 100644 index 0000000..e069460 Binary files /dev/null and b/src/images/templates/elapsedtimemeter.svgz differ diff --git a/src/images/templates/meterbox.svgz b/src/images/templates/meterbox.svgz new file mode 100644 index 0000000..adf0035 Binary files /dev/null and b/src/images/templates/meterbox.svgz differ diff --git a/images/trainingscreen.svgz b/src/images/templates/trainingscreen.svgz similarity index 100% rename from images/trainingscreen.svgz rename to src/images/templates/trainingscreen.svgz diff --git a/images/trainingscreen-footer.png b/src/images/trainingscreen-footer.png similarity index 100% rename from images/trainingscreen-footer.png rename to src/images/trainingscreen-footer.png diff --git a/images/trainingscreen-header.png b/src/images/trainingscreen-header.png similarity index 100% rename from images/trainingscreen-header.png rename to src/images/trainingscreen-header.png diff --git a/images/trainingscreen-toolbar.png b/src/images/trainingscreen-toolbar.png similarity index 100% rename from images/trainingscreen-toolbar.png rename to src/images/trainingscreen-toolbar.png diff --git a/images/trainingscreen-viewport-shadow.png b/src/images/trainingscreen-viewport-shadow.png similarity index 100% rename from images/trainingscreen-viewport-shadow.png rename to src/images/trainingscreen-viewport-shadow.png diff --git a/images/trainingscreen-viewport.png b/src/images/trainingscreen-viewport.png similarity index 100% rename from images/trainingscreen-viewport.png rename to src/images/trainingscreen-viewport.png diff --git a/src/qml/common/Balloon.qml b/src/qml/common/Balloon.qml index 9e18360..bf91734 100644 --- a/src/qml/common/Balloon.qml +++ b/src/qml/common/Balloon.qml @@ -1,166 +1,166 @@ /* * Copyright 2012 Marco Martin * Copyright 2015 Sebastian Gottfried * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtGraphicalEffects 1.0 Loader { id: root property Item visualParent property string status: 'closed' default property Item data active: status != 'closed' function open() { root.status = 'loading' } function close() { root.status = 'closing' } sourceComponent: Component { MouseArea { id: dismissArea anchors.fill: parent opacity: root.active && (root.status == 'open' || root.status =='opening')? 1 : 0 layer.enabled: true layer.effect: DropShadow { anchors.fill: parent radius: 5 samples: 11 } Behavior on opacity { SequentialAnimation { NumberAnimation { duration: 250 easing.type: Easing.InOutQuad properties: "opacity" } ScriptAction { script: { root.status = root.status == 'opening' ? 'open' : 'closed' } } } } SystemPalette { id: palette colorGroup: SystemPalette.Active } Rectangle { id: internal color: palette.alternateBase radius: 5 property variant parentPos: root.visualParent? root.visualParent.mapToItem(null, 0, 0): Qt.point(0, 0) property bool under: root.visualParent ? internal.parentPos.y + root.visualParent.height + height < dismissArea.height : true // bindings don't work for anchor definition onUnderChanged: { if (under) { balloonTip.anchors.top = undefined balloonTip.anchors.bottom = balloonTip.parent.top } else { balloonTip.anchors.bottom = undefined balloonTip.anchors.top = balloonTip.parent.bottom } } property int preferedX: internal.parentPos.x - internal.width/2 + root.visualParent.width/2 x: Math.round(Math.max(radius, Math.min(dismissArea.width - internal.width - radius, preferedX))) y: { if (root.visualParent) { if (under) { Math.round(internal.parentPos.y + root.visualParent.height + balloonTip.height + radius) } else { Math.round(internal.parentPos.y - internal.height - balloonTip.height - radius) } } else { Math.round(dismissArea.height/2 - internal.height/2) } } width: contentItem.width + 2 * internal.radius height: contentItem.height + 2 * internal.radius Rectangle { id: balloonTip color: internal.color anchors { horizontalCenter: parent.horizontalCenter horizontalCenterOffset: internal.preferedX - internal.x top: parent.bottom } width: 10 height: 10 visible: false } Image { id: balloonTipMask anchors.fill: balloonTip visible: false - source: utils.findImage("balloontip.svgz") + source: "qrc:///ktouch/images/balloontip.svgz" sourceSize: Qt.size(width, height) } OpacityMask { anchors.fill: balloonTip visible: root.visualParent != null source: balloonTip maskSource: balloonTipMask rotation: internal.under? 0: 180 } Item { id: contentItem x: internal.radius y: internal.radius width: childrenRect.width height: childrenRect.height + 2 data: root.data } } onClicked: { root.close() } Component.onCompleted: { var candidate = root while (candidate.parent.parent) { candidate = candidate.parent } if (candidate) { dismissArea.parent = candidate } root.status = 'opening' } } } } diff --git a/src/qml/meters/AccuracyMeter.qml b/src/qml/meters/AccuracyMeter.qml index f8b00db..91fdc05 100644 --- a/src/qml/meters/AccuracyMeter.qml +++ b/src/qml/meters/AccuracyMeter.qml @@ -1,90 +1,90 @@ /* * Copyright 2012 Sebastian Gottfried * Copyright 2015 Sebastian Gottfried * * 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) 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 . */ import QtQuick 2.9 import ktouch 1.0 Meter { id: meter property real accuracy: 1.0 property real referenceAccuracy: 1.0 label: i18n("Accuracy") value: strFormatter.formatAccuracy(meter.accuracy) referenceValue: strFormatter.formatAccuracyDiff(meter.referenceAccuracy, meter.accuracy) valueStatus: Math.round(1000 * meter.accuracy) >= Math.round(10 * preferences.requiredAccuracy)? "good": "bad" analogPartContent: Image { anchors.centerIn: parent - source: utils.findImage("accuracymeter-background.png") + source: "qrc:///ktouch/images/accuracymeter-background.png" ScaleBackgroundItem { anchors.centerIn: parent anchors.verticalCenterOffset: 25 width: scale.width height: scale.height startAngle: Math.min(135, Math.max(45, 135 - (preferences.requiredAccuracy - 90) * 9)) stopAngle: 45 scaleMarkHeight: 8 color: "#88ff00"; } Image { id: scale anchors.centerIn: parent anchors.verticalCenterOffset: 25 - source: utils.findImage("accuracymeter-scale.png") + source: "qrc:///ktouch/images/accuracymeter-scale.png" } Text { anchors { verticalCenter: parent.verticalCenter left: parent.left leftMargin: 20 } text: "90" font.pixelSize: 10 } Text { anchors { verticalCenter: parent.verticalCenter right: parent.right rightMargin: 20 } text: "100" font.pixelSize: 10 } Image { id: hand anchors.centerIn: parent anchors.verticalCenterOffset: 25 - source: utils.findImage("accuracymeter-hand.png") + source: "qrc:///ktouch/images/accuracymeter-hand.png" transform: Rotation { origin.x: hand.width / 2 origin.y: hand.height / 2 angle: Math.min(90, Math.max(0, accuracy - 0.9) * 900) Behavior on angle { SpringAnimation { spring: 2; damping: 0.2; modulus: 360; mass: 0.75} } } } } } diff --git a/src/qml/meters/CharactersPerMinuteMeter.qml b/src/qml/meters/CharactersPerMinuteMeter.qml index 2762042..7596ec6 100644 --- a/src/qml/meters/CharactersPerMinuteMeter.qml +++ b/src/qml/meters/CharactersPerMinuteMeter.qml @@ -1,94 +1,94 @@ /* * Copyright 2012 Sebastian Gottfried * Copyright 2015 Sebastian Gottfried * * 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) 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 . */ import QtQuick 2.9 import ktouch 1.0 Meter { id: meter property int charactersPerMinute: 0 property int referenceCharactersPerMinute: 0 property int minimumCharactersPerMinute: preferences.requiredStrokesPerMinute property int diff: meter.charactersPerMinute - meter.referenceCharactersPerMinute label: i18n("Characters per Minute") value: meter.charactersPerMinute referenceValue: strFormatter.formatSign(diff) + " " + (diff > 0? diff: -diff) valueStatus: meter.charactersPerMinute >= minimumCharactersPerMinute? "good": "bad" analogPartContent: Image { anchors.centerIn: parent - source: utils.findImage("charactersperminutemeter-background.png") + source: "qrc:///ktouch/images/charactersperminutemeter-background.png" ScaleBackgroundItem { anchors.centerIn: parent anchors.verticalCenterOffset: 25 width: scale.width height: scale.height startAngle: Math.min(135, Math.max(45, 135 - (minimumCharactersPerMinute * 90 / 360))) stopAngle: 45 scaleMarkHeight: 8 color: "#88ff00"; } Image { id: scale anchors.centerIn: parent anchors.verticalCenterOffset: 25 - source: utils.findImage("charactersperminutemeter-scale.png") + source: "qrc:///ktouch/images/charactersperminutemeter-scale.png" } Text { anchors { verticalCenter: parent.verticalCenter left: parent.left leftMargin: 20 } text: "0" font.pixelSize: 10 } Text { anchors { verticalCenter: parent.verticalCenter right: parent.right rightMargin: 20 } text: "360" font.pixelSize: 10 } Image { id: hand anchors.centerIn: parent anchors.verticalCenterOffset: 25 - source: utils.findImage("charactersperminutemeter-hand.png") + source: "qrc:///ktouch/images/charactersperminutemeter-hand.png" smooth: true transform: Rotation { origin.x: hand.width / 2 origin.y: hand.height / 2 angle: Math.min(90, charactersPerMinute * 90 / 360) Behavior on angle { SpringAnimation { spring: 2; damping: 0.2; modulus: 360; mass: 0.75} } } } } } diff --git a/src/qml/meters/ElapsedTimeMeter.qml b/src/qml/meters/ElapsedTimeMeter.qml index 585ffe1..c2c74ff 100644 --- a/src/qml/meters/ElapsedTimeMeter.qml +++ b/src/qml/meters/ElapsedTimeMeter.qml @@ -1,66 +1,66 @@ /* * Copyright 2012 Sebastian Gottfried * Copyright 2015 Sebastian Gottfried * * 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) 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 . */ import QtQuick 2.9 import ktouch 1.0 Meter { id: meter property variant elapsedTime property variant referenceElapsedTime label: i18n("Elapsed time") value: strFormatter.formatTime(meter.elapsedTime) referenceValue: strFormatter.formatTimeDiff(meter.referenceElapsedTime, meter.elapsedTime) positiveDiffIsGood: false analogPartContent: Image { anchors.centerIn: parent - source: utils.findImage("elapsedtimemeter-background.png") + source: "qrc:///ktouch/images/elapsedtimemeter-background.png" Image { id: minuteHand anchors.centerIn: parent - source: utils.findImage("elapsedtimemeter-minute-hand.png") + source: "qrc:///ktouch/images/elapsedtimemeter-minute-hand.png" smooth: true transform: Rotation { origin.x: minuteHand.width / 2 origin.y: minuteHand.height / 2 angle: elapsedTime? 6 * utils.getMinutesOfQTime(elapsedTime): 0 Behavior on angle { SpringAnimation { spring: 2; damping: 0.2; modulus: 360; mass: 0.75} } } } Image { id: secondHand anchors.centerIn: parent - source: utils.findImage("elapsedtimemeter-second-hand.png") + source: "qrc:///ktouch/images/elapsedtimemeter-second-hand.png" transform: Rotation { origin.x: secondHand.width / 2 origin.y: secondHand.height / 2 angle: elapsedTime? 6 * utils.getSecondsOfQTime(elapsedTime): 0 Behavior on angle { SpringAnimation { spring: 2; damping: 0.2; modulus: 360; mass: 0.75} } } } } } diff --git a/src/qml/meters/Meter.qml b/src/qml/meters/Meter.qml index d01569c..92f0583 100644 --- a/src/qml/meters/Meter.qml +++ b/src/qml/meters/Meter.qml @@ -1,121 +1,121 @@ /* * Copyright 2012 Sebastian Gottfried * Copyright 2015 Sebastian Gottfried * * 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) 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 . */ import QtQuick 2.9 import QtQuick.Layouts 1.3 RowLayout { id: meter property alias label: label.text property alias value: value.text; property alias referenceValue: referenceValue.text property bool positiveDiffIsGood: true property string valueStatus: "none" property alias analogPartContent: analogPart.data height: 112 width: 304 spacing: 0 BorderImage { id: analogPart Layout.preferredWidth: height Layout.fillHeight: true border { left: 6 top: 6 right:6 bottom: 6 } - source: utils.findImage("meterbox-left.png") + source: "qrc:///ktouch/images/meterbox-left.png" } BorderImage { id: digitalPart Layout.fillHeight: true Layout.fillWidth: true border { left: 6 top: 6 right:6 bottom: 6 } - source: utils.findImage("meterbox-right.png") + source: "qrc:///ktouch/images/meterbox-right.png" Column { anchors { verticalCenter: parent.verticalCenter left: parent.left leftMargin: 12 right: parent.right rightMargin: 12 } spacing: 0 Row { width: parent.width spacing: 5 Text { id: label width: Math.min(implicitWidth, parent.width - statusLed.width - parent.spacing) color: "#555" font.pixelSize: 15 elide: Text.ElideRight } Rectangle { id: statusLed height: 15 width: 15 radius: height / 2 visible: valueStatus !== "none" color: valueStatus === "good"? "#88ff00": "#424b35" onColorChanged: statusLedAnimaton.restart() SequentialAnimation { id: statusLedAnimaton NumberAnimation { target: statusLed; property: "scale"; to: 1.3; duration: 150; easing.type: Easing.InOutQuad } NumberAnimation { target: statusLed; property: "scale"; to: 1.0; duration: 150; easing.type: Easing.InOutQuad } } } } Text { id: value font.pixelSize: 30 font.bold: true } Text { id: referenceValue font.pixelSize: 15 color: { if (text[0] === "+") return positiveDiffIsGood? "#006E28": "#BF0303" if (text[0] === "-") return positiveDiffIsGood? "#BF0303": "#006E28" return "#555" } } } } } diff --git a/src/qml/trainingscreen/TrainingScreen.qml b/src/qml/trainingscreen/TrainingScreen.qml index 5da2b6d..20a060e 100644 --- a/src/qml/trainingscreen/TrainingScreen.qml +++ b/src/qml/trainingscreen/TrainingScreen.qml @@ -1,333 +1,333 @@ /* * Copyright 2018 Sebastian Gottfried * * 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) 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 . */ import QtQuick 2.9 import QtQuick.Layouts 1.3 import ktouch 1.0 import "../common" import "../keyboard" import "../meters" FocusScope { id: screen property KeyboardLayout keyboardLayout property Profile profile property Course course property Lesson lesson property alias stats: stats property alias referenceStats: referenceStats signal restartRequested() signal abortRequested() signal finished() property bool trainingStarted: false property bool trainingFinished: true property bool isActive: Qt.application.active function setLessonKeys() { if (!lesson) return; var chars = lesson.characters; var keyItems = keyboard.keyItems() var modifierItems = [] var usedModifiers = {} for (var i = 0; i < keyItems.length; i++) { var key = keyItems[i].key if (key.keyType() == "key") { keyItems[i].enabled = false; for (var j = 0; j < key.keyCharCount; j++) { var keyChar = key.keyChar(j) if (chars.indexOf(keyChar.value) != -1) { keyItems[i].enabled = true; if (keyChar.modifier !== "") { usedModifiers[keyChar.modifier] = true } } } } else { var type = keyItems[i].key.type if (type != SpecialKey.Return && type != SpecialKey.Backspace && type != SpecialKey.Space) { modifierItems.push(keyItems[i]) keyItems[i].enabled = false } else if (type == SpecialKey.Return && preferences.nextLineWithSpace) { keyItems[i].enabled = false } } } for (i = 0; i < modifierItems.length; i++) { var modifierItem = modifierItems[i] modifierItem.enabled = !!usedModifiers[modifierItem.key.modifierId] } } function reset() { toolbar.reset() trainingWidget.reset() screen.trainingStarted = false screen.trainingFinished = true profileDataAccess.loadReferenceTrainingStats(referenceStats, screen.profile, screen.course.id, screen.lesson.id) profileDataAccess.saveCourseProgress(lesson.id, profile, course.id, ProfileDataAccess.LastSelectedLesson) } function start() { screen.trainingFinished = false screen.trainingStarted = true } function forceActiveFocus() { trainingWidget.forceActiveFocus() } onLessonChanged: setLessonKeys() onIsActiveChanged: { if (!screen.isActive) { stats.stopTraining() } } KColorScheme { id: colorScheme colorGroup: KColorScheme.Active colorSet: KColorScheme.Complementary } TrainingStats { id: stats onTimeIsRunningChanged: { if (timeIsRunning) { screen.trainingStarted = false } } } TrainingStats { id: referenceStats } Shortcut { sequence: "Escape" enabled: screen.visible onActivated: { if (!menu.visible) { menu.open() } } } ColumnLayout { id: screenContent anchors.fill: parent spacing: 0 BorderImage { Layout.fillWidth: true Layout.preferredHeight: 41 border { top: 1 bottom: 1 } cache: false - source: utils.findImage("trainingscreen-toolbar.png") + source: "qrc:///ktouch/images/trainingscreen-toolbar.png" horizontalTileMode: BorderImage.Repeat verticalTileMode: BorderImage.Repeat TrainingScreenToolbar { id: toolbar anchors.fill: parent trainingStarted: screen.trainingStarted trainingFinished: screen.trainingFinished stats: stats menu: menu } } BorderImage { id: header Layout.fillWidth: true Layout.preferredHeight: visible? 130: 0 visible: preferences.showStatistics border { top: 1 bottom: 1 } - source: utils.findImage("trainingscreen-header.png") + source: "qrc:///ktouch/images/trainingscreen-header.png" cache: false StatBox { anchors.centerIn: parent width: parent.width - 60 stats: stats referenceStats: referenceStats } } BorderImage { id: body Layout.fillWidth: true Layout.fillHeight: true border { top: 1 bottom: 1 } - source: utils.findImage("trainingscreen-viewport.png") + source: "qrc:///ktouch/images/trainingscreen-viewport.png" cache: false TrainingWidget { id: trainingWidget anchors.fill: parent lesson: screen.lesson keyboardLayout: screen.keyboardLayout trainingStats: stats overlayContainer: trainingOverlayContainer onKeyPressed: keyboard.handleKeyPress(event) onKeyReleased: keyboard.handleKeyRelease(event) onNextCharChanged: keyboard.updateKeyHighlighting() onIsCorrectChanged: keyboard.updateKeyHighlighting() onFinished: { profileDataAccess.saveTrainingStats(stats, screen.profile, screen.course.id, screen.lesson.id) screen.finished(stats) screen.trainingFinished = true } } BorderImage { anchors.fill: parent border { top: 3 bottom: 3 } - source: utils.findImage("trainingscreen-viewport-shadow.png") + source: "qrc:///ktouch/images/trainingscreen-viewport-shadow.png" cache: false } } BorderImage { id: footer visible: preferences.showKeyboard Layout.fillWidth: true Layout.preferredHeight: visible? screen.keyboardLayout.isValid? Math.round(Math.min((parent.height - toolbar.height - header.height) / 2, parent.width / keyboard.aspectRatio)): keyboardUnavailableNotice.height: 0 border { top: 1 bottom: 1 } - source: utils.findImage("trainingscreen-footer.png") + source: "qrc:///ktouch/images/trainingscreen-footer.png" cache: false Keyboard { id: keyboard property variant highlightedKeys: [] function highlightKey(which) { for (var i = 0; i < highlightedKeys.length; i++) highlightedKeys[i].isHighlighted = false var keys = findKeyItems(which) var newHighlightedKeys = [] for (var index = 0; index < keys.length ; index++) { var key = keys[index] if (key) { key.isHighlighted = true newHighlightedKeys.push(key) if (typeof which == "string") { for (var i = 0; i < key.key.keyCharCount; i++) { var keyChar = key.key.keyChar(i) if (keyChar.value == which && keyChar.modifier != "") { var modifier = findModifierKeyItem(keyChar.modifier) if (modifier) { modifier.isHighlighted = true newHighlightedKeys.push(modifier) } break } } } } } highlightedKeys = newHighlightedKeys } function updateKeyHighlighting() { if (!visible) return; if (trainingWidget.isCorrect) { if (trainingWidget.nextChar !== "") { highlightKey(trainingWidget.nextChar) } else { highlightKey(preferences.nextLineWithSpace? Qt.Key_Space: Qt.Key_Return) } } else { highlightKey(Qt.Key_Backspace) } } keyboardLayout: screen.keyboardLayout anchors { fill: parent leftMargin: 30 rightMargin: 30 topMargin: 10 bottomMargin: 10 } onKeyboardUpdate: { setLessonKeys() highlightedKeys = [] updateKeyHighlighting() } } KeyboardUnavailableNotice { id: keyboardUnavailableNotice colorScheme: colorScheme visible: !screen.keyboardLayout.isValid width: parent.width } } } Item { id: trainingOverlayContainer anchors.fill: parent } TrainingScreenMenu { id: menu onClosed: trainingWidget.forceActiveFocus() onRestartRequested: screen.restartRequested() onAbortRequested: screen.abortRequested() } }