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()
}
}