codeeditorhelper.h 4.63 KB
Newer Older
1
2
3
4
5
6
7
8
#ifndef CODEEDITORHELPER_H
#define CODEEDITORHELPER_H

#include <QQuickTextDocument>
#include <QtDebug>
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QRegularExpression>
Leander Schulten's avatar
Leander Schulten committed
9
#include <programms/modulemanager.h>
10
#include <QSortFilterProxyModel>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

// Highlight code from https://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html
class CodeHighlighter : public QSyntaxHighlighter{
private:
    struct HighlightingRule
    {
        QRegularExpression pattern;
        QTextCharFormat format;
    };
    QVector<HighlightingRule> highlightingRules;

    QRegularExpression commentStartExpression;
    QRegularExpression commentEndExpression;

    QTextCharFormat keywordFormat;
    QTextCharFormat classFormat;
    QTextCharFormat singleLineCommentFormat;
    QTextCharFormat multiLineCommentFormat;
    QTextCharFormat quotationFormat;
    QTextCharFormat functionFormat;
protected:
    void highlightBlock(const QString &text) override;
public:
    CodeHighlighter(QTextDocument * doc);
    CodeHighlighter(const CodeHighlighter &) = delete ;
};

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class CodeCompletionEntry : public QObject{
    Q_OBJECT
public:
    const QString type;
    const QString description;
    const QString completion;
    const bool closeAfterCompletion;
    Q_PROPERTY(QString type MEMBER type CONSTANT)
    Q_PROPERTY(QString description MEMBER description CONSTANT)
    Q_PROPERTY(QString completion MEMBER completion CONSTANT)
    Q_PROPERTY(bool closeAfterCompletion MEMBER closeAfterCompletion CONSTANT)
public:
    CodeCompletionEntry(QString completion,QString type,QString description,bool closeAfterCompletion = true):type(type.trimmed()),description(description),completion(completion.trimmed()),closeAfterCompletion(closeAfterCompletion){

    }
};


class PossibleCodeCompletions : public ModelVector<CodeCompletionEntry*>{
  Q_OBJECT
};

class CodeCompletions : public QSortFilterProxyModel{
    Q_OBJECT
public:
    PossibleCodeCompletions model;
    CodeCompletions(){
        setSourceModel(&model);
    }
protected:
    virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right)const override;
    virtual bool filterAcceptsRow(int sourceRow,const QModelIndex &sourceParent) const override;
};

72
73
74
75
class CodeEditorHelper : public QObject
{
    QQuickTextDocument* documentWrapper = nullptr;
    QTextDocument * document = nullptr;
Leander Schulten's avatar
Leander Schulten committed
76
    QMetaObject::Connection typeConnection;
77
78
    CodeCompletions codeCompletions;

79
    Q_PROPERTY(QQuickTextDocument* document READ getDocument WRITE setDocument NOTIFY documentChanged)
Leander Schulten's avatar
Leander Schulten committed
80
    Q_PROPERTY(Modules::Module* module READ getModule WRITE setModule NOTIFY moduleChanged)
81
    Q_PROPERTY(QAbstractItemModel * codeCompletions READ getCodeCompletions CONSTANT)
82
83
84
85
86
    Q_OBJECT
    /** Wird automatisch gelöscht, wenn das textdocument zerstört wird
     * @brief highlighter
     */
    CodeHighlighter * highlighter = nullptr;
Leander Schulten's avatar
Leander Schulten committed
87
    Modules::Module * module = nullptr;
88
89
90

protected:
    int countTabs(int startPos);
91
    QString getType(QString variable, int pos);
92
public:
93
94
95
    QAbstractItemModel * getCodeCompletions(){
        return &codeCompletions;
    }
Leander Schulten's avatar
Leander Schulten committed
96

97
    void setModule(  Modules::Module* _module);
Leander Schulten's avatar
Leander Schulten committed
98
99
100
101
    Modules::Module *getModule() const {
            return module;
    }

102
    CodeEditorHelper();
Leander Schulten's avatar
Leander Schulten committed
103
    Q_INVOKABLE void compile();
104
    Q_INVOKABLE void updateCodeCompletionModel(int cursorPosition);
Leander Schulten's avatar
Leander Schulten committed
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
    void setDocument(  QQuickTextDocument* _document){
       if(_document != documentWrapper){
             documentWrapper = _document;
             emit documentChanged();
             qDebug() << "add connection";
             if(documentWrapper){
                QObject::connect(documentWrapper->textDocument(),&QTextDocument::contentsChange,this,&CodeEditorHelper::contentsChange);
                document = documentWrapper->textDocument();
             }else
                document = nullptr;
             if(document && !highlighter){
                 highlighter = new CodeHighlighter(document);
             }else if(document){
                 highlighter->setDocument(document);
             }
       }
    }
   QQuickTextDocument* getDocument() const {
        return documentWrapper;
   }
signals:
127
   void information(QString text);
Leander Schulten's avatar
Leander Schulten committed
128
   void moduleChanged();
129
   void documentChanged();
130
131
132
133
134
   /**
    * @brief insertText send a signal to the qml editor component to inform the component, that text should be inserted at the current cursor pos
    * @param newText the text that should be inserted
    * @param pos the new cursor after text inserting.
    */
135
136
   void insertText(QString newText, int pos);
   protected:
Leander Schulten's avatar
Leander Schulten committed
137
   void typeChanged();
138
139
140
141
142
   void contentsChange(int from, int charsRemoved, int charsAdded);

};

#endif // CODEEDITORHELPER_H