diff --git a/src/controls/ApplicationWindow.qml b/src/controls/ApplicationWindow.qml index edb1c06..93bcdae 100644 --- a/src/controls/ApplicationWindow.qml +++ b/src/controls/ApplicationWindow.qml @@ -1,477 +1,469 @@ /* * Copyright 2018 Camilo Higuita * * 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 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 QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Window 2.3 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import QtQuick.Controls.Material 2.1 import "private" Kirigami.AbstractApplicationWindow { id: root visible: true width: Screen.width * (Kirigami.Settings.isMobile ? 1 : 0.4) height: Screen.height * (Kirigami.Settings.isMobile ? 1 : 0.4) contentItem.anchors.leftMargin: root.sideBar && !root.globalDrawer ? ((root.sideBar.collapsible && root.sideBar.collapsed) ? root.sideBar.collapsedSize : (root.sideBar.modal ? 0 : root.sideBar.width * root.sideBar.position)) : (!root.sideBar && root.globalDrawer && (root.globalDrawer.modal === false) ? root.globalDrawer.width * root.globalDrawer.position : 0) property Maui.AbstractSideBar sideBar /***************************************************/ /******************** ALIASES *********************/ /*************************************************/ property alias headBar : _headBar property alias footBar: _footBar property alias dialog: dialogLoader.item property alias leftIcon : menuBtn property alias rightIcon : searchBtn property alias mainMenu : mainMenu.contentData property alias about : aboutDialog property alias accounts: _accountsDialogLoader.item property var currentAccount: Maui.App.accounts.currentAccount property alias notifyDialog: _notify property alias searchButton : searchBtn property alias menuButton : menuBtn wideScreen: isWide /***************************************************/ /*********************** UI ***********************/ /*************************************************/ property bool isWide : root.width >= Kirigami.Units.gridUnit * 30 property string colorSchemeName : Qt.application.name /***************************************************/ /********************* COLORS *********************/ /*************************************************/ property color headBarBGColor: Kirigami.Theme.backgroundColor property color headBarFGColor: Kirigami.Theme.textColor /***************************************************/ /**************** READONLY PROPS ******************/ /*************************************************/ readonly property bool isMobile : Kirigami.Settings.isMobile readonly property bool isAndroid: Maui.Handy.isAndroid readonly property bool isTouch: Maui.Handy.isTouch readonly property real screenWidth : Screen.width readonly property real screenHeight : Screen.height /***************************************************/ /******************** SIGNALS *********************/ /*************************************************/ signal menuButtonClicked(); signal searchButtonClicked(); onClosing: { if(!Kirigami.Settings.isMobile) { const height = root.height const width = root.width const x = root.x const y = root.y Maui.FM.saveSettings("GEOMETRY", Qt.rect(x, y, width, height), "WINDOW") } } property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation || Screen.primaryOrientation === Qt.InvertedPortraitOrientation onIsPortraitChanged: { if(isPortrait) { console.log("PORTARIT MODE CHANGED") width: Screen.width height: Screen.height } } // onHeadBarBGColorChanged: // { // if(!isMobile && colorSchemeName.length > 0) // Maui.KDE.setColorScheme(colorSchemeName, headBarBGColor, headBarFGColor) // else if(isAndroid && headBar.position === ToolBar.Header) // Maui.Android.statusbarColor(headBarBGColor, false) // else if(isAndroid && headBar.position === ToolBar.Footer) // Maui.Android.statusbarColor(Kirigami.Theme.viewBackgroundColor, true) // // } // // onHeadBarFGColorChanged: // { // if(!isAndroid && !isMobile && colorSchemeName.length > 0 && headBar.position === ToolBar.Header) // Maui.KDE.setColorScheme(colorSchemeName, headBarBGColor, headBarFGColor) // else if(isAndroid && headBar.position === ToolBar.Header) // Maui.Android.statusbarColor(headBarBGColor, false) // else if(isAndroid && headBar.position === ToolBar.Footer) // Maui.Android.statusbarColor(Kirigami.Theme.viewBackgroundColor, true) // } /* * background: Rectangle * { * color: bgColor } */ Component { id: _accountsComponent ColumnLayout { visible: Maui.App.handleAccounts spacing: Maui.Style.space.medium Kirigami.Icon { visible: Maui.App.accounts.currentAccountIndex >= 0 source: "user-identity" Layout.preferredHeight: Maui.Style.iconSizes.large Layout.preferredWidth: Maui.Style.iconSizes.large Layout.alignment: Qt.AlignCenter Layout.margins: Maui.Style.space.medium } Label { visible: Maui.App.accounts.currentAccountIndex >= 0 text: currentAccount.user Layout.fillWidth: true horizontalAlignment: Qt.AlignHCenter elide: Text.ElideMiddle wrapMode: Text.NoWrap font.bold: true font.weight: Font.Bold } Kirigami.Separator { visible: _accountsListing.count > 0 Layout.fillWidth: true } ListBrowser { id: _accountsListing visible: _accountsListing.count > 0 Layout.fillWidth: true Layout.preferredHeight: Math.min(listView.contentHeight, 300) listView.spacing: Maui.Style.space.medium Kirigami.Theme.backgroundColor: "transparent" + currentIndex: Maui.App.accounts.currentAccountIndex + model: Maui.BaseModel { list: Maui.App.accounts } delegate: Maui.ListBrowserDelegate { iconSource: "amarok_artist" iconSizeHint: Maui.Style.iconSizes.medium label1.text: model.user label2.text: model.server width: _accountsListing.width height: Maui.Style.rowHeight * 1.2 leftPadding: Maui.Style.space.tiny - rightPadding: Maui.Style.space.tiny - - onClicked: - { - _accountsListing.currentIndex = index - Maui.App.accounts.currentAccountIndex = - index - } - } + rightPadding: Maui.Style.space.tiny + onClicked: Maui.App.accounts.currentAccountIndex = index + } Component.onCompleted: { - if(_accountsListing.count > 0) - { - _accountsListing.currentIndex = 0 - Maui.App.accounts.currentAccountIndex = - _accountsListing.currentIndex - } + if(_accountsListing.count > 0) + Maui.App.accounts.currentAccountIndex = 0 } } Kirigami.Separator { visible: _accountsListing.count > 0 Layout.fillWidth: true } Button { Layout.margins: Maui.Style.space.small Layout.preferredHeight: implicitHeight Layout.alignment: Qt.AlignCenter text: qsTr("Manage accounts") icon.name: "list-add-user" onClicked: { if(root.accounts) accounts.open() mainMenu.close() } Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.1) Kirigami.Theme.textColor: Kirigami.Theme.textColor } Kirigami.Separator { Layout.fillWidth: true } } } property Maui.ToolBar mheadBar : Maui.ToolBar { id: _headBar visible: count > 1 position: ToolBar.Header width: root.width height: implicitHeight // Kirigami.Theme.backgroundColor: headBarBGColor // Kirigami.Theme.textColor: headBarFGColor // Kirigami.Theme.inherit: true leftContent: [ ToolButton { id: menuBtn icon.name: "application-menu" icon.color: headBarFGColor icon.width: Maui.Style.iconSizes.medium icon.height: Maui.Style.iconSizes.medium checked: mainMenu.visible onClicked: { menuButtonClicked() mainMenu.visible ? mainMenu.close() : mainMenu.popup(parent, parent.x , parent.height+ Maui.Style.space.medium) } Menu { id: mainMenu modal: true z: 999 width: Maui.Style.unit * 250 Loader { id: _accountsMenuLoader width: parent.width * 0.9 anchors.horizontalCenter: parent.horizontalCenter active: Maui.App.handleAccounts sourceComponent: Maui.App.handleAccounts ? _accountsComponent : null } MenuItem { text: qsTr("About") icon.name: "documentinfo" onTriggered: aboutDialog.open() } } } ] rightContent: ToolButton { id: searchBtn icon.name: "edit-find" icon.color: headBarFGColor onClicked: searchButtonClicked() icon.width: Maui.Style.iconSizes.medium icon.height: Maui.Style.iconSizes.medium } } property Maui.ToolBar mfootBar : Maui.ToolBar { id: _footBar visible: count position: ToolBar.Footer width: root.width height: implicitHeight } header: headBar.count && headBar.position === ToolBar.Header ? headBar : null footer: Column { id: _footer visible : children children: { if(headBar.position === ToolBar.Footer && headBar.count && footBar.count) return [footBar , headBar] else if(headBar.position === ToolBar.Footer && headBar.count) return [headBar] else if(footBar.count) return [footBar] else return [] } } Maui.AboutDialog { id: aboutDialog } Loader { id: _accountsDialogLoader source: Maui.App.handleAccounts ? "private/AccountsHelper.qml" : "" } Maui.Dialog { id: _notify property var cb : ({}) property alias iconName : _notifyTemplate.iconSource property alias title : _notifyTemplate.label1 property alias body: _notifyTemplate.label2 verticalAlignment: Qt.AlignTop defaultButtons: _notify.cb !== null rejectButton.visible: false onAccepted: { if(_notify.cb) { _notify.cb() _notify.close() } } page.padding: Maui.Style.space.medium footBar.background: null maxHeight: Math.max(Maui.Style.iconSizes.large + Maui.Style.space.huge, (_notifyTemplate.implicitHeight)) + Maui.Style.space.big + footBar.height maxWidth: Kirigami.Settings.isMobile ? parent.width * 0.9 : Maui.Style.unit * 500 widthHint: 0.8 Timer { id: _notifyTimer onTriggered: { if(_mouseArea.containsPress || _mouseArea.containsMouse) return; _notify.close() } } onClosed: _notifyTimer.stop() Maui.ListItemTemplate { id: _notifyTemplate anchors.fill: parent iconSizeHint: Maui.Style.iconSizes.huge label1.font.bold: true label1.font.weight: Font.Bold label1.font.pointSize: Maui.Style.fontSizes.big iconSource: "dialog-warning" } MouseArea { id: _mouseArea height: parent.height width: parent.width anchors.centerIn: parent hoverEnabled: true } function show(callback) { _notify.cb = callback || null _notifyTimer.start() _notify.open() } } Loader { id: dialogLoader } Component.onCompleted: { if(isAndroid) { if(headBar.position === ToolBar.Footer) Maui.Android.statusbarColor(Kirigami.Theme.backgroundColor, true) else Maui.Android.statusbarColor(headBar.Kirigami.Theme.backgroundColor, true) } if(!Kirigami.Settings.isMobile) { const rect = Maui.FM.loadSettings("GEOMETRY", "WINDOW", Qt.rect(root.x, root.y, root.width, root.height)) root.x = rect.x root.y = rect.y root.width = rect.width root.height = rect.height } } Connections { target: Maui.App onSendNotification: notify(icon, title, body, callback, timeout, buttonText) } function notify(icon, title, body, callback, timeout, buttonText) { _notify.iconName = icon || "emblem-warning" _notify.title.text = title _notify.body.text = body _notifyTimer.interval = timeout ? timeout : 2500 _notify.acceptButton.text = buttonText || qsTr ("Accept") _notify.show(callback) } } diff --git a/src/utils/accounts/mauiaccounts.cpp b/src/utils/accounts/mauiaccounts.cpp index 48e3dba..a0ddf47 100644 --- a/src/utils/accounts/mauiaccounts.cpp +++ b/src/utils/accounts/mauiaccounts.cpp @@ -1,212 +1,215 @@ /* * * Copyright (C) 2019 camilo * * 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 3 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 "mauiaccounts.h" #include "accountsdb.h" MauiAccounts::MauiAccounts() : MauiList(nullptr), db(new AccountsDB(nullptr)) { this->setAccounts(); } MauiAccounts::~MauiAccounts() { qDebug() << "DELETING MAUI ACCOUNTS INSTANCE"; this->db->deleteLater(); this->db = nullptr; } FMH::MODEL_LIST MauiAccounts::items() const { return this->m_data; } void MauiAccounts::setAccounts() { emit this->preListChanged(); this->m_data = this->getCloudAccounts(); qDebug()<< "ACCOUNTS LIST"<< this->m_data; this->m_count = this->m_data.count(); emit this->countChanged(this->m_count); emit this->postListChanged(); } FMH::MODEL_LIST MauiAccounts::getCloudAccounts() { auto accounts = this->get("select * from cloud"); FMH::MODEL_LIST res; for(const auto &account : accounts) { auto map = account.toMap(); res << FMH::MODEL { {FMH::MODEL_KEY::PATH, FMH::PATHTYPE_URI[FMH::PATHTYPE_KEY::CLOUD_PATH]+map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, {FMH::MODEL_KEY::ICON, "folder-cloud"}, {FMH::MODEL_KEY::LABEL, map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, {FMH::MODEL_KEY::USER, map[FMH::MODEL_NAME[FMH::MODEL_KEY::USER]].toString()}, {FMH::MODEL_KEY::SERVER, map[FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER]].toString()}, {FMH::MODEL_KEY::PASSWORD, map[FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD]].toString()}, {FMH::MODEL_KEY::TYPE, FMH::PATHTYPE_LABEL[FMH::PATHTYPE_KEY::CLOUD_PATH]}}; } return res; } bool MauiAccounts::addCloudAccount(const QString &server, const QString &user, const QString &password) { const QVariantMap account = { {FMH::MODEL_NAME[FMH::MODEL_KEY::SERVER], server}, {FMH::MODEL_NAME[FMH::MODEL_KEY::USER], user}, {FMH::MODEL_NAME[FMH::MODEL_KEY::PASSWORD], password} }; if(this->db->insert("cloud", account)) { emit this->accountAdded(account); return true; } return false; } bool MauiAccounts::removeCloudAccount(const QString &server, const QString &user) { FMH::MODEL account = { {FMH::MODEL_KEY::SERVER, server}, {FMH::MODEL_KEY::USER, user}, }; if(this->db->remove("cloud", account)) { emit this->accountRemoved(FMH::toMap(account)); return true; } return false; } QVariantList MauiAccounts::get(const QString &queryTxt) { QVariantList mapList; auto query = this->db->getQuery(queryTxt); if(query.exec()) { while(query.next()) { QVariantMap data; for(auto key : FMH::MODEL_NAME.keys()) if(query.record().indexOf(FMH::MODEL_NAME[key]) > -1) data[FMH::MODEL_NAME[key]] = query.value(FMH::MODEL_NAME[key]).toString(); mapList<< data; } }else qDebug()<< query.lastError()<< query.lastQuery(); return mapList; } int MauiAccounts::getCurrentAccountIndex() const { return this->m_currentAccountIndex; } QVariantMap MauiAccounts::getCurrentAccount() const { return this->m_currentAccount; } void MauiAccounts::registerAccount(const QVariantMap& account) { // register the account to the backend needed auto model = FMH::toModel(account); if(this->addCloudAccount(model[FMH::MODEL_KEY::SERVER], model[FMH::MODEL_KEY::USER], model[FMH::MODEL_KEY::PASSWORD])) { this->setAccounts(); } } void MauiAccounts::setCurrentAccountIndex(const int& index) { if(index >= this->m_data.size() || index < 0) return; + if(index == this->m_currentAccountIndex) + return; + //make sure the account exists this->m_currentAccountIndex = index; this->m_currentAccount = FMH::toMap(this->m_data.at(m_currentAccountIndex)); emit this->currentAccountChanged(this->m_currentAccount); emit this->currentAccountIndexChanged(this->m_currentAccountIndex); } QVariantMap MauiAccounts::get(const int& index) const { if(index >= this->m_data.size() || index < 0) return QVariantMap(); return FMH::toMap(this->m_data.at(index)); } QVariantList MauiAccounts::getCloudAccountsList() { QVariantList res; const auto data = this->getCloudAccounts(); for(const auto &item : data) res << FMH::toMap(item); return res; } uint MauiAccounts::getCount() const { return this->m_count; } void MauiAccounts::refresh() { this->setAccounts(); } void MauiAccounts::removeAccount(const int& index) { if(index >= this->m_data.size() || index < 0) return; if(this->removeCloudAccount(this->m_data.at(index)[FMH::MODEL_KEY::SERVER], this->m_data.at(index)[FMH::MODEL_KEY::USER])) { this->refresh(); } } void MauiAccounts::removeAccountAndFiles(const int& index) { if(index >= this->m_data.size() || index < 0) return; if(this->removeCloudAccount(this->m_data.at(index)[FMH::MODEL_KEY::SERVER], this->m_data.at(index)[FMH::MODEL_KEY::USER])) { this->refresh(); } // FM_STATIC::removeDir(FM::resolveUserCloudCachePath(this->m_data.at(index)[FMH::MODEL_KEY::SERVER], this->m_data.at(index)[FMH::MODEL_KEY::USER])); } diff --git a/src/utils/editor/documenthandler.h b/src/utils/editor/documenthandler.h index 15961e4..61190b1 100644 --- a/src/utils/editor/documenthandler.h +++ b/src/utils/editor/documenthandler.h @@ -1,389 +1,389 @@ /**************************************************************************** * * ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef DOCUMENTHANDLER_H #define DOCUMENTHANDLER_H #include #include #include #include #include #include #include #ifndef STATIC_MAUIKIT #include "mauikit_export.h" #endif QT_BEGIN_NAMESPACE class QFileSystemWatcher; class QTextDocument; class QQuickTextDocument; QT_END_NAMESPACE namespace KSyntaxHighlighting { class Repository; class SyntaxHighlighter; } struct AlertAction { QString label; std::function action; } ; class DocumentAlert : public QObject { Q_OBJECT Q_PROPERTY(QString title MEMBER m_title CONSTANT FINAL) Q_PROPERTY(QString body MEMBER m_body CONSTANT FINAL) Q_PROPERTY(uint level MEMBER m_level CONSTANT FINAL) public: enum LEVEL : uint { INFO_LEVEL = 0, WARNING_LEVEL = 1, DANGER_LEVEL = 2 }; DocumentAlert(const QString &title, const QString &body, const uint &level, const int &id, QObject *parent = nullptr) : QObject(parent) { this->m_title = title; this->m_body = body; this->m_level = level; this->m_id = id; } void setIndex(const int &index) { this->m_index = index; } void setActions(QVector actions) { this->m_actions = actions; } int getId() const { return this->m_id; } friend bool operator==(const DocumentAlert &other, const DocumentAlert &other2) { return other.getId()== other2.getId(); } private: QString m_title; QString m_body; uint m_level; int m_index = -1; int m_id = -1; QVector m_actions; public slots: QStringList actionLabels() const { return std::accumulate(this->m_actions.constBegin(), this->m_actions.constEnd(), QStringList(), [](QStringList &labels, const AlertAction &action) -> QStringList { labels << action.label; return labels; }); } void triggerAction(const int &actionIndex, const int &alertIndex) { qDebug()<< "TRIGGERING DOCUMENT ACTION AT INDEX << " << actionIndex << alertIndex; this->m_actions.at(actionIndex).action(); emit this->done(alertIndex); } signals: void done(int index); }; class Alerts : public QAbstractListModel { Q_OBJECT public: enum ROLES : uint { ALERT = Qt::DisplayRole + 1 }; enum ALERT_TYPES : uint { MISSING, UNSAVED, MODIFIED, SAVE_ERROR }; explicit Alerts(QObject *parent = nullptr); ~Alerts(); QVariant data(const QModelIndex & index, int role) const override final; int rowCount(const QModelIndex &parent = QModelIndex()) const override final; QHash roleNames() const override; void append(DocumentAlert *alert); private: QVector m_alerts; bool contains(DocumentAlert * const alert); }; class FileLoader : public QObject { Q_OBJECT public slots: void loadFile(const QUrl &url); signals: void fileReady(QString array, QUrl url); }; #ifdef STATIC_MAUIKIT class DocumentHandler : public QObject #else class MAUIKIT_EXPORT DocumentHandler : public QObject #endif { Q_OBJECT Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged) Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged) Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor NOTIFY textColorChanged) Q_PROPERTY(QString fontFamily READ fontFamily WRITE setFontFamily NOTIFY fontFamilyChanged) Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged) Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY boldChanged) Q_PROPERTY(bool uppercase READ uppercase WRITE setUppercase NOTIFY uppercaseChanged) Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY italicChanged) Q_PROPERTY(bool underline READ underline WRITE setUnderline NOTIFY underlineChanged) Q_PROPERTY(bool isRich READ getIsRich NOTIFY isRichChanged) Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged) Q_PROPERTY(QString fileName READ fileName NOTIFY fileUrlChanged) Q_PROPERTY(QString fileType READ fileType NOTIFY fileUrlChanged) Q_PROPERTY(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(bool externallyModified READ getExternallyModified WRITE setExternallyModified NOTIFY externallyModifiedChanged) Q_PROPERTY(bool modified READ getModified NOTIFY modifiedChanged) Q_PROPERTY(bool autoReload READ getAutoReload WRITE setAutoReload NOTIFY autoReloadChanged) Q_PROPERTY(QString formatName READ formatName WRITE setFormatName NOTIFY formatNameChanged) Q_PROPERTY(Alerts *alerts READ getAlerts CONSTANT FINAL) Q_PROPERTY(QColor backgroundColor READ getBackgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged) public: explicit DocumentHandler(QObject *parent = nullptr); ~DocumentHandler(); QQuickTextDocument *document() const; void setDocument(QQuickTextDocument *document); int cursorPosition() const; void setCursorPosition(int position); int selectionStart() const; void setSelectionStart(int position); int selectionEnd() const; void setSelectionEnd(int position); QString fontFamily() const; void setFontFamily(const QString &family); QColor textColor() const; void setTextColor(const QColor &color); Qt::Alignment alignment() const; void setAlignment(Qt::Alignment alignment); bool bold() const; void setBold(bool bold); bool uppercase() const; void setUppercase(bool uppercase); bool italic() const; void setItalic(bool italic); bool underline() const; void setUnderline(bool underline); bool getIsRich() const; int fontSize() const; void setFontSize(int size); QString fileName() const; QString fileType() const; QUrl fileUrl() const; void setFileUrl(const QUrl &url); inline QString text() const { return m_text; } void setText(const QString &text); bool getAutoReload() const; void setAutoReload(const bool &value); bool getModified() const; bool getExternallyModified() const; void setExternallyModified(const bool &value); QString formatName() const; void setFormatName(const QString &formatName); QColor getBackgroundColor() const; void setBackgroundColor(const QColor &color); Alerts *getAlerts() const; public slots: - void load(const QUrl &fileUrl); - void saveAs(const QUrl &fileUrl); + void load(const QUrl &url); + void saveAs(const QUrl &url); static const QStringList getLanguageNameList(); static const QString getLanguageNameFromFileName(const QUrl &fileName); signals: void documentChanged(); void cursorPositionChanged(); void selectionStartChanged(); void selectionEndChanged(); void fontFamilyChanged(); void textColorChanged(); void alignmentChanged(); void boldChanged(); void uppercaseChanged(); void italicChanged(); void underlineChanged(); void isRichChanged(); void fontSizeChanged(); void textChanged(); void fileUrlChanged(); void loaded(const QUrl &url); void error(const QString &message); void loadFile(QUrl url); void autoReloadChanged(); void externallyModifiedChanged(); void backgroundColorChanged(); void formatNameChanged() const; void modifiedChanged(); private: void reset(); void setStyle(); QTextCursor textCursor() const; QTextDocument *textDocument() const; void mergeFormatOnWordOrSelection(const QTextCharFormat &format); QQuickTextDocument *m_document; QFileSystemWatcher *m_watcher; int m_cursorPosition; int m_selectionStart; int m_selectionEnd; bool isRich = false; QFont m_font; int m_fontSize; QUrl m_fileUrl; QThread m_worker; QString m_text; bool m_autoReload = false; bool m_externallyModified = false; bool m_internallyModified = false; QColor m_backgroundColor; static int m_instanceCount; QString m_formatName; static KSyntaxHighlighting::Repository *m_repository; KSyntaxHighlighting::SyntaxHighlighter *m_highlighter; Alerts *m_alerts; DocumentAlert * missingAlert(); DocumentAlert * externallyModifiedAlert(); DocumentAlert * canNotSaveAlert(const QString &details); }; #endif // DOCUMENTHANDLER_H