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
24TodoParser::TodoParser(QObject *parent) : QObject(parent),
25 mMutex(QMutex::Recursive)
26{
27 mThread = nullptr;
28}
29
30void 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
54bool TodoParser::parsing() const
55{
56 return (mThread!=nullptr);
57}
58
59TodoThread::TodoThread(const QString& filename, QObject *parent): QThread(parent)
60{
61 mFilename = filename;
62}
63
64void 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 commentAttr = 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
100TodoModel::TodoModel(QObject *parent) : QAbstractListModel(parent)
101{
102
103}
104
105void 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
117void TodoModel::clear()
118{
119 beginResetModel();
120 mItems.clear();
121 endResetModel();
122}
123
124PTodoItem TodoModel::getItem(const QModelIndex &index)
125{
126 if (!index.isValid())
127 return PTodoItem();
128 return mItems[index.row()];
129}
130
131int TodoModel::rowCount(const QModelIndex &) const
132{
133 return mItems.count();
134}
135
136QVariant 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
156QVariant TodoModel::headerData(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
173int TodoModel::columnCount(const QModelIndex &) const
174{
175 return 4;
176}
177