diff --git a/CMakeLists.txt b/CMakeLists.txt index 6605209..938e4b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,74 +1,75 @@ # 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.5) 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 + Core 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 ) option(COMPILE_QML "Precompile QML code" ON) # 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(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/README.md b/README.md index 819ab4f..f452f71 100644 --- a/README.md +++ b/README.md @@ -1,101 +1,106 @@ # KTouch [![Build Status](https://build.kde.org/view/Applications/job/Applications%20ktouch%20kf5-qt5%20SUSEQt5.9/badge/icon)](https://build.kde.org/view/Applications/job/Applications%20ktouch%20kf5-qt5%20SUSEQt5.9/) KTouch is a program to learn and practice touch typing. Every finger has its place on the keyboard with associated keys to press. Starting with only a few keys to remember you will advance through different training levels where additional keys are introduced. Because you no longer need to search for the keys on the keyboard you will be able to type quickly and accurately. # Development Setup ## Building KTouch has the following build dependencies: * [CMake][cmake] ≥ 3.0.0 * [Extra CMake Modules][ecm] ≥ 1.0.0 * [Qt][qt] ≥ 5.9 with the following modules * Qt GUI * Qt QML * Qt Quick * Qt Quick Widgets * Qt Quick Controls 2 * Qt SQL * Qt Test * Qt X11 Extras * Qt XML * Qt XML Patterns * [KDE Frameworks 5][kf5] with: * Completion * Config * ConfigWidgets * CoreAddons * Declarative * DocTools * I18n * ItemViews * KCMUtils * KIO * TextWidgets * WidgetsAddons * WindowSystem * XmlGui * IconThemes - * [libxkbfile][libxkbfile] (optional, for keyboard layout auto-detection) - * [libxcb][libxcb] (optional, for keyboard layout auto-detection) + * optionally, for keyboard layout auto-detection: + * [Xlib][xlib] + * [XKB][xkb] + * [libxkbfile][libxkbfile] + * [libxcb][libxcb] with libxcb-xkb [cmake]: https://cmake.org/ [ecm]: https://cgit.kde.org/extra-cmake-modules.git/ [qt]: https://www.qt.io/ [kf5]: https://api.kde.org/frameworks/ -[libxkbfile]: https://cgit.freedesktop.org/xorg/lib/libxkbfile +[xlib]: https://tronche.com/gui/x/xlib/ +[xkb]: https://www.x.org/wiki/XKB/ +[libxkbfile]: https://gitlab.freedesktop.org/xorg/lib/libxkbfile [libxcb]: https://xcb.freedesktop.org/ Collecting and installing all dependencies by hand can be a challenge. Far easier is to use the dependency resolution of your package manager. Usually they can be instructed to install all dependencies automatically by using the information of the packaged version of KTouch: apt-get build-dep ktouch # Ubuntu, Debian, ... zypper source-install --build-deps-only ktouch # openSUSE If the build requirements are met, execute the following commands in the root directory of your working copy to built and install KTouch: mkdir build cd build cmake .. -DCMAKE_INSTALL_PREFIX=../install make make install These commands install KTouch to the directory `install` in the root of your working copy. You can install KTouch to any directory of your choice by passing a different path to `-DCMAKE_INSTALL_PREFIX`. ## Running At runtime KTouch needs the following additional software packages to be installed: * [Breeze icon set][breeze] * [kqtquickcharts][kqtquickcharts] ≥ 16.12 * [plasma-desktop][plasma-desktop] (optional, for keyboard layout configuration inside the application) [breeze]: https://phabricator.kde.org/source/breeze-icons/ [kqtquickcharts]: https://phabricator.kde.org/source/kqtquickcharts/ [plasma-desktop]: https://phabricator.kde.org/source/plasma-desktop/ KTouch needs the following environment variables to be set in order to find all its installed resources: export KDEDIRS=:$KDEDIRS export XDG_DATA_DIRS=/share:$XDG_DATA_DIRS After this, KTouch can finally be launched with: /bin/ktouch diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2293b3f..3134dc4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,162 +1,158 @@ 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") + +if (X11_FOUND AND X11_Xkbfile_FOUND AND X11_Xkb_FOUND AND XCB_FOUND AND XCB_XKB_FOUND) + set(KTOUCH_BUILD_WITH_X11 TRUE) +endif() + +add_feature_info ("Keyboard Layout Detection" KTOUCH_BUILD_WITH_X11 "needs libX11, libxkb, libxkbfile, libxcb, and libxcb-xkb") 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 AND COMPILE_QML) 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_Xkb_INCLUDE_PATH}) include_directories(${X11_Xkbfile_INCLUDE_PATH}) set(ktouch_SRCS ${ktouch_SRCS} x11_helper.cpp) -else (KTOUCH_BUILD_WITH_X11) + set(ktouch_X11_DEPS ${X11_Xkb_LIB} ${X11_LIBRARIES} XCB::XCB XCB::XKB) +else () set(ktouch_SRCS ${ktouch_SRCS} keyboardlayoutmenu.cpp) -endif (KTOUCH_BUILD_WITH_X11) +endif () kconfig_add_kcfg_files(ktouch_SRCS preferences.kcfgc) 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/src/ktouchcontext.cpp b/src/ktouchcontext.cpp index 4020fef..d001d35 100644 --- a/src/ktouchcontext.cpp +++ b/src/ktouchcontext.cpp @@ -1,212 +1,212 @@ /* * Copyright 2016 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 . */ #include "ktouchcontext.h" #include #include #include #include #include "application.h" #include "colorsconfigwidget.h" #include "editor/resourceeditor.h" #include "customlessoneditordialog.h" #include "preferences.h" #include "trainingconfigwidget.h" #include "core/lesson.h" #include #include #include #include #include #include #include #include #ifdef KTOUCH_BUILD_WITH_X11 #include "x11_helper.h" #else #include "keyboardlayoutmenu.h" #endif const QString keyboardKCMName = QStringLiteral("kcm_keyboard"); KTouchContext::KTouchContext(KMainWindow* mainWindow, QQuickView* view, QObject *parent) : QObject(parent), m_actionCollection(new KActionCollection(this)), m_menu(new QMenu(mainWindow)), m_mainWindow(mainWindow), m_view(view) { #ifdef KTOUCH_BUILD_WITH_X11 m_XEventNotifier = new XEventNotifier(); m_XEventNotifier->start(); connect(m_XEventNotifier, &XEventNotifier::layoutChanged, this, &KTouchContext::keyboardLayoutNameChanged); #else - m_keyboardLayoutMenu = new KeyboardLayoutMenu(this); + m_keyboardLayoutMenu = new KeyboardLayoutMenu(m_mainWindow); m_keyboardLayoutMenu->setDataIndex(Application::dataIndex()); connect(m_keyboardLayoutMenu, SIGNAL(keyboardLayoutNameChanged()), SIGNAL(keyboardLayoutNameChanged())); #endif init(); } KTouchContext::~KTouchContext() { #ifdef KTOUCH_BUILD_WITH_X11 m_XEventNotifier->stop(); delete m_XEventNotifier; #endif } QString KTouchContext::keyboardLayoutName() const { #ifdef KTOUCH_BUILD_WITH_X11 return X11Helper::getCurrentLayout().toString(); #else return m_keyboardLayoutMenu->keyboardLayoutName(); #endif } DataIndex* KTouchContext::dataIndex() { return Application::dataIndex(); } bool KTouchContext::keyboardKCMAvailable() { return testKCMAvailibility(keyboardKCMName); } void KTouchContext::showMenu(int xPos, int yPos) { m_menu->popup(m_view->mapToGlobal(QPoint(xPos, yPos))); } Lesson* KTouchContext::createLesson() { return new Lesson(); } void KTouchContext::showResourceEditor() { QPointer& resourceEditorRef = Application::resourceEditorRef(); if (resourceEditorRef.isNull()) { resourceEditorRef = QPointer(new ResourceEditor()); } ResourceEditor* resourceEditor = resourceEditorRef.data(); resourceEditor->show(); resourceEditor->activateWindow(); } bool KTouchContext::showCustomLessonDialog(Lesson* lesson, KeyboardLayout* keyboardLayout) { CustomLessonEditorDialog* dialog = new CustomLessonEditorDialog(m_mainWindow); dialog->setLesson(lesson); dialog->setKeyboardLayout(keyboardLayout); bool result = dialog->exec() == QDialog::Accepted; delete dialog; return result; } void KTouchContext::showConfigDialog() { if (KConfigDialog::showDialog(QStringLiteral("preferences"))) { return; } KConfigDialog* dialog = new KConfigDialog(m_mainWindow, QStringLiteral("preferences"), Preferences::self()); dialog->setFaceType(KPageDialog::List); dialog->setModal(true); dialog->addPage(new TrainingConfigWidget(), i18n("Training"), QStringLiteral("chronometer"), i18n("Training Settings")); dialog->addPage(new ColorsConfigWidget(), i18n("Colors"), QStringLiteral("preferences-desktop-color"), i18n("Color Settings")); dialog->show(); } void KTouchContext::configureShortcuts() { KShortcutsDialog::configure(m_actionCollection, KShortcutsEditor::LetterShortcutsDisallowed, m_mainWindow); } void KTouchContext::showKeyboardKCM() { QPointer kcm = new KCMultiDialog(m_mainWindow); kcm->setWindowTitle(i18n("Configure Keyboard")); kcm->addModule(keyboardKCMName); kcm->exec(); delete kcm; } void KTouchContext::setFullscreen(bool fullScreen) { KToggleFullScreenAction::setFullScreen(m_mainWindow, fullScreen); } void KTouchContext::init() { m_actionCollection->addAssociatedWidget(m_mainWindow); m_menu->addAction(KStandardAction::fullScreen(this, SLOT(setFullscreen(bool)), m_mainWindow, m_actionCollection)); m_menu->addSeparator(); QAction* editorAction = new QAction(i18n("Course and Keyboard Layout Editor..."), this); connect(editorAction, &QAction::triggered, this, &KTouchContext::showResourceEditor); m_actionCollection->addAction(QStringLiteral("editor"), editorAction); m_menu->addAction(editorAction); m_menu->addSeparator(); m_menu->addAction(KStandardAction::preferences(this, SLOT(showConfigDialog()), m_actionCollection)); m_menu->addAction(KStandardAction::keyBindings(this, SLOT(configureShortcuts()), m_actionCollection)); #ifdef KTOUCH_BUILD_WITH_X11 if (testKCMAvailibility(keyboardKCMName)) { QAction* configureKeyboardAction = new QAction(i18n("Configure Keyboard..."), this); m_menu->addAction(configureKeyboardAction); connect(configureKeyboardAction, &QAction::triggered, this, &KTouchContext::showKeyboardKCM); } #else m_menu->addMenu(m_keyboardLayoutMenu); #endif m_menu->addSeparator(); KHelpMenu* helpMenu = new KHelpMenu(m_mainWindow); m_menu->addMenu(helpMenu->menu()); } bool KTouchContext::testKCMAvailibility(const QString& name) { KService::Ptr service = KService::serviceByStorageId(name + ".desktop"); if (!service) { return false; } return service->hasServiceType(QStringLiteral("KCModule")) && !service->noDisplay(); }