From b992ae0fa4d792002ffae10a9ef893ef4fa42ac4 Mon Sep 17 00:00:00 2001 From: rtk0c Date: Fri, 1 Jul 2022 18:12:31 +0000 Subject: Convert hardcoding files in CMakeLists.txt to file(GLOB) git-svn-id: file:///home/arch/svn/epistmool/trunk@8 71f44415-077c-4ad7-a976-72ddbf76608f --- ui.qt/CMakeLists.txt | 23 ++---- ui.qt/qml/Document.qml | 163 +++++++++++++++++++++++++++++++++++++ ui.qt/qml/GoToKnowledge.qml | 4 + ui.qt/qml/MainWindow.qml | 21 +++++ ui.qt/qml/Navigator.qml | 36 ++++++++ ui.qt/source/DatabaseClient.cpp | 5 -- ui.qt/source/DatabaseClient.hpp | 7 -- ui.qt/source/DatabaseServer.cpp | 5 -- ui.qt/source/DatabaseServer.hpp | 7 -- ui.qt/source/Document.cpp | 152 ---------------------------------- ui.qt/source/Document.hpp | 72 ---------------- ui.qt/source/Keyword.cpp | 10 --- ui.qt/source/Keyword.hpp | 26 ------ ui.qt/source/KnowledgeFragment.cpp | 11 --- ui.qt/source/KnowledgeFragment.hpp | 38 --------- ui.qt/source/fwd.hpp | 13 --- ui.qt/source/main.cpp | 35 -------- ui.qt/source/qml/Document.qml | 163 ------------------------------------- ui.qt/source/qml/GoToKnowledge.qml | 4 - ui.qt/source/qml/MainWindow.qml | 21 ----- ui.qt/source/qml/Navigator.qml | 36 -------- ui.qt/src/DatabaseClient.cpp | 5 ++ ui.qt/src/DatabaseClient.hpp | 7 ++ ui.qt/src/DatabaseServer.cpp | 5 ++ ui.qt/src/DatabaseServer.hpp | 7 ++ ui.qt/src/Document.cpp | 152 ++++++++++++++++++++++++++++++++++ ui.qt/src/Document.hpp | 72 ++++++++++++++++ ui.qt/src/Keyword.cpp | 10 +++ ui.qt/src/Keyword.hpp | 26 ++++++ ui.qt/src/KnowledgeFragment.cpp | 11 +++ ui.qt/src/KnowledgeFragment.hpp | 38 +++++++++ ui.qt/src/fwd.hpp | 13 +++ ui.qt/src/main.cpp | 35 ++++++++ 33 files changed, 613 insertions(+), 620 deletions(-) create mode 100644 ui.qt/qml/Document.qml create mode 100644 ui.qt/qml/GoToKnowledge.qml create mode 100644 ui.qt/qml/MainWindow.qml create mode 100644 ui.qt/qml/Navigator.qml delete mode 100644 ui.qt/source/DatabaseClient.cpp delete mode 100644 ui.qt/source/DatabaseClient.hpp delete mode 100644 ui.qt/source/DatabaseServer.cpp delete mode 100644 ui.qt/source/DatabaseServer.hpp delete mode 100644 ui.qt/source/Document.cpp delete mode 100644 ui.qt/source/Document.hpp delete mode 100644 ui.qt/source/Keyword.cpp delete mode 100644 ui.qt/source/Keyword.hpp delete mode 100644 ui.qt/source/KnowledgeFragment.cpp delete mode 100644 ui.qt/source/KnowledgeFragment.hpp delete mode 100644 ui.qt/source/fwd.hpp delete mode 100644 ui.qt/source/main.cpp delete mode 100644 ui.qt/source/qml/Document.qml delete mode 100644 ui.qt/source/qml/GoToKnowledge.qml delete mode 100644 ui.qt/source/qml/MainWindow.qml delete mode 100644 ui.qt/source/qml/Navigator.qml create mode 100644 ui.qt/src/DatabaseClient.cpp create mode 100644 ui.qt/src/DatabaseClient.hpp create mode 100644 ui.qt/src/DatabaseServer.cpp create mode 100644 ui.qt/src/DatabaseServer.hpp create mode 100644 ui.qt/src/Document.cpp create mode 100644 ui.qt/src/Document.hpp create mode 100644 ui.qt/src/Keyword.cpp create mode 100644 ui.qt/src/Keyword.hpp create mode 100644 ui.qt/src/KnowledgeFragment.cpp create mode 100644 ui.qt/src/KnowledgeFragment.hpp create mode 100644 ui.qt/src/fwd.hpp create mode 100644 ui.qt/src/main.cpp diff --git a/ui.qt/CMakeLists.txt b/ui.qt/CMakeLists.txt index c235133..f59962f 100644 --- a/ui.qt/CMakeLists.txt +++ b/ui.qt/CMakeLists.txt @@ -5,27 +5,20 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(Qt6 6.2 COMPONENTS Network Widgets Quick REQUIRED) +find_package(Qt6 6.3 COMPONENTS Network Widgets Quick REQUIRED) +file(GLOB_RECURSE appEpistmoolUI_SRC_HPP_FILES src/*.hpp) +file(GLOB_RECURSE appEpistmoolUI_SRC_CPP_FILES src/*.cpp) qt_add_executable(appEpistmoolUI - source/main.cpp - source/fwd.hpp - source/DatabaseClient.hpp source/DatabaseClient.cpp - source/DatabaseServer.hpp source/DatabaseServer.cpp - source/KnowledgeFragment.hpp source/KnowledgeFragment.cpp - source/Keyword.hpp source/Keyword.cpp + ${appEpistmoolUI_SRC_HPP_FILES} + ${appEpistmoolUI_SRC_CPP_FILES} ) +file(GLOB_RECURSE appEpistmoolUI_QML_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} qml/*.qml) qt_add_qml_module(appEpistmoolUI URI EpistmoolUI VERSION 1.0 - SOURCES - source/Document.hpp source/Document.cpp - QML_FILES - source/qml/MainWindow.qml - source/qml/Navigator.qml - source/qml/Document.qml - source/qml/GoToKnowledge.qml + QML_FILES ${appEpistmoolUI_QML_FILES} ) set_target_properties(appEpistmoolUI PROPERTIES @@ -36,7 +29,7 @@ set_target_properties(appEpistmoolUI PROPERTIES WIN32_EXECUTABLE TRUE ) -target_include_directories(appEpistmoolUI PUBLIC source) +target_include_directories(appEpistmoolUI PUBLIC src) target_compile_definitions(appEpistmoolUI PRIVATE $<$,$>:QT_QML_DEBUG> ) diff --git a/ui.qt/qml/Document.qml b/ui.qt/qml/Document.qml new file mode 100644 index 0000000..a3d4075 --- /dev/null +++ b/ui.qt/qml/Document.qml @@ -0,0 +1,163 @@ +import QtCore +import QtQuick +import QtQuick.Controls +import QtQuick.Dialogs +import Qt.labs.platform as Platform + +import EpistmoolUI + +Item { + Action { + id: boldAction + shortcut: StandardKey.Bold + onTriggered: docHandler.bold = !docHandler.bold + } + + Action { + id: italicAction + shortcut: StandardKey.Italic + onTriggered: docHandler.italic = !docHandler.italic + } + + Action { + id: underlineAction + shortcut: StandardKey.Underline + onTriggered: docHandler.underline = !docHandler.underline + } + + Action { + id: strikeoutAction + shortcut: "Ctrl+Shift+X" + onTriggered: docHandler.strikeout = !docHandler.strikeout + } + + Platform.ColorDialog { + id: colorDialog + currentColor: "black" + } + + Item { + id: toolbar + width: parent.width + height: childrenRect.height + + Row { + id: toolbarLeft + layoutDirection: Qt.LeftToRight + + ToolButton { + id: boldButton + text: "B" + font.bold: true + focusPolicy: Qt.TabFocus + checkable: true + checked: docHandler.bold + action: boldAction + } + ToolButton { + id: italicButton + text: "I" + font.italic: true + focusPolicy: Qt.TabFocus + checkable: true + checked: docHandler.italic + action: italicAction + } + ToolButton { + id: underlineButton + text: "U" + font.underline: true + focusPolicy: Qt.TabFocus + checkable: true + checked: docHandler.underline + action: underlineAction + } + ToolButton { + id: strikeoutButton + text: "S" + font.strikeout: true + focusPolicy: Qt.TabFocus + checkable: true + checked: docHandler.strikeout + action: strikeoutAction + } + ToolButton { + id: textColorButton + text: "\uF1FC" // icon-brush + font.family: "fontello" + focusPolicy: Qt.TabFocus + onClicked: colorDialog.open() + + Rectangle { + width: aFontMetrics.width + 3 + height: 2 + color: docHandler.activeTextColor + parent: textColorButton.contentItem + anchors.horizontalCenter: parent.horizontalCenter + anchors.baseline: parent.baseline + anchors.baselineOffset: 6 + + TextMetrics { + id: aFontMetrics + font: textColorButton.font + text: textColorButton.text + } + } + } + } + + Row { + id: toolbarRight + layoutDirection: Qt.RightToLeft + height: parent.height + anchors.left: toolbarLeft.right + anchors.right: parent.right + + Label { + text: docHandler.modifyTime.toLocaleTimeString() + + ToolTip.visible: ma.containsMouse + ToolTip.text: docHandler.modifyTime.toLocaleString() + + MouseArea { + id: ma + anchors.fill: parent + hoverEnabled: true + } + } + } + } + + DocumentHandler { + id: docHandler + document: textArea.textDocument + + // Binding for current editing state of the TextArea + cursorPos: textArea.cursorPosition + selectionBegin: textArea.selectionStart + selectionEnd: textArea.selectionEnd + + property alias family: docHandler.activeFont.family + property alias bold: docHandler.activeFont.bold + property alias italic: docHandler.activeFont.italic + property alias underline: docHandler.activeFont.underline + property alias strikeout: docHandler.activeFont.strikeout + property alias size: docHandler.activeFont.pointSize + } + + ScrollView { + id: scrollView + width: parent.width + anchors.top: toolbar.bottom + anchors.bottom: parent.bottom + + TextArea { + id: textArea + textFormat: Qt.RichText + wrapMode: TextArea.Wrap + focus: true + selectByMouse: true + persistentSelection: true + } + } +} diff --git a/ui.qt/qml/GoToKnowledge.qml b/ui.qt/qml/GoToKnowledge.qml new file mode 100644 index 0000000..f97cbcf --- /dev/null +++ b/ui.qt/qml/GoToKnowledge.qml @@ -0,0 +1,4 @@ +import QtQuick + +Item { +} diff --git a/ui.qt/qml/MainWindow.qml b/ui.qt/qml/MainWindow.qml new file mode 100644 index 0000000..d81fb4f --- /dev/null +++ b/ui.qt/qml/MainWindow.qml @@ -0,0 +1,21 @@ +import QtQuick + +Window { + width: 640 + height: 480 + visible: true + title: qsTr("Hello World") + + Navigator { + id: navigator + width: childrenRect.width + height: parent.height + } + + Document { + id: document + height: parent.height + anchors.left: navigator.right + anchors.right: parent.right + } +} diff --git a/ui.qt/qml/Navigator.qml b/ui.qt/qml/Navigator.qml new file mode 100644 index 0000000..40c66e4 --- /dev/null +++ b/ui.qt/qml/Navigator.qml @@ -0,0 +1,36 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Item { + ColumnLayout { + spacing: 0 + + Button { + contentItem: Label { + text: qsTr("Settings") + anchors.verticalCenter: parent.verticalCenter + } + + Layout.fillWidth: true + } + + Button { + contentItem: Label { + text: qsTr("Keyword") + anchors.verticalCenter: parent.verticalCenter + } + + Layout.fillWidth: true + } + + Button { + contentItem: Label { + text: qsTr("Knowledge Fragments") + anchors.verticalCenter: parent.verticalCenter + } + + Layout.fillWidth: true + } + } +} diff --git a/ui.qt/source/DatabaseClient.cpp b/ui.qt/source/DatabaseClient.cpp deleted file mode 100644 index 430fe79..0000000 --- a/ui.qt/source/DatabaseClient.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "DatabaseClient.hpp" - -DatabaseClient::DatabaseClient() -{ -} diff --git a/ui.qt/source/DatabaseClient.hpp b/ui.qt/source/DatabaseClient.hpp deleted file mode 100644 index 17c6ed7..0000000 --- a/ui.qt/source/DatabaseClient.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class DatabaseClient -{ -public: - DatabaseClient(); -}; diff --git a/ui.qt/source/DatabaseServer.cpp b/ui.qt/source/DatabaseServer.cpp deleted file mode 100644 index a850e63..0000000 --- a/ui.qt/source/DatabaseServer.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "DatabaseServer.hpp" - -DatabaseServer::DatabaseServer() -{ -} diff --git a/ui.qt/source/DatabaseServer.hpp b/ui.qt/source/DatabaseServer.hpp deleted file mode 100644 index 0cd5039..0000000 --- a/ui.qt/source/DatabaseServer.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class DatabaseServer -{ -public: - DatabaseServer(); -}; diff --git a/ui.qt/source/Document.cpp b/ui.qt/source/Document.cpp deleted file mode 100644 index 272ac4c..0000000 --- a/ui.qt/source/Document.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "Document.hpp" - -#include -#include -#include -#include - -DocumentHandler::DocumentHandler(QObject* parent) - : QObject{ parent } -{ -} - -QQuickTextDocument* DocumentHandler::getDoc() const -{ - return mDoc; -} - -void DocumentHandler::setDoc(QQuickTextDocument* newDoc) -{ - if (mDoc != newDoc) { - auto oldDoc = mDoc; - mDoc = newDoc; - - if (oldDoc) { - disconnect(oldDoc->textDocument(), nullptr, this, nullptr); - } - if (newDoc) { - connect(newDoc->textDocument(), &QTextDocument::modificationChanged, this, [&]() { - // TODO add a timer to wait for 1 second before updating? - mModifyTime = QDateTime::currentDateTime(); - emit modificationChanged(); - }); - } - - emit docChanged(oldDoc); - } -} - -const QDateTime& DocumentHandler::getModifyTime() const -{ - return mModifyTime; -} - -int DocumentHandler::getCursorPos() const -{ - return mCursorPos; -} - -void DocumentHandler::setCursorPos(int newCursorPos) -{ - if (mCursorPos == newCursorPos) { - return; - } - mCursorPos = newCursorPos; - emit cursorPosChanged(); -} - -int DocumentHandler::getSelectionBegin() const -{ - return mSelectionBegin; -} - -void DocumentHandler::setSelectionBegin(int newSelectionBegin) -{ - if (mSelectionBegin == newSelectionBegin) { - return; - } - mSelectionBegin = newSelectionBegin; - emit selectionBeginChanged(); -} - -int DocumentHandler::getSelectionEnd() const -{ - return mSelectionEnd; -} - -void DocumentHandler::setSelectionEnd(int newSelectionEnd) -{ - if (mSelectionEnd == newSelectionEnd) { - return; - } - mSelectionEnd = newSelectionEnd; - emit selectionEndChanged(); -} - -QFont DocumentHandler::getActiveFont() const -{ - auto cursor = makeTextCursor(); - if (cursor.isNull()) { - return mDoc->textDocument()->defaultFont(); - } - auto format = cursor.charFormat(); - return format.font(); -} - -void DocumentHandler::setActiveFont(const QFont& font) -{ - auto cursor = makeTextCursor(); - if (!cursor.isNull() && cursor.charFormat().font() == font) { - return; - } - - QTextCharFormat format; - format.setFont(font); - mergeFormatOnWordOrSelection(format); - - emit activeFontChanged(); -} - -QColor DocumentHandler::getActiveTextColor() const -{ - auto cursor = makeTextCursor(); - if (cursor.isNull()) { - return QColor(Qt::black); - } - QTextCharFormat format = cursor.charFormat(); - return format.foreground().color(); -} - -void DocumentHandler::setActiveTextColor(const QColor& color) -{ - QTextCharFormat format; - format.setForeground(QBrush(color)); - mergeFormatOnWordOrSelection(format); - emit activeTextColorChanged(); -} - -QTextCursor DocumentHandler::makeTextCursor() const -{ - auto doc = mDoc->textDocument(); - if (!doc) { - return QTextCursor(); - } - - QTextCursor cursor(doc); - if (mSelectionBegin != mSelectionEnd) { - cursor.setPosition(mSelectionBegin); - cursor.setPosition(mSelectionEnd, QTextCursor::KeepAnchor); - } else { - cursor.setPosition(mCursorPos); - } - return cursor; -} - -void DocumentHandler::mergeFormatOnWordOrSelection(const QTextCharFormat& format) -{ - auto cursor = makeTextCursor(); - if (!cursor.hasSelection()) { - cursor.select(QTextCursor::WordUnderCursor); - } - cursor.mergeCharFormat(format); -} diff --git a/ui.qt/source/Document.hpp b/ui.qt/source/Document.hpp deleted file mode 100644 index 5ef1bba..0000000 --- a/ui.qt/source/Document.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "fwd.hpp" - -#include -#include -#include -#include -#include - -// To be instanciated in QML as the logic backend to some TextArea -class DocumentHandler : public QObject -{ - Q_OBJECT - QML_ELEMENT - - Q_PROPERTY(QQuickTextDocument* document READ getDoc WRITE setDoc NOTIFY docChanged) - Q_PROPERTY(QDateTime modifyTime READ getModifyTime NOTIFY modificationChanged) - - Q_PROPERTY(int cursorPos READ getCursorPos WRITE setCursorPos NOTIFY cursorPosChanged) - Q_PROPERTY(int selectionBegin READ getSelectionBegin WRITE setSelectionBegin NOTIFY selectionBeginChanged) - Q_PROPERTY(int selectionEnd READ getSelectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) - - Q_PROPERTY(QFont activeFont READ getActiveFont WRITE setActiveFont NOTIFY activeFontChanged) - Q_PROPERTY(QColor activeTextColor READ getActiveTextColor WRITE setActiveTextColor NOTIFY activeTextColorChanged) - -private: - QQuickTextDocument* mDoc = nullptr; - QDateTime mModifyTime; - - int mCursorPos; - int mSelectionBegin; - int mSelectionEnd; - -public: - explicit DocumentHandler(QObject* parent = nullptr); - - QQuickTextDocument* getDoc() const; - void setDoc(QQuickTextDocument* newDoc); - - const QDateTime& getModifyTime() const; - - int getCursorPos() const; - void setCursorPos(int newCursorPos); - - int getSelectionBegin() const; - void setSelectionBegin(int newSelectionBegin); - - int getSelectionEnd() const; - void setSelectionEnd(int newSelectionEnd); - - QFont getActiveFont() const; - void setActiveFont(const QFont& font); - - QColor getActiveTextColor() const; - void setActiveTextColor(const QColor& color); - -signals: - void docChanged(QQuickTextDocument* oldDoc); - void modificationChanged(); // Redirected from the currently bound document - - void cursorPosChanged(); - void selectionBeginChanged(); - void selectionEndChanged(); - - void activeFontChanged(); - void activeTextColorChanged(); - -private: - QTextCursor makeTextCursor() const; - void mergeFormatOnWordOrSelection(const QTextCharFormat& format); -}; diff --git a/ui.qt/source/Keyword.cpp b/ui.qt/source/Keyword.cpp deleted file mode 100644 index f6c18be..0000000 --- a/ui.qt/source/Keyword.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "Keyword.hpp" - -#include "KnowledgeFragment.hpp" - -Keyword::Keyword(const QString& name) - : mName(name) -{ -} - -Keyword::~Keyword() = default; diff --git a/ui.qt/source/Keyword.hpp b/ui.qt/source/Keyword.hpp deleted file mode 100644 index 481b5bb..0000000 --- a/ui.qt/source/Keyword.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "fwd.hpp" - -#include -#include - -class Keyword -{ -private: - QString mName; - std::vector mAssociations; - -public: - Keyword(const QString& name); - ~Keyword(); - - Keyword(const Keyword&) = default; - Keyword& operator=(const Keyword&) = default; - Keyword(Keyword&&) = default; - Keyword& operator=(Keyword&&) = default; -}; - -class KeywordDatabase -{ -}; diff --git a/ui.qt/source/KnowledgeFragment.cpp b/ui.qt/source/KnowledgeFragment.cpp deleted file mode 100644 index 3d08f6e..0000000 --- a/ui.qt/source/KnowledgeFragment.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "KnowledgeFragment.hpp" - -KnowledgeFragment::KnowledgeFragment(KnowledgeId id) - : mId{ id } -{ -} - -KnowledgeId KnowledgeFragment::getId() const -{ - return mId; -} diff --git a/ui.qt/source/KnowledgeFragment.hpp b/ui.qt/source/KnowledgeFragment.hpp deleted file mode 100644 index 9f4912d..0000000 --- a/ui.qt/source/KnowledgeFragment.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "fwd.hpp" - -#include -#include -#include - -struct KnowledgeId -{ - size_t id; -}; - -class KnowledgeFragment -{ -private: - QDateTime mCreateTime; - QDateTime mModifyTime; - KnowledgeId mId; - -public: - KnowledgeFragment(KnowledgeId id); - - KnowledgeId getId() const; -}; - -class KnowledgeDatabase -{ -private: - std::vector mStorage; - std::vector mIndex; // Mapping from KnowledgeId (index) to `storage` index - KnowledgeId mNextId; - -public: - KnowledgeId allocateFragment(); - bool deleteFragment(KnowledgeId id); - KnowledgeFragment* getFragment(KnowledgeId id); -}; diff --git a/ui.qt/source/fwd.hpp b/ui.qt/source/fwd.hpp deleted file mode 100644 index 14e0033..0000000 --- a/ui.qt/source/fwd.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -// Document.hpp -class DocumentHandler; - -// Keyword.hpp -class Keyword; -class KeywordDatabase; - -// Knowledgefragment.cpp -struct KnowledgeId; -class KnowledgeFragment; -class KnowledgeDatabase; diff --git a/ui.qt/source/main.cpp b/ui.qt/source/main.cpp deleted file mode 100644 index 863ee20..0000000 --- a/ui.qt/source/main.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - QTranslator translator; - const QStringList uiLanguages = QLocale::system().uiLanguages(); - for (const QString& locale : uiLanguages) { - const QString baseName = "EpistmoolUI_" + QLocale(locale).name(); - if (translator.load(":/i18n/" + baseName)) { - app.installTranslator(&translator); - break; - } - } - - QQmlApplicationEngine engine; - const QUrl url(u"qrc:/EpistmoolUI/source/qml/MainWindow.qml"_qs); - QObject::connect( - &engine, - &QQmlApplicationEngine::objectCreated, - &app, - [url](QObject* obj, const QUrl& objUrl) { - if (!obj && url == objUrl) { - QCoreApplication::exit(-1); - } - }, - Qt::QueuedConnection); - engine.load(url); - - return app.exec(); -} diff --git a/ui.qt/source/qml/Document.qml b/ui.qt/source/qml/Document.qml deleted file mode 100644 index a3d4075..0000000 --- a/ui.qt/source/qml/Document.qml +++ /dev/null @@ -1,163 +0,0 @@ -import QtCore -import QtQuick -import QtQuick.Controls -import QtQuick.Dialogs -import Qt.labs.platform as Platform - -import EpistmoolUI - -Item { - Action { - id: boldAction - shortcut: StandardKey.Bold - onTriggered: docHandler.bold = !docHandler.bold - } - - Action { - id: italicAction - shortcut: StandardKey.Italic - onTriggered: docHandler.italic = !docHandler.italic - } - - Action { - id: underlineAction - shortcut: StandardKey.Underline - onTriggered: docHandler.underline = !docHandler.underline - } - - Action { - id: strikeoutAction - shortcut: "Ctrl+Shift+X" - onTriggered: docHandler.strikeout = !docHandler.strikeout - } - - Platform.ColorDialog { - id: colorDialog - currentColor: "black" - } - - Item { - id: toolbar - width: parent.width - height: childrenRect.height - - Row { - id: toolbarLeft - layoutDirection: Qt.LeftToRight - - ToolButton { - id: boldButton - text: "B" - font.bold: true - focusPolicy: Qt.TabFocus - checkable: true - checked: docHandler.bold - action: boldAction - } - ToolButton { - id: italicButton - text: "I" - font.italic: true - focusPolicy: Qt.TabFocus - checkable: true - checked: docHandler.italic - action: italicAction - } - ToolButton { - id: underlineButton - text: "U" - font.underline: true - focusPolicy: Qt.TabFocus - checkable: true - checked: docHandler.underline - action: underlineAction - } - ToolButton { - id: strikeoutButton - text: "S" - font.strikeout: true - focusPolicy: Qt.TabFocus - checkable: true - checked: docHandler.strikeout - action: strikeoutAction - } - ToolButton { - id: textColorButton - text: "\uF1FC" // icon-brush - font.family: "fontello" - focusPolicy: Qt.TabFocus - onClicked: colorDialog.open() - - Rectangle { - width: aFontMetrics.width + 3 - height: 2 - color: docHandler.activeTextColor - parent: textColorButton.contentItem - anchors.horizontalCenter: parent.horizontalCenter - anchors.baseline: parent.baseline - anchors.baselineOffset: 6 - - TextMetrics { - id: aFontMetrics - font: textColorButton.font - text: textColorButton.text - } - } - } - } - - Row { - id: toolbarRight - layoutDirection: Qt.RightToLeft - height: parent.height - anchors.left: toolbarLeft.right - anchors.right: parent.right - - Label { - text: docHandler.modifyTime.toLocaleTimeString() - - ToolTip.visible: ma.containsMouse - ToolTip.text: docHandler.modifyTime.toLocaleString() - - MouseArea { - id: ma - anchors.fill: parent - hoverEnabled: true - } - } - } - } - - DocumentHandler { - id: docHandler - document: textArea.textDocument - - // Binding for current editing state of the TextArea - cursorPos: textArea.cursorPosition - selectionBegin: textArea.selectionStart - selectionEnd: textArea.selectionEnd - - property alias family: docHandler.activeFont.family - property alias bold: docHandler.activeFont.bold - property alias italic: docHandler.activeFont.italic - property alias underline: docHandler.activeFont.underline - property alias strikeout: docHandler.activeFont.strikeout - property alias size: docHandler.activeFont.pointSize - } - - ScrollView { - id: scrollView - width: parent.width - anchors.top: toolbar.bottom - anchors.bottom: parent.bottom - - TextArea { - id: textArea - textFormat: Qt.RichText - wrapMode: TextArea.Wrap - focus: true - selectByMouse: true - persistentSelection: true - } - } -} diff --git a/ui.qt/source/qml/GoToKnowledge.qml b/ui.qt/source/qml/GoToKnowledge.qml deleted file mode 100644 index f97cbcf..0000000 --- a/ui.qt/source/qml/GoToKnowledge.qml +++ /dev/null @@ -1,4 +0,0 @@ -import QtQuick - -Item { -} diff --git a/ui.qt/source/qml/MainWindow.qml b/ui.qt/source/qml/MainWindow.qml deleted file mode 100644 index d81fb4f..0000000 --- a/ui.qt/source/qml/MainWindow.qml +++ /dev/null @@ -1,21 +0,0 @@ -import QtQuick - -Window { - width: 640 - height: 480 - visible: true - title: qsTr("Hello World") - - Navigator { - id: navigator - width: childrenRect.width - height: parent.height - } - - Document { - id: document - height: parent.height - anchors.left: navigator.right - anchors.right: parent.right - } -} diff --git a/ui.qt/source/qml/Navigator.qml b/ui.qt/source/qml/Navigator.qml deleted file mode 100644 index 40c66e4..0000000 --- a/ui.qt/source/qml/Navigator.qml +++ /dev/null @@ -1,36 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -Item { - ColumnLayout { - spacing: 0 - - Button { - contentItem: Label { - text: qsTr("Settings") - anchors.verticalCenter: parent.verticalCenter - } - - Layout.fillWidth: true - } - - Button { - contentItem: Label { - text: qsTr("Keyword") - anchors.verticalCenter: parent.verticalCenter - } - - Layout.fillWidth: true - } - - Button { - contentItem: Label { - text: qsTr("Knowledge Fragments") - anchors.verticalCenter: parent.verticalCenter - } - - Layout.fillWidth: true - } - } -} diff --git a/ui.qt/src/DatabaseClient.cpp b/ui.qt/src/DatabaseClient.cpp new file mode 100644 index 0000000..430fe79 --- /dev/null +++ b/ui.qt/src/DatabaseClient.cpp @@ -0,0 +1,5 @@ +#include "DatabaseClient.hpp" + +DatabaseClient::DatabaseClient() +{ +} diff --git a/ui.qt/src/DatabaseClient.hpp b/ui.qt/src/DatabaseClient.hpp new file mode 100644 index 0000000..17c6ed7 --- /dev/null +++ b/ui.qt/src/DatabaseClient.hpp @@ -0,0 +1,7 @@ +#pragma once + +class DatabaseClient +{ +public: + DatabaseClient(); +}; diff --git a/ui.qt/src/DatabaseServer.cpp b/ui.qt/src/DatabaseServer.cpp new file mode 100644 index 0000000..a850e63 --- /dev/null +++ b/ui.qt/src/DatabaseServer.cpp @@ -0,0 +1,5 @@ +#include "DatabaseServer.hpp" + +DatabaseServer::DatabaseServer() +{ +} diff --git a/ui.qt/src/DatabaseServer.hpp b/ui.qt/src/DatabaseServer.hpp new file mode 100644 index 0000000..0cd5039 --- /dev/null +++ b/ui.qt/src/DatabaseServer.hpp @@ -0,0 +1,7 @@ +#pragma once + +class DatabaseServer +{ +public: + DatabaseServer(); +}; diff --git a/ui.qt/src/Document.cpp b/ui.qt/src/Document.cpp new file mode 100644 index 0000000..272ac4c --- /dev/null +++ b/ui.qt/src/Document.cpp @@ -0,0 +1,152 @@ +#include "Document.hpp" + +#include +#include +#include +#include + +DocumentHandler::DocumentHandler(QObject* parent) + : QObject{ parent } +{ +} + +QQuickTextDocument* DocumentHandler::getDoc() const +{ + return mDoc; +} + +void DocumentHandler::setDoc(QQuickTextDocument* newDoc) +{ + if (mDoc != newDoc) { + auto oldDoc = mDoc; + mDoc = newDoc; + + if (oldDoc) { + disconnect(oldDoc->textDocument(), nullptr, this, nullptr); + } + if (newDoc) { + connect(newDoc->textDocument(), &QTextDocument::modificationChanged, this, [&]() { + // TODO add a timer to wait for 1 second before updating? + mModifyTime = QDateTime::currentDateTime(); + emit modificationChanged(); + }); + } + + emit docChanged(oldDoc); + } +} + +const QDateTime& DocumentHandler::getModifyTime() const +{ + return mModifyTime; +} + +int DocumentHandler::getCursorPos() const +{ + return mCursorPos; +} + +void DocumentHandler::setCursorPos(int newCursorPos) +{ + if (mCursorPos == newCursorPos) { + return; + } + mCursorPos = newCursorPos; + emit cursorPosChanged(); +} + +int DocumentHandler::getSelectionBegin() const +{ + return mSelectionBegin; +} + +void DocumentHandler::setSelectionBegin(int newSelectionBegin) +{ + if (mSelectionBegin == newSelectionBegin) { + return; + } + mSelectionBegin = newSelectionBegin; + emit selectionBeginChanged(); +} + +int DocumentHandler::getSelectionEnd() const +{ + return mSelectionEnd; +} + +void DocumentHandler::setSelectionEnd(int newSelectionEnd) +{ + if (mSelectionEnd == newSelectionEnd) { + return; + } + mSelectionEnd = newSelectionEnd; + emit selectionEndChanged(); +} + +QFont DocumentHandler::getActiveFont() const +{ + auto cursor = makeTextCursor(); + if (cursor.isNull()) { + return mDoc->textDocument()->defaultFont(); + } + auto format = cursor.charFormat(); + return format.font(); +} + +void DocumentHandler::setActiveFont(const QFont& font) +{ + auto cursor = makeTextCursor(); + if (!cursor.isNull() && cursor.charFormat().font() == font) { + return; + } + + QTextCharFormat format; + format.setFont(font); + mergeFormatOnWordOrSelection(format); + + emit activeFontChanged(); +} + +QColor DocumentHandler::getActiveTextColor() const +{ + auto cursor = makeTextCursor(); + if (cursor.isNull()) { + return QColor(Qt::black); + } + QTextCharFormat format = cursor.charFormat(); + return format.foreground().color(); +} + +void DocumentHandler::setActiveTextColor(const QColor& color) +{ + QTextCharFormat format; + format.setForeground(QBrush(color)); + mergeFormatOnWordOrSelection(format); + emit activeTextColorChanged(); +} + +QTextCursor DocumentHandler::makeTextCursor() const +{ + auto doc = mDoc->textDocument(); + if (!doc) { + return QTextCursor(); + } + + QTextCursor cursor(doc); + if (mSelectionBegin != mSelectionEnd) { + cursor.setPosition(mSelectionBegin); + cursor.setPosition(mSelectionEnd, QTextCursor::KeepAnchor); + } else { + cursor.setPosition(mCursorPos); + } + return cursor; +} + +void DocumentHandler::mergeFormatOnWordOrSelection(const QTextCharFormat& format) +{ + auto cursor = makeTextCursor(); + if (!cursor.hasSelection()) { + cursor.select(QTextCursor::WordUnderCursor); + } + cursor.mergeCharFormat(format); +} diff --git a/ui.qt/src/Document.hpp b/ui.qt/src/Document.hpp new file mode 100644 index 0000000..5ef1bba --- /dev/null +++ b/ui.qt/src/Document.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "fwd.hpp" + +#include +#include +#include +#include +#include + +// To be instanciated in QML as the logic backend to some TextArea +class DocumentHandler : public QObject +{ + Q_OBJECT + QML_ELEMENT + + Q_PROPERTY(QQuickTextDocument* document READ getDoc WRITE setDoc NOTIFY docChanged) + Q_PROPERTY(QDateTime modifyTime READ getModifyTime NOTIFY modificationChanged) + + Q_PROPERTY(int cursorPos READ getCursorPos WRITE setCursorPos NOTIFY cursorPosChanged) + Q_PROPERTY(int selectionBegin READ getSelectionBegin WRITE setSelectionBegin NOTIFY selectionBeginChanged) + Q_PROPERTY(int selectionEnd READ getSelectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) + + Q_PROPERTY(QFont activeFont READ getActiveFont WRITE setActiveFont NOTIFY activeFontChanged) + Q_PROPERTY(QColor activeTextColor READ getActiveTextColor WRITE setActiveTextColor NOTIFY activeTextColorChanged) + +private: + QQuickTextDocument* mDoc = nullptr; + QDateTime mModifyTime; + + int mCursorPos; + int mSelectionBegin; + int mSelectionEnd; + +public: + explicit DocumentHandler(QObject* parent = nullptr); + + QQuickTextDocument* getDoc() const; + void setDoc(QQuickTextDocument* newDoc); + + const QDateTime& getModifyTime() const; + + int getCursorPos() const; + void setCursorPos(int newCursorPos); + + int getSelectionBegin() const; + void setSelectionBegin(int newSelectionBegin); + + int getSelectionEnd() const; + void setSelectionEnd(int newSelectionEnd); + + QFont getActiveFont() const; + void setActiveFont(const QFont& font); + + QColor getActiveTextColor() const; + void setActiveTextColor(const QColor& color); + +signals: + void docChanged(QQuickTextDocument* oldDoc); + void modificationChanged(); // Redirected from the currently bound document + + void cursorPosChanged(); + void selectionBeginChanged(); + void selectionEndChanged(); + + void activeFontChanged(); + void activeTextColorChanged(); + +private: + QTextCursor makeTextCursor() const; + void mergeFormatOnWordOrSelection(const QTextCharFormat& format); +}; diff --git a/ui.qt/src/Keyword.cpp b/ui.qt/src/Keyword.cpp new file mode 100644 index 0000000..f6c18be --- /dev/null +++ b/ui.qt/src/Keyword.cpp @@ -0,0 +1,10 @@ +#include "Keyword.hpp" + +#include "KnowledgeFragment.hpp" + +Keyword::Keyword(const QString& name) + : mName(name) +{ +} + +Keyword::~Keyword() = default; diff --git a/ui.qt/src/Keyword.hpp b/ui.qt/src/Keyword.hpp new file mode 100644 index 0000000..481b5bb --- /dev/null +++ b/ui.qt/src/Keyword.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "fwd.hpp" + +#include +#include + +class Keyword +{ +private: + QString mName; + std::vector mAssociations; + +public: + Keyword(const QString& name); + ~Keyword(); + + Keyword(const Keyword&) = default; + Keyword& operator=(const Keyword&) = default; + Keyword(Keyword&&) = default; + Keyword& operator=(Keyword&&) = default; +}; + +class KeywordDatabase +{ +}; diff --git a/ui.qt/src/KnowledgeFragment.cpp b/ui.qt/src/KnowledgeFragment.cpp new file mode 100644 index 0000000..3d08f6e --- /dev/null +++ b/ui.qt/src/KnowledgeFragment.cpp @@ -0,0 +1,11 @@ +#include "KnowledgeFragment.hpp" + +KnowledgeFragment::KnowledgeFragment(KnowledgeId id) + : mId{ id } +{ +} + +KnowledgeId KnowledgeFragment::getId() const +{ + return mId; +} diff --git a/ui.qt/src/KnowledgeFragment.hpp b/ui.qt/src/KnowledgeFragment.hpp new file mode 100644 index 0000000..9f4912d --- /dev/null +++ b/ui.qt/src/KnowledgeFragment.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "fwd.hpp" + +#include +#include +#include + +struct KnowledgeId +{ + size_t id; +}; + +class KnowledgeFragment +{ +private: + QDateTime mCreateTime; + QDateTime mModifyTime; + KnowledgeId mId; + +public: + KnowledgeFragment(KnowledgeId id); + + KnowledgeId getId() const; +}; + +class KnowledgeDatabase +{ +private: + std::vector mStorage; + std::vector mIndex; // Mapping from KnowledgeId (index) to `storage` index + KnowledgeId mNextId; + +public: + KnowledgeId allocateFragment(); + bool deleteFragment(KnowledgeId id); + KnowledgeFragment* getFragment(KnowledgeId id); +}; diff --git a/ui.qt/src/fwd.hpp b/ui.qt/src/fwd.hpp new file mode 100644 index 0000000..14e0033 --- /dev/null +++ b/ui.qt/src/fwd.hpp @@ -0,0 +1,13 @@ +#pragma once + +// Document.hpp +class DocumentHandler; + +// Keyword.hpp +class Keyword; +class KeywordDatabase; + +// Knowledgefragment.cpp +struct KnowledgeId; +class KnowledgeFragment; +class KnowledgeDatabase; diff --git a/ui.qt/src/main.cpp b/ui.qt/src/main.cpp new file mode 100644 index 0000000..e8af4aa --- /dev/null +++ b/ui.qt/src/main.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QTranslator translator; + QStringList uiLanguages = QLocale::system().uiLanguages(); + for (const QString& locale : uiLanguages) { + const QString baseName = "EpistmoolUI_" + QLocale(locale).name(); + if (translator.load(":/i18n/" + baseName)) { + app.installTranslator(&translator); + break; + } + } + + QQmlApplicationEngine engine; + QUrl url(u"qrc:/EpistmoolUI/qml/MainWindow.qml"_qs); + QObject::connect( + &engine, + &QQmlApplicationEngine::objectCreated, + &app, + [url](QObject* obj, const QUrl& objUrl) { + if (!obj && url == objUrl) { + QCoreApplication::exit(-1); + } + }, + Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} -- cgit v1.2.3-70-g09d2