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 "bookmarkmodel.h" |
18 | #include "../systemconsts.h" |
19 | |
20 | #include <QFile> |
21 | #include <QFileInfo> |
22 | #include <QJsonArray> |
23 | #include <QJsonDocument> |
24 | #include <QJsonObject> |
25 | #include <QJsonParseError> |
26 | #include <QSet> |
27 | #include "../utils.h" |
28 | |
29 | BookmarkModel::BookmarkModel(QObject* parent):QAbstractTableModel(parent) |
30 | { |
31 | |
32 | } |
33 | |
34 | QSet<int> BookmarkModel::bookmarksInFile(const QString &filename) |
35 | { |
36 | QSet<int> lines; |
37 | foreach (const PBookmark& bookmark, mBookmarks) { |
38 | if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0) { |
39 | lines.insert(bookmark->line); |
40 | } |
41 | } |
42 | return lines; |
43 | } |
44 | |
45 | void BookmarkModel::addBookmark(const QString &filename, int line, const QString &description) |
46 | { |
47 | Q_ASSERT(!isBookmarkExists(filename,line)); |
48 | PBookmark bookmark = std::make_shared<Bookmark>(); |
49 | bookmark->filename = filename; |
50 | bookmark->line = line; |
51 | bookmark->description = description; |
52 | beginInsertRows(QModelIndex(),mBookmarks.count(),mBookmarks.count()); |
53 | mBookmarks.append(bookmark); |
54 | endInsertRows(); |
55 | } |
56 | |
57 | PBookmark BookmarkModel::bookmark(int i) |
58 | { |
59 | return mBookmarks[i]; |
60 | } |
61 | |
62 | PBookmark BookmarkModel::bookmark(const QString &filename, int line) |
63 | { |
64 | for (int i=0;i<mBookmarks.count();i++) { |
65 | PBookmark bookmark = mBookmarks[i]; |
66 | if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0 |
67 | && bookmark->line == line) { |
68 | return bookmark; |
69 | } |
70 | } |
71 | return PBookmark(); |
72 | } |
73 | |
74 | bool BookmarkModel::removeBookmark(const QString &filename, int line) |
75 | { |
76 | for (int i=0;i<mBookmarks.count();i++) { |
77 | PBookmark bookmark = mBookmarks[i]; |
78 | if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0 |
79 | && bookmark->line == line) { |
80 | removeBookmarkAt(i); |
81 | return true; |
82 | } |
83 | } |
84 | return false; |
85 | } |
86 | |
87 | void BookmarkModel::removeBookmarks(const QString &filename) |
88 | { |
89 | for (int i=mBookmarks.count()-1;i>=0;i--) { |
90 | PBookmark bookmark = mBookmarks[i]; |
91 | if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0) { |
92 | removeBookmarkAt(i); |
93 | } |
94 | } |
95 | } |
96 | |
97 | void BookmarkModel::clear() |
98 | { |
99 | beginResetModel(); |
100 | mBookmarks.clear(); |
101 | endResetModel(); |
102 | } |
103 | |
104 | bool BookmarkModel::updateDescription(const QString &filename, int line, const QString &description) |
105 | { |
106 | for (int i=0;i<mBookmarks.count();i++) { |
107 | PBookmark bookmark = mBookmarks[i]; |
108 | if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0 |
109 | && bookmark->line == line) { |
110 | bookmark->description = description; |
111 | emit dataChanged(createIndex(i,0),createIndex(i,2)); |
112 | return true; |
113 | } |
114 | } |
115 | return false; |
116 | } |
117 | |
118 | void BookmarkModel::save(const QString &filename) |
119 | { |
120 | QFile file(filename); |
121 | if (file.open(QFile::WriteOnly | QFile::Truncate)) { |
122 | QJsonArray array; |
123 | foreach (const PBookmark& bookmark, mBookmarks) { |
124 | QJsonObject obj; |
125 | obj["filename" ]=bookmark->filename; |
126 | obj["line" ]=bookmark->line; |
127 | obj["description" ]=bookmark->description; |
128 | array.append(obj); |
129 | } |
130 | QJsonDocument doc; |
131 | doc.setArray(array); |
132 | if (file.write(doc.toJson())<0) { |
133 | throw FileError(tr("Save file '%1' failed." ) |
134 | .arg(filename)); |
135 | } |
136 | } else { |
137 | throw FileError(tr("Can't open file '%1' for write." ) |
138 | .arg(filename)); |
139 | } |
140 | } |
141 | |
142 | void BookmarkModel::load(const QString& filename) |
143 | { |
144 | clear(); |
145 | QFile file(filename); |
146 | if (!file.exists()) |
147 | return; |
148 | if (file.open(QFile::ReadOnly)) { |
149 | QByteArray content = file.readAll(); |
150 | QJsonParseError error; |
151 | QJsonDocument doc(QJsonDocument::fromJson(content,&error)); |
152 | if (error.error != QJsonParseError::NoError) { |
153 | throw FileError(tr("Error in json file '%1':%2 : %3" ) |
154 | .arg(filename) |
155 | .arg(error.offset) |
156 | .arg(error.errorString())); |
157 | } |
158 | QJsonArray array = doc.array(); |
159 | for (int i=0;i<array.count();i++) { |
160 | QJsonValue value = array[i]; |
161 | QJsonObject obj=value.toObject(); |
162 | addBookmark( QFileInfo(obj["filename" ].toString()).absoluteFilePath(), |
163 | obj["line" ].toInt(), |
164 | obj["description" ].toString()); |
165 | |
166 | } |
167 | } else { |
168 | throw FileError(tr("Can't open file '%1' for read." ) |
169 | .arg(filename)); |
170 | } |
171 | } |
172 | |
173 | void BookmarkModel::onFileDeleteLines(const QString &filename, int startLine, int count) |
174 | { |
175 | for (int i = mBookmarks.count()-1;i>=0;i--){ |
176 | PBookmark bookmark = mBookmarks[i]; |
177 | if (bookmark->filename == filename |
178 | && bookmark->line>=startLine) { |
179 | if (bookmark->line >= startLine+count) { |
180 | bookmark->line -= count; |
181 | emit dataChanged(createIndex(i,0),createIndex(i,2)); |
182 | } else { |
183 | removeBookmarkAt(i); |
184 | } |
185 | } |
186 | } |
187 | } |
188 | |
189 | void BookmarkModel::onFileInsertLines(const QString &filename, int startLine, int count) |
190 | { |
191 | for (int i = mBookmarks.count()-1;i>=0;i--){ |
192 | PBookmark bookmark = mBookmarks[i]; |
193 | if (bookmark->filename == filename |
194 | && bookmark->line>=startLine) { |
195 | bookmark->line+=count; |
196 | emit dataChanged(createIndex(i,0),createIndex(i,2)); |
197 | } |
198 | } |
199 | } |
200 | |
201 | void BookmarkModel::removeBookmarkAt(int i) |
202 | { |
203 | beginRemoveRows(QModelIndex(), i,i); |
204 | mBookmarks.removeAt(i); |
205 | endRemoveRows(); |
206 | } |
207 | |
208 | bool BookmarkModel::isBookmarkExists(const QString &filename, int line) |
209 | { |
210 | foreach (const PBookmark& bookmark, mBookmarks) { |
211 | if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0 |
212 | && bookmark->line == line) { |
213 | return true; |
214 | } |
215 | } |
216 | return false; |
217 | } |
218 | |
219 | int BookmarkModel::rowCount(const QModelIndex &) const |
220 | { |
221 | return mBookmarks.count(); |
222 | } |
223 | |
224 | QVariant BookmarkModel::data(const QModelIndex &index, int role) const |
225 | { |
226 | if (!index.isValid()) |
227 | return QVariant(); |
228 | int row = index.row(); |
229 | PBookmark bookmark = mBookmarks[row]; |
230 | if (role == Qt::DisplayRole) { |
231 | switch(index.column()) { |
232 | case 0: |
233 | return bookmark->description; |
234 | case 1: |
235 | return bookmark->line; |
236 | case 2: |
237 | return bookmark->filename; |
238 | } |
239 | } |
240 | return QVariant(); |
241 | } |
242 | |
243 | int BookmarkModel::columnCount(const QModelIndex &) const |
244 | { |
245 | return 3; |
246 | } |
247 | |
248 | QVariant BookmarkModel::(int section, Qt::Orientation orientation, int role) const |
249 | { |
250 | if (orientation == Qt::Horizontal) { |
251 | if (role == Qt::DisplayRole) { |
252 | switch(section) { |
253 | case 0: |
254 | return tr("Description" ); |
255 | case 1: |
256 | return tr("Line" ); |
257 | case 2: |
258 | return tr("Filename" ); |
259 | } |
260 | } |
261 | } |
262 | return QVariant(); |
263 | } |
264 | |
265 | |