diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40c8994..fc28c33 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,156 +1,157 @@ 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_SRCS qml/qml.qrc) # 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}) 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::Script 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/application.cpp b/src/application.cpp index c0ed281..0c2c59a 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1,161 +1,163 @@ /* * Copyright 2012 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 "application.h" #include #include #include #include #include #include #include #include #include #include #include "bindings/utils.h" #include "bindings/stringformatter.h" #include "declarativeitems/griditem.h" #include "declarativeitems/kcolorschemeproxy.h" #include "declarativeitems/lessonpainter.h" +#include "declarativeitems/lessontexthighlighteritem.h" #include "declarativeitems/preferencesproxy.h" #include "declarativeitems/scalebackgrounditem.h" #include "declarativeitems/traininglinecore.h" #include "core/keyboardlayout.h" #include "core/key.h" #include "core/specialkey.h" #include "core/keychar.h" #include "core/course.h" #include "core/lesson.h" #include "core/profile.h" #include "core/trainingstats.h" #include "core/dataindex.h" #include "core/dataaccess.h" #include "core/profiledataaccess.h" #include "models/resourcemodel.h" #include "models/lessonmodel.h" #include "models/categorizedresourcesortfilterproxymodel.h" #include "models/learningprogressmodel.h" #include "models/errorsmodel.h" Application::Application(int& argc, char** argv, int flags): QApplication(argc, argv, flags), m_dataIndex(new DataIndex(this)) { registerQmlTypes(); migrateKde4Files(); QIcon::setThemeName("breeze"); QQuickStyle::setStyle("Default"); DataAccess dataAccess; dataAccess.loadDataIndex(m_dataIndex); } DataIndex* Application::dataIndex() { Application* app = qobject_cast(QCoreApplication::instance()); return app->m_dataIndex; } QPointer& Application::resourceEditorRef() { Application* app = qobject_cast(QCoreApplication::instance()); return app->m_resourceEditorRef; } void Application::setupDeclarativeBindings(QQmlEngine* qmlEngine) { KDeclarative::KDeclarative kDeclarative; kDeclarative.setDeclarativeEngine(qmlEngine); kDeclarative.setupBindings(); Application* app = static_cast(Application::instance()); foreach (const QString& path, app->m_qmlImportPaths) { qmlEngine->addImportPath(path); } QQmlContext* rootContext = qmlEngine->rootContext(); rootContext->setContextProperty("utils", new Utils()); rootContext->setContextProperty("strFormatter", new StringFormatter()); } QStringList& Application::qmlImportPaths() { return m_qmlImportPaths; } void Application::registerQmlTypes() { qmlRegisterType("ktouch", 1, 0, "KeyboardLayout"); qmlRegisterType("ktouch", 1, 0, "AbstractKey"); qmlRegisterType("ktouch", 1, 0, "Key"); qmlRegisterType("ktouch", 1, 0, "SpecialKey"); qmlRegisterType("ktouch", 1, 0, "KeyChar"); qmlRegisterType("ktouch", 1, 0, "Course"); qmlRegisterType("ktouch", 1, 0, "Lesson"); qmlRegisterType("ktouch", 1, 0, "TrainingStats"); qmlRegisterType("ktouch", 1, 0, "Profile"); qmlRegisterType("ktouch", 1, 0, "DataIndex"); qmlRegisterType("ktouch", 1, 0, "DataIndexCourse"); qmlRegisterType("ktouch", 1, 0, "DataIndexKeyboardLayout"); qmlRegisterType("ktouch", 1, 0, "Preferences"); qmlRegisterType("ktouch", 1, 0, "DataAccess"); qmlRegisterType("ktouch", 1, 0, "ProfileDataAccess"); qmlRegisterType("ktouch", 1, 0, "ResourceModel"); qmlRegisterType("ktouch", 1, 0, "LessonModel"); qmlRegisterType("ktouch", 1, 0, "CategorizedResourceSortFilterProxyModel"); qmlRegisterType("ktouch", 1, 0, "LearningProgressModel"); qmlRegisterType("ktouch", 1, 0, "ErrorsModel"); qmlRegisterType("ktouch", 1, 0 , "LineGrid"); qmlRegisterType("ktouch", 1, 0, "ScaleBackgroundItem"); qmlRegisterType("ktouch", 1, 0, "LessonPainter"); + qmlRegisterType("ktouch", 1, 0, "LessonTextHighlighter"); qmlRegisterType("ktouch", 1, 0, "TrainingLineCore"); qmlRegisterType("ktouch", 1, 0, "KColorScheme"); } void Application::migrateKde4Files() { QStringList configFiles; configFiles << QLatin1String("ktouchrc"); Kdelibs4ConfigMigrator confMigrator(QLatin1String("ktouch")); confMigrator.setConfigFiles(configFiles); confMigrator.migrate(); Kdelibs4Migration migration; const QDir dataDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); if (!dataDir.exists()) { dataDir.mkpath(dataDir.path()); } const QString dbPath = dataDir.filePath("profiles.db"); const QString oldDbPath = migration.locateLocal("data", QStringLiteral("ktouch/profiles.db")); if (!QFile(dbPath).exists() && !oldDbPath.isEmpty()) { QFile(oldDbPath).copy(dbPath); } } diff --git a/src/declarativeitems/lessontexthighlighteritem.cpp b/src/declarativeitems/lessontexthighlighteritem.cpp new file mode 100644 index 0000000..e8d46f5 --- /dev/null +++ b/src/declarativeitems/lessontexthighlighteritem.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2017 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 "lessontexthighlighteritem.h" + +#include + +#include "editor/lessontexthighlighter.h" + +LessonTextHighlighterItem::LessonTextHighlighterItem(): + m_highligher(new LessonTextHighlighter(this)) +{ +} + +QString LessonTextHighlighterItem::allowedCharacters() const +{ + return m_highligher->allowedCharacters(); +} + +void LessonTextHighlighterItem::setAllowedCharacters(const QString& characters) +{ + if (characters != m_highligher->allowedCharacters()) + { + m_highligher->setAllowedCharacters(characters); + emit allowedCharactersChanged(); + } +} + +QQuickTextDocument* LessonTextHighlighterItem::document() const +{ + return m_document; +} + +void LessonTextHighlighterItem::setDocument(QQuickTextDocument* document) +{ + if (document != m_document) + { + m_document = document; + if (document != nullptr) + { + m_highligher->setDocument(document->textDocument()); + } + else + { + m_highligher->setDocument(nullptr); + } + emit documentChanged(); + } +} diff --git a/src/declarativeitems/lessontexthighlighteritem.h b/src/declarativeitems/lessontexthighlighteritem.h new file mode 100644 index 0000000..9a6a4c1 --- /dev/null +++ b/src/declarativeitems/lessontexthighlighteritem.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 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 . + */ + +#ifndef LESSONTEXTHIGHLIGHTERITEM_H +#define LESSONTEXTHIGHLIGHTERITEM_H + +#include + +class LessonTextHighlighter; +class QQuickTextDocument; + +class LessonTextHighlighterItem : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QString allowedCharacters READ allowedCharacters WRITE setAllowedCharacters NOTIFY allowedCharactersChanged) + Q_PROPERTY(QQuickTextDocument* document READ document WRITE setDocument NOTIFY documentChanged) +public: + LessonTextHighlighterItem(); + QString allowedCharacters() const; + void setAllowedCharacters(const QString& characters); + QQuickTextDocument* document() const; + void setDocument(QQuickTextDocument* document); +signals: + void allowedCharactersChanged(); + void documentChanged(); +private: + LessonTextHighlighter* m_highligher; + QQuickTextDocument* m_document; +}; + +#endif // LESSONTEXTHIGHLIGHTERITEM_H diff --git a/src/editor/lessontexthighlighter.cpp b/src/editor/lessontexthighlighter.cpp index c054c9a..90ee31e 100644 --- a/src/editor/lessontexthighlighter.cpp +++ b/src/editor/lessontexthighlighter.cpp @@ -1,83 +1,84 @@ /* * Copyright 2012 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 "lessontexthighlighter.h" #include LessonTextHighlighter::LessonTextHighlighter(QObject* parent): - QSyntaxHighlighter(parent) + QSyntaxHighlighter(parent), + m_maximumLineLength(60) { KColorScheme inactiveScheme(QPalette::Inactive, KColorScheme::View); KColorScheme activeScheme(QPalette::Active, KColorScheme::View); m_overLongLineFormat.setForeground(inactiveScheme.foreground(KColorScheme::InactiveText)); m_overLongLineFormat.setBackground(inactiveScheme.background(KColorScheme::NegativeBackground)); m_invalidCharFormat.setForeground(activeScheme.background(KColorScheme::NeutralBackground)); m_invalidCharFormat.setBackground(activeScheme.foreground(KColorScheme::NegativeText)); m_invalidCharFormat.setFontWeight(QFont::Bold); } QString LessonTextHighlighter::allowedCharacters() const { return m_allowedCharacters; } void LessonTextHighlighter::setAllowedCharacters(const QString& characters) { if (characters != m_allowedCharacters) { m_allowedCharacters = characters; rehighlight(); }; } int LessonTextHighlighter::maximumLineLength() const { return m_maximumLineLength; } void LessonTextHighlighter::setMaximumLineLength(int length) { if (length != m_maximumLineLength) { m_maximumLineLength = length; rehighlight(); } } void LessonTextHighlighter::highlightBlock(const QString& text) { const QLatin1Char space(32); - if (text.length() > 60) + if (text.length() > m_maximumLineLength) { - setFormat(60, text.length() - 60, m_overLongLineFormat); + setFormat(m_maximumLineLength, text.length() - m_maximumLineLength, m_overLongLineFormat); } if (m_allowedCharacters.isNull()) return; for (int i = 0; i < text.length(); i++) { const QChar c = text.at(i); if (c != space && !m_allowedCharacters.contains(c)) { setFormat(i, 1, m_invalidCharFormat); } } } diff --git a/src/qml/homescreen/LessonEditorDialog.qml b/src/qml/homescreen/LessonEditorDialog.qml index a810386..7e07eb3 100644 --- a/src/qml/homescreen/LessonEditorDialog.qml +++ b/src/qml/homescreen/LessonEditorDialog.qml @@ -1,105 +1,110 @@ /* * Copyright 2017 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.6 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.2 import ktouch 1.0 import '../common' PopupDialog { id: root property Lesson lesson: Lesson {} property KeyboardLayout keyboardLayout: KeyboardLayout {} property Profile profile: Profile {} onClosed: { profileDataAccess.storeCustomLesson(root.lesson, root.profile, root.keyboardLayout.name) } title: i18n("Edit lesson") margins: { left: 40 bottom: 40 right: 40 top: 40 } width: parent.width - leftMargin - rightMargin height: parent.height - topMargin - bottomMargin padding: titleLabel.font.pixelSize contentItem: GridLayout { columnSpacing: titleLabel.font.pixelSize rowSpacing: titleLabel.font.pixelSize Label { id: titleLabel text: i18n("Title:") Layout.row: 0 Layout.column: 0 } TextField { id: titleTextField text: root.lesson? root.lesson.title: "" onTextChanged: { if (root.lesson) { root.lesson.title = text } } Layout.row: 0 Layout.column: 1 Layout.fillWidth: true } ScrollView { Layout.row: 1 Layout.column: 0 Layout.columnSpan: 2 Layout.fillHeight: true Layout.fillWidth: true TextArea { id: lessonTextArea text: root.lesson? root.lesson.text: "" onTextChanged: { if (root.lesson) { root.lesson.text = text } } placeholderText: i18n("Lesson text") font.family: "monospace" + + LessonTextHighlighter { + document: lessonTextArea.textDocument + allowedCharacters: root.visible? keyboardLayout.allCharacters(): "" + } } } } footer: IconButton { text: i18n("Done") icon: "dialog-ok" bgColor: colorScheme.positiveBackground onClicked: { root.close() } } }