File indexing completed on 2024-05-19 04:48:09
0001 /**************************************************************************** 0002 * * 0003 ** Copyright (C) 2017 The Qt Company Ltd. 0004 ** Contact: https://www.qt.io/licensing/ 0005 ** 0006 ** This file is part of the examples of the Qt Toolkit. 0007 ** 0008 ** $QT_BEGIN_LICENSE:BSD$ 0009 ** Commercial License Usage 0010 ** Licensees holding valid commercial Qt licenses may use this file in 0011 ** accordance with the commercial license agreement provided with the 0012 ** Software or, alternatively, in accordance with the terms contained in 0013 ** a written agreement between you and The Qt Company. For licensing terms 0014 ** and conditions see https://www.qt.io/terms-conditions. For further 0015 ** information use the contact form at https://www.qt.io/contact-us. 0016 ** 0017 ** BSD License Usage 0018 ** Alternatively, you may use this file under the terms of the BSD license 0019 ** as follows: 0020 ** 0021 ** "Redistribution and use in source and binary forms, with or without 0022 ** modification, are permitted provided that the following conditions are 0023 ** met: 0024 ** * Redistributions of source code must retain the above copyright 0025 ** notice, this list of conditions and the following disclaimer. 0026 ** * Redistributions in binary form must reproduce the above copyright 0027 ** notice, this list of conditions and the following disclaimer in 0028 ** the documentation and/or other materials provided with the 0029 ** distribution. 0030 ** * Neither the name of The Qt Company Ltd nor the names of its 0031 ** contributors may be used to endorse or promote products derived 0032 ** from this software without specific prior written permission. 0033 ** 0034 ** 0035 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 0036 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 0037 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 0038 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 0039 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 0040 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 0041 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0042 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0043 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0044 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0045 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 0046 ** 0047 ** $QT_END_LICENSE$ 0048 ** 0049 ****************************************************************************/ 0050 0051 #pragma once 0052 0053 #include <QAbstractListModel> 0054 #include <QDebug> 0055 #include <QFont> 0056 #include <QObject> 0057 #include <QTextCursor> 0058 #include <QThread> 0059 #include <QTimer> 0060 #include <QUrl> 0061 0062 QT_BEGIN_NAMESPACE 0063 class QFileSystemWatcher; 0064 class QTextDocument; 0065 class QQuickTextDocument; 0066 QT_END_NAMESPACE 0067 0068 namespace KSyntaxHighlighting 0069 { 0070 class Repository; 0071 class SyntaxHighlighter; 0072 } 0073 0074 /** 0075 * @brief The AlertAction struct 0076 */ 0077 struct AlertAction { 0078 QString label; 0079 std::function<void()> action; 0080 }; 0081 0082 /** 0083 * @brief The DocumentAlert class 0084 */ 0085 class DocumentAlert : public QObject 0086 { 0087 Q_OBJECT 0088 Q_PROPERTY(QString title MEMBER m_title CONSTANT FINAL) 0089 Q_PROPERTY(QString body MEMBER m_body CONSTANT FINAL) 0090 Q_PROPERTY(uint level MEMBER m_level CONSTANT FINAL) 0091 Q_PROPERTY(QStringList actionLabels READ actionLabels CONSTANT FINAL) 0092 0093 public: 0094 enum LEVEL : uint { INFO_LEVEL = 0, WARNING_LEVEL = 1, DANGER_LEVEL = 2 }; 0095 0096 DocumentAlert(const QString &title, const QString &body, const uint &level, const int &id, QObject *parent = nullptr) 0097 : QObject(parent) 0098 { 0099 this->m_title = title; 0100 this->m_body = body; 0101 this->m_level = level; 0102 this->m_id = id; 0103 } 0104 0105 /** 0106 * @brief setIndex 0107 * @param index 0108 */ 0109 void setIndex(const int &index) 0110 { 0111 this->m_index = index; 0112 } 0113 0114 /** 0115 * @brief setActions 0116 * @param actions 0117 */ 0118 void setActions(QVector<AlertAction> actions) 0119 { 0120 this->m_actions = actions; 0121 } 0122 0123 /** 0124 * @brief getId 0125 * @return 0126 */ 0127 int getId() const 0128 { 0129 return this->m_id; 0130 } 0131 0132 /** 0133 * @brief operator == 0134 * @param other 0135 * @param other2 0136 * @return 0137 */ 0138 friend bool operator==(const DocumentAlert &other, const DocumentAlert &other2) 0139 { 0140 return other.getId() == other2.getId(); 0141 } 0142 0143 /** 0144 * @brief actionLabels 0145 * @return 0146 */ 0147 QStringList actionLabels() const 0148 { 0149 return std::accumulate(this->m_actions.constBegin(), this->m_actions.constEnd(), QStringList(), [](QStringList &labels, const AlertAction &action) -> QStringList { 0150 labels << action.label; 0151 return labels; 0152 }); 0153 } 0154 0155 private: 0156 QString m_title; 0157 QString m_body; 0158 uint m_level; 0159 int m_index = -1; 0160 int m_id = -1; 0161 0162 QVector<AlertAction> m_actions; 0163 0164 public Q_SLOTS: 0165 /** 0166 * @brief triggerAction 0167 * @param actionIndex 0168 * @param alertIndex 0169 */ 0170 void triggerAction(const int &actionIndex, const int &alertIndex) 0171 { 0172 qDebug() << "TRIGGERING DOCUMENT ACTION AT INDEX << " << actionIndex << alertIndex; 0173 this->m_actions.at(actionIndex).action(); 0174 Q_EMIT this->done(alertIndex); 0175 } 0176 0177 Q_SIGNALS: 0178 /** 0179 * @brief done 0180 * @param index 0181 */ 0182 void done(int index); 0183 }; 0184 0185 /** 0186 * @brief The Alerts class 0187 */ 0188 class Alerts : public QAbstractListModel 0189 { 0190 Q_OBJECT 0191 0192 public: 0193 enum ROLES : uint { ALERT = Qt::DisplayRole + 1 }; 0194 0195 enum ALERT_TYPES : uint { MISSING, UNSAVED, MODIFIED, SAVE_ERROR }; 0196 0197 explicit Alerts(QObject *parent = nullptr); 0198 ~Alerts(); 0199 QVariant data(const QModelIndex &index, int role) const override final; 0200 int rowCount(const QModelIndex &parent = QModelIndex()) const override final; 0201 QHash<int, QByteArray> roleNames() const override; 0202 0203 void append(DocumentAlert *alert); 0204 0205 private: 0206 QVector<DocumentAlert *> m_alerts; 0207 bool contains(DocumentAlert *const alert); 0208 }; 0209 0210 /** 0211 * @brief The FileLoader class 0212 */ 0213 class FileLoader : public QObject 0214 { 0215 Q_OBJECT 0216 0217 public Q_SLOTS: 0218 /** 0219 * @brief loadFile 0220 * @param url 0221 */ 0222 void loadFile(const QUrl &url); 0223 0224 Q_SIGNALS: 0225 /** 0226 * @brief fileReady 0227 * @param array 0228 * @param url 0229 */ 0230 void fileReady(QString array, QUrl url); 0231 }; 0232 0233 /** 0234 * @brief The DocumentHandler class 0235 */ 0236 class DocumentHandler : public QObject 0237 { 0238 Q_OBJECT 0239 0240 Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged) 0241 Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) 0242 Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged) 0243 Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) 0244 0245 Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor NOTIFY textColorChanged) 0246 Q_PROPERTY(QString fontFamily READ fontFamily WRITE setFontFamily NOTIFY fontFamilyChanged) 0247 Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged) 0248 0249 Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY boldChanged) 0250 Q_PROPERTY(bool uppercase READ uppercase WRITE setUppercase NOTIFY uppercaseChanged) 0251 Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY italicChanged) 0252 Q_PROPERTY(bool underline READ underline WRITE setUnderline NOTIFY underlineChanged) 0253 Q_PROPERTY(bool isRich READ getIsRich NOTIFY isRichChanged) 0254 0255 Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged) 0256 Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged) 0257 Q_PROPERTY(qreal tabSpace READ tabSpace WRITE setTabSpace NOTIFY tabSpaceChanged) 0258 0259 Q_PROPERTY(QString fileName READ fileName NOTIFY fileUrlChanged) 0260 Q_PROPERTY(QString fileType READ fileType NOTIFY fileUrlChanged) 0261 0262 Q_PROPERTY(QVariantMap fileInfo READ fileInfo NOTIFY fileInfoChanged) 0263 Q_PROPERTY(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged) 0264 0265 Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) 0266 0267 Q_PROPERTY(bool externallyModified READ getExternallyModified WRITE setExternallyModified NOTIFY externallyModifiedChanged) 0268 0269 Q_PROPERTY(bool modified READ getModified NOTIFY modifiedChanged) 0270 0271 Q_PROPERTY(bool autoReload READ getAutoReload WRITE setAutoReload NOTIFY autoReloadChanged) 0272 Q_PROPERTY(bool autoSave READ autoSave WRITE setAutoSave NOTIFY autoSaveChanged) 0273 0274 Q_PROPERTY(QString formatName READ formatName WRITE setFormatName NOTIFY formatNameChanged) 0275 0276 Q_PROPERTY(int currentLineIndex READ getCurrentLineIndex NOTIFY currentLineIndexChanged) 0277 0278 Q_PROPERTY(Alerts *alerts READ getAlerts CONSTANT FINAL) 0279 0280 Q_PROPERTY(QColor backgroundColor READ getBackgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged) 0281 0282 Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged) 0283 0284 Q_PROPERTY(bool enableSyntaxHighlighting READ enableSyntaxHighlighting WRITE setEnableSyntaxHighlighting NOTIFY enableSyntaxHighlightingChanged) 0285 0286 Q_PROPERTY(bool findWholeWords MEMBER m_findWholeWords NOTIFY findWholeWordsChanged) 0287 0288 Q_PROPERTY(bool findCaseSensitively MEMBER m_findCaseSensitively NOTIFY findCaseSensitivelyChanged) 0289 0290 public: 0291 explicit DocumentHandler(QObject *parent = nullptr); 0292 ~DocumentHandler(); 0293 0294 /** 0295 * @brief document 0296 * @return 0297 */ 0298 QQuickTextDocument *document() const; 0299 0300 /** 0301 * @brief setDocument 0302 * @param document 0303 */ 0304 void setDocument(QQuickTextDocument *document); 0305 0306 /** 0307 * @brief cursorPosition 0308 * @return 0309 */ 0310 int cursorPosition() const; 0311 0312 /** 0313 * @brief setCursorPosition 0314 * @param position 0315 */ 0316 void setCursorPosition(int position); 0317 0318 /** 0319 * @brief selectionStart 0320 * @return 0321 */ 0322 int selectionStart() const; 0323 0324 /** 0325 * @brief setSelectionStart 0326 * @param position 0327 */ 0328 void setSelectionStart(int position); 0329 0330 /** 0331 * @brief selectionEnd 0332 * @return 0333 */ 0334 int selectionEnd() const; 0335 0336 /** 0337 * @brief setSelectionEnd 0338 * @param position 0339 */ 0340 void setSelectionEnd(int position); 0341 0342 /** 0343 * @brief fontFamily 0344 * @return 0345 */ 0346 QString fontFamily() const; 0347 0348 /** 0349 * @brief setFontFamily 0350 * @param family 0351 */ 0352 void setFontFamily(const QString &family); 0353 0354 /** 0355 * @brief textColor 0356 * @return 0357 */ 0358 QColor textColor() const; 0359 0360 /** 0361 * @brief setTextColor 0362 * @param color 0363 */ 0364 void setTextColor(const QColor &color); 0365 0366 /** 0367 * @brief alignment 0368 * @return 0369 */ 0370 Qt::Alignment alignment() const; 0371 0372 /** 0373 * @brief setAlignment 0374 * @param alignment 0375 */ 0376 void setAlignment(Qt::Alignment alignment); 0377 0378 /** 0379 * @brief bold 0380 * @return 0381 */ 0382 bool bold() const; 0383 0384 /** 0385 * @brief setBold 0386 * @param bold 0387 */ 0388 void setBold(bool bold); 0389 0390 /** 0391 * @brief uppercase 0392 * @return 0393 */ 0394 bool uppercase() const; 0395 0396 /** 0397 * @brief setUppercase 0398 * @param uppercase 0399 */ 0400 void setUppercase(bool uppercase); 0401 0402 /** 0403 * @brief italic 0404 * @return 0405 */ 0406 bool italic() const; 0407 0408 /** 0409 * @brief setItalic 0410 * @param italic 0411 */ 0412 void setItalic(bool italic); 0413 0414 /** 0415 * @brief underline 0416 * @return 0417 */ 0418 bool underline() const; 0419 0420 /** 0421 * @brief setUnderline 0422 * @param underline 0423 */ 0424 void setUnderline(bool underline); 0425 0426 /** 0427 * @brief getIsRich 0428 * @return 0429 */ 0430 bool getIsRich() const; 0431 0432 /** 0433 * @brief fontSize 0434 * @return 0435 */ 0436 int fontSize() const; 0437 0438 /** 0439 * @brief setFontSize 0440 * @param size 0441 */ 0442 void setFontSize(int size); 0443 0444 qreal tabSpace() const; 0445 void setTabSpace(qreal value); 0446 0447 /** 0448 * @brief fileName 0449 * @return 0450 */ 0451 QString fileName() const; 0452 0453 /** 0454 * @brief fileType 0455 * @return 0456 */ 0457 QString fileType() const; 0458 0459 /** 0460 * @brief fileUrl 0461 * @return 0462 */ 0463 QUrl fileUrl() const; 0464 0465 /** 0466 * @brief setFileUrl 0467 * @param url 0468 */ 0469 void setFileUrl(const QUrl &url); 0470 0471 /** 0472 * @brief fileInfo 0473 * @return 0474 */ 0475 QVariantMap fileInfo() const; 0476 0477 /** 0478 * @brief text 0479 * @return 0480 */ 0481 inline QString text() const 0482 { 0483 return m_text; 0484 } 0485 0486 /** 0487 * @brief setText 0488 * @param text 0489 */ 0490 void setText(const QString &text); 0491 0492 /** 0493 * @brief getAutoReload 0494 * @return 0495 */ 0496 bool getAutoReload() const; 0497 0498 /** 0499 * @brief setAutoReload 0500 * @param value 0501 */ 0502 void setAutoReload(const bool &value); 0503 0504 /** 0505 * @brief autoSave 0506 * @return 0507 */ 0508 bool autoSave() const; 0509 0510 /** 0511 * @brief setAutoSave 0512 * @param value 0513 */ 0514 void setAutoSave(const bool &value); 0515 0516 /** 0517 * @brief getModified 0518 * @return 0519 */ 0520 bool getModified() const; 0521 0522 /** 0523 * @brief getExternallyModified 0524 * @return 0525 */ 0526 bool getExternallyModified() const; 0527 0528 /** 0529 * @brief setExternallyModified 0530 * @param value 0531 */ 0532 void setExternallyModified(const bool &value); 0533 0534 /** 0535 * @brief formatName 0536 * @return 0537 */ 0538 QString formatName() const; 0539 0540 /** 0541 * @brief setFormatName 0542 * @param formatName 0543 */ 0544 void setFormatName(const QString &formatName); 0545 0546 /** 0547 * @brief getBackgroundColor 0548 * @return 0549 */ 0550 QColor getBackgroundColor() const; 0551 0552 /** 0553 * @brief setBackgroundColor 0554 * @param color 0555 */ 0556 void setBackgroundColor(const QColor &color); 0557 0558 /** 0559 * @brief getAlerts 0560 * @return 0561 */ 0562 Alerts *getAlerts() const; 0563 0564 /** 0565 * @brief theme 0566 * @return 0567 */ 0568 QString theme() const; 0569 0570 /** 0571 * @brief setTheme 0572 * @param theme 0573 */ 0574 void setTheme(const QString &theme); 0575 0576 /** 0577 * @brief enableSyntaxHighlighting 0578 * @return 0579 */ 0580 bool enableSyntaxHighlighting() const; 0581 0582 /** 0583 * @brief setEnableSyntaxHighlighting 0584 * @param value 0585 */ 0586 void setEnableSyntaxHighlighting(const bool &value); 0587 0588 /** 0589 * @brief isDark 0590 * @param color 0591 * @return 0592 */ 0593 static bool isDark(const QColor &color) 0594 { 0595 const double darkness = 1 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255; 0596 return (darkness > 0.5); 0597 } 0598 0599 public Q_SLOTS: 0600 /** 0601 * @brief load 0602 * @param url 0603 */ 0604 void load(const QUrl &url); 0605 0606 /** 0607 * @brief saveAs 0608 * @param url 0609 */ 0610 void saveAs(const QUrl &url); 0611 0612 /** 0613 * @brief find 0614 * @param query 0615 */ 0616 void find(const QString &query, const bool &forward = true); 0617 0618 void replace(const QString &query, const QString &value); 0619 0620 void replaceAll(const QString &query, const QString &value); 0621 0622 bool isFoldable(const int &line) const; 0623 bool isFolded(const int &line) const; 0624 void toggleFold(const int &line); 0625 0626 /** 0627 * @brief lineHeight 0628 * @param line 0629 * @return 0630 */ 0631 int lineHeight(const int &line); 0632 0633 int lineCount(); 0634 0635 /** 0636 * @brief getCurrentLineIndex 0637 * @return 0638 */ 0639 int getCurrentLineIndex(); 0640 0641 int goToLine(const int &line); 0642 0643 /** 0644 * @brief getLanguageNameList 0645 * @return 0646 */ 0647 static const QStringList getLanguageNameList(); 0648 0649 /** 0650 * @brief getLanguageNameFromFileName 0651 * @param fileName 0652 * @return 0653 */ 0654 static const QString getLanguageNameFromFileName(const QUrl &fileName); 0655 0656 Q_SIGNALS: 0657 void documentChanged(); 0658 void fileSaved(); 0659 0660 void cursorPositionChanged(); 0661 void selectionStartChanged(); 0662 void selectionEndChanged(); 0663 0664 void fontFamilyChanged(); 0665 void textColorChanged(); 0666 void alignmentChanged(); 0667 0668 void boldChanged(); 0669 void uppercaseChanged(); 0670 void italicChanged(); 0671 void underlineChanged(); 0672 void isRichChanged(); 0673 0674 void lineCountChanged(); 0675 void fontSizeChanged(); 0676 void tabSpaceChanged(); 0677 0678 void textChanged(); 0679 void fileUrlChanged(); 0680 void fileInfoChanged(); 0681 0682 void loaded(const QUrl &url); 0683 void error(const QString &message); 0684 void loadFile(QUrl url); 0685 0686 void autoReloadChanged(); 0687 void autoSaveChanged(); 0688 0689 void externallyModifiedChanged(); 0690 0691 void backgroundColorChanged(); 0692 0693 void formatNameChanged(); 0694 0695 void modifiedChanged(); 0696 0697 void currentLineIndexChanged(); 0698 0699 void enableSyntaxHighlightingChanged(); 0700 void themeChanged(); 0701 0702 void searchFound(int start, int end); 0703 void findCaseSensitivelyChanged(); 0704 void findWholeWordsChanged(); 0705 // void cursorYPosChanged(); 0706 0707 private: 0708 void reset(); 0709 void setStyle(); 0710 0711 QTextCursor textCursor() const; 0712 QTextDocument *textDocument() const; 0713 void mergeFormatOnWordOrSelection(const QTextCharFormat &format); 0714 0715 QQuickTextDocument *m_document; 0716 QFileSystemWatcher *m_watcher; 0717 0718 int m_cursorPosition; 0719 int m_selectionStart; 0720 int m_selectionEnd; 0721 0722 bool isRich = false; 0723 0724 QFont m_font; 0725 int m_fontSize = 12; 0726 qreal m_tabSpace = 8; 0727 0728 QUrl m_fileUrl; 0729 0730 QThread m_worker; 0731 QString m_text; 0732 0733 bool m_autoReload = false; 0734 bool m_autoSave = false; 0735 0736 bool m_externallyModified = false; 0737 bool m_internallyModified = false; 0738 0739 bool m_findCaseSensitively = false; 0740 bool m_findWholeWords = false; 0741 0742 QColor m_backgroundColor; 0743 0744 static int m_instanceCount; 0745 QString m_formatName = "None"; 0746 static KSyntaxHighlighting::Repository *m_repository; 0747 KSyntaxHighlighting::SyntaxHighlighter *m_highlighter; 0748 0749 bool m_enableSyntaxHighlighting = false; 0750 QString m_theme; 0751 0752 QString m_searchQuery; 0753 QString m_replaceText; 0754 0755 Alerts *m_alerts; 0756 DocumentAlert *missingAlert(); 0757 DocumentAlert *externallyModifiedAlert(); 0758 DocumentAlert *canNotSaveAlert(const QString &details); 0759 0760 QTimer m_autoSaveTimer; 0761 0762 void refreshAllBlocks(); 0763 };