1 | /* |
2 | * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) |
3 | * |
4 | * This program is free software: you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation, either version 3 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
16 | */ |
17 | #include "todoparser.h" |
18 | #include "mainwindow.h" |
19 | #include "editor.h" |
20 | #include "editorlist.h" |
21 | #include "HighlighterManager.h" |
22 | #include "qsynedit/Constants.h" |
23 | |
24 | TodoParser::TodoParser(QObject *parent) : QObject(parent), |
25 | mMutex(QMutex::Recursive) |
26 | { |
27 | mThread = nullptr; |
28 | } |
29 | |
30 | void TodoParser::parseFile(const QString &filename) |
31 | { |
32 | QMutexLocker locker(&mMutex); |
33 | if (mThread) { |
34 | return; |
35 | } |
36 | mThread = new TodoThread(filename); |
37 | connect(mThread,&QThread::finished, |
38 | [this] { |
39 | QMutexLocker locker(&mMutex); |
40 | if (mThread) { |
41 | mThread->deleteLater(); |
42 | mThread = nullptr; |
43 | } |
44 | }); |
45 | connect(mThread, &TodoThread::parseStarted, |
46 | pMainWindow, &MainWindow::onTodoParseStarted); |
47 | connect(mThread, &TodoThread::todoFound, |
48 | pMainWindow, &MainWindow::onTodoParsing); |
49 | connect(mThread, &TodoThread::parseFinished, |
50 | pMainWindow, &MainWindow::onTodoParseFinished); |
51 | mThread->start(); |
52 | } |
53 | |
54 | bool TodoParser::parsing() const |
55 | { |
56 | return (mThread!=nullptr); |
57 | } |
58 | |
59 | TodoThread::TodoThread(const QString& filename, QObject *parent): QThread(parent) |
60 | { |
61 | mFilename = filename; |
62 | } |
63 | |
64 | void TodoThread::run() |
65 | { |
66 | QSynedit::PHighlighter highlighter = highlighterManager.getCppHighlighter(); |
67 | emit parseStarted(mFilename); |
68 | auto action = finally([this]{ |
69 | emit parseFinished(); |
70 | }); |
71 | QStringList lines; |
72 | if (!pMainWindow->editorList()->getContentFromOpenedEditor(mFilename,lines)) { |
73 | return; |
74 | } |
75 | QSynedit::PHighlighterAttribute = highlighter->getAttribute(SYNS_AttrComment); |
76 | |
77 | highlighter->resetState(); |
78 | for (int i =0;i<lines.count();i++) { |
79 | highlighter->setLine(lines[i],i); |
80 | while (!highlighter->eol()) { |
81 | QSynedit::PHighlighterAttribute attr; |
82 | attr = highlighter->getTokenAttribute(); |
83 | if (attr == commentAttr) { |
84 | QString token = highlighter->getToken(); |
85 | int pos = token.indexOf("TODO:" ,0,Qt::CaseInsensitive); |
86 | if (pos>=0) { |
87 | emit todoFound( |
88 | mFilename, |
89 | i+1, |
90 | pos+highlighter->getTokenPos(), |
91 | lines[i].trimmed() |
92 | ); |
93 | } |
94 | } |
95 | highlighter->next(); |
96 | } |
97 | } |
98 | } |
99 | |
100 | TodoModel::TodoModel(QObject *parent) : QAbstractListModel(parent) |
101 | { |
102 | |
103 | } |
104 | |
105 | void TodoModel::addItem(const QString &filename, int lineNo, int ch, const QString &line) |
106 | { |
107 | beginInsertRows(QModelIndex(),mItems.count(),mItems.count()); |
108 | PTodoItem item = std::make_shared<TodoItem>(); |
109 | item->filename = filename; |
110 | item->lineNo = lineNo; |
111 | item->ch = ch; |
112 | item->line = line; |
113 | mItems.append(item); |
114 | endInsertRows(); |
115 | } |
116 | |
117 | void TodoModel::clear() |
118 | { |
119 | beginResetModel(); |
120 | mItems.clear(); |
121 | endResetModel(); |
122 | } |
123 | |
124 | PTodoItem TodoModel::getItem(const QModelIndex &index) |
125 | { |
126 | if (!index.isValid()) |
127 | return PTodoItem(); |
128 | return mItems[index.row()]; |
129 | } |
130 | |
131 | int TodoModel::rowCount(const QModelIndex &) const |
132 | { |
133 | return mItems.count(); |
134 | } |
135 | |
136 | QVariant TodoModel::data(const QModelIndex &index, int role) const |
137 | { |
138 | if (!index.isValid()) |
139 | return QVariant(); |
140 | if (role==Qt::DisplayRole) { |
141 | PTodoItem item = mItems[index.row()]; |
142 | switch(index.column()) { |
143 | case 0: |
144 | return item->filename; |
145 | case 1: |
146 | return item->lineNo; |
147 | case 2: |
148 | return item->ch; |
149 | case 3: |
150 | return item->line; |
151 | } |
152 | } |
153 | return QVariant(); |
154 | } |
155 | |
156 | QVariant TodoModel::(int section, Qt::Orientation orientation, int role) const |
157 | { |
158 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { |
159 | switch(section) { |
160 | case 0: |
161 | return tr("Filename" ); |
162 | case 1: |
163 | return tr("Line" ); |
164 | case 2: |
165 | return tr("Column" ); |
166 | case 3: |
167 | return tr("Content" ); |
168 | } |
169 | } |
170 | return QVariant(); |
171 | } |
172 | |
173 | int TodoModel::columnCount(const QModelIndex &) const |
174 | { |
175 | return 4; |
176 | } |
177 | |