1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "annotation.h"
27
28 #include <QDateTime>
29 #include <QJsonArray>
30 #include <QString>
31
32 namespace QmlDesigner {
33
34 static const QString s_sep = " //;;// "; //separator
35
Comment()36 Comment::Comment()
37 : m_title(QString())
38 , m_author(QString())
39 , m_text(QString())
40 , m_timestamp(0)
41 {}
42
Comment(const QString & title,const QString & author,const QString & text,qint64 timestamp)43 Comment::Comment(const QString &title, const QString &author, const QString &text, qint64 timestamp)
44 : m_title(title)
45 , m_author(author)
46 , m_text(text)
47 , m_timestamp(timestamp)
48 {}
49
title() const50 QString Comment::title() const
51 {
52 return m_title;
53 }
54
setTitle(const QString & title)55 void Comment::setTitle(const QString &title)
56 {
57 m_title = title;
58 }
59
author() const60 QString Comment::author() const
61 {
62 return m_author;
63 }
64
setAuthor(const QString & author)65 void Comment::setAuthor(const QString &author)
66 {
67 m_author = author;
68 }
69
text() const70 QString Comment::text() const
71 {
72 return m_text;
73 }
74
setText(const QString & text)75 void Comment::setText(const QString &text)
76 {
77 m_text = text;
78 }
79
deescapedText() const80 QString Comment::deescapedText() const
81 {
82 QString result = m_text;
83
84 result.replace(QStringLiteral("*\\/"), QStringLiteral("*/"));
85 result.replace(QStringLiteral("\\n"), QStringLiteral("\n"));
86 result.replace(QStringLiteral("\\r"), QStringLiteral("\r"));
87 result.replace(QStringLiteral("\\t"), QStringLiteral("\t"));
88 result.replace(QStringLiteral("\\\""), QStringLiteral("\""));
89 result.replace(QStringLiteral("\\\'"), QStringLiteral("\'"));
90 result.replace(QStringLiteral("\\\\"), QStringLiteral("\\"));
91
92 return result;
93 }
94
timestampStr() const95 QString Comment::timestampStr() const
96 {
97 return QDateTime::fromSecsSinceEpoch(m_timestamp).toString();
98 }
99
timestampStr(const QString & format) const100 QString Comment::timestampStr(const QString &format) const
101 {
102 return QDateTime::fromSecsSinceEpoch(m_timestamp).toString(format);
103 }
104
timestamp() const105 qint64 Comment::timestamp() const
106 {
107 return m_timestamp;
108 }
109
setTimestamp(qint64 timestamp)110 void Comment::setTimestamp(qint64 timestamp)
111 {
112 m_timestamp = timestamp;
113 }
114
updateTimestamp()115 void Comment::updateTimestamp()
116 {
117 m_timestamp = QDateTime::currentSecsSinceEpoch();
118 }
119
sameContent(const Comment & comment) const120 bool Comment::sameContent(const Comment &comment) const
121 {
122 return sameContent(*this, comment);
123 }
124
sameContent(const Comment & a,const Comment & b)125 bool Comment::sameContent(const Comment &a, const Comment &b)
126 {
127 return ((a.title() == b.title())
128 && (a.author() == b.author())
129 && (a.text() == b.text()));
130 }
131
operator ==(const Comment & comment) const132 bool Comment::operator==(const Comment &comment) const
133 {
134 return (sameContent(comment) && (m_timestamp == comment.timestamp()));
135 }
136
isEmpty() const137 bool Comment::isEmpty() const
138 {
139 return sameContent(Comment());
140 }
141
toQString() const142 QString Comment::toQString() const
143 {
144 QStringList result;
145
146 result.push_back(m_title);
147 result.push_back(m_author);
148 result.push_back(m_text);
149 result.push_back(QString::number(m_timestamp));
150
151 return result.join(s_sep);
152 }
153
toJsonValue() const154 QJsonValue Comment::toJsonValue() const
155 {
156 return QJsonObject{
157 {{"title", m_title}, {"author", m_author}, {"text", m_text}, {"timestamp", m_timestamp}}};
158 };
159
fromJsonValue(QJsonValue const & v)160 bool Comment::fromJsonValue(QJsonValue const &v)
161 {
162 if (!v.isObject())
163 return false;
164
165 auto obj = v.toObject();
166 Comment comment;
167 comment.m_title = obj["title"].toString();
168 comment.m_author = obj["author"].toString();
169 comment.m_text = obj["text"].toString();
170 comment.m_timestamp = obj["timestamp"].toInt();
171 *this = comment;
172 return true;
173 }
174
operator <<(QDebug & stream,const Comment & comment)175 QDebug &operator<<(QDebug &stream, const Comment &comment)
176 {
177 stream << "\"title: " << comment.m_title << "\" ";
178 stream << "\"author: " << comment.m_author << "\" ";
179 stream << "\"text: " << comment.m_text << "\" ";
180 stream << "\"timestamp: " << comment.m_timestamp << "\" ";
181 stream << "\"date/time: " << QDateTime::fromSecsSinceEpoch(comment.m_timestamp).toString() << "\" ";
182
183 return stream;
184 }
185
operator <<(QDataStream & stream,const Comment & comment)186 QDataStream &operator<<(QDataStream &stream, const Comment &comment)
187 {
188 stream << comment.m_title;
189 stream << comment.m_author;
190 stream << comment.m_text;
191 stream << comment.m_timestamp;
192
193 return stream;
194 }
195
operator >>(QDataStream & stream,Comment & comment)196 QDataStream &operator>>(QDataStream &stream, Comment &comment)
197 {
198 stream >> comment.m_title;
199 stream >> comment.m_author;
200 stream >> comment.m_text;
201 stream >> comment.m_timestamp;
202
203 return stream;
204 }
205
206
207 //Annotation
208
Annotation()209 Annotation::Annotation()
210 : m_comments()
211 {
212
213 }
214
comments() const215 QVector<Comment> Annotation::comments() const
216 {
217 return m_comments;
218 }
219
220
hasComments() const221 bool Annotation::hasComments() const
222 {
223 return !m_comments.isEmpty();
224 }
225
setComments(const QVector<Comment> & comments)226 void Annotation::setComments(const QVector<Comment> &comments)
227 {
228 m_comments = comments;
229 }
230
removeComments()231 void Annotation::removeComments()
232 {
233 m_comments.clear();
234 }
235
commentsSize() const236 int Annotation::commentsSize() const
237 {
238 return m_comments.size();
239 }
240
comment(int n) const241 Comment Annotation::comment(int n) const
242 {
243 if (m_comments.size() > n)
244 return m_comments.at(n);
245 else
246 return Comment();
247 }
248
addComment(const Comment & comment)249 void Annotation::addComment(const Comment &comment)
250 {
251 m_comments.push_back(comment);
252 }
253
updateComment(const Comment & comment,int n)254 bool Annotation::updateComment(const Comment &comment, int n)
255 {
256 bool result = false;
257
258 if ((m_comments.size() > n) && (n > 0)) {
259 m_comments[n] = comment;
260 result = true;
261 }
262
263 return result;
264 }
265
removeComment(int n)266 bool Annotation::removeComment(int n)
267 {
268 bool result = false;
269
270 if (m_comments.size() > n) {
271 m_comments.remove(n);
272 result = true;
273 }
274
275 return result;
276 }
277
toQString() const278 QString Annotation::toQString() const
279 {
280 QStringList result;
281
282 result.push_back(QString::number(m_comments.size()));
283
284 for (const Comment &com : m_comments)
285 result.push_back(com.toQString());
286
287 return result.join(s_sep);
288 }
289
fromQString(const QString & str)290 void Annotation::fromQString(const QString &str)
291 {
292 QStringList strl (str.split(s_sep, Qt::KeepEmptyParts));
293 removeComments();
294
295 const int intro = 1;
296 const int comSize = 4;
297
298 if (!strl.isEmpty()) {
299
300 if (strl.size() >= intro) {
301
302 int size = strl.at(0).toInt();
303
304 if (size > 0) {
305 if (strl.size() == (size*comSize) + intro)
306 {
307 for (int i = 0; i < size; i++)
308 {
309 const int offset = intro + (i * comSize);
310 Comment com;
311 com.setTitle(strl.at(offset + 0));
312 com.setAuthor(strl.at(offset + 1));
313 com.setText(strl.at(offset + 2));
314 com.setTimestamp(strl.at(offset + 3).toLongLong());
315
316 m_comments.push_back(com);
317 }
318 }
319 }
320 }
321 }
322 }
323
toJsonValue() const324 QJsonValue Annotation::toJsonValue() const
325 {
326 QJsonObject obj;
327 QJsonArray comments;
328 for (auto &comment : m_comments)
329 comments.push_back(comment.toJsonValue());
330
331 obj["comments"] = comments;
332 return obj;
333 }
334
fromJsonValue(const QJsonValue & v)335 bool Annotation::fromJsonValue(const QJsonValue &v)
336 {
337 if (!v.isObject())
338 return false;
339
340 auto obj = v.toObject();
341 auto jsonComments = obj["comments"].toArray();
342 m_comments.clear();
343 for (auto json : jsonComments) {
344 Comment comment;
345 if (comment.fromJsonValue(json))
346 m_comments.push_back(comment);
347 }
348 return true;
349 }
350
operator <<(QDebug & stream,const Annotation & annotation)351 QDebug &operator<<(QDebug &stream, const Annotation &annotation)
352 {
353 stream << "\"Annotation: " << annotation.m_comments << "\" ";
354
355 return stream;
356 }
357
operator <<(QDataStream & stream,const Annotation & annotation)358 QDataStream &operator<<(QDataStream &stream, const Annotation &annotation)
359 {
360 stream << annotation.m_comments;
361
362 return stream;
363 }
364
operator >>(QDataStream & stream,Annotation & annotation)365 QDataStream &operator>>(QDataStream &stream, Annotation &annotation)
366 {
367 stream >> annotation.m_comments;
368
369 return stream;
370 }
371
GlobalAnnotationStatus()372 GlobalAnnotationStatus::GlobalAnnotationStatus()
373 : m_status(GlobalAnnotationStatus::Status::NoStatus)
374 { }
375
GlobalAnnotationStatus(GlobalAnnotationStatus::Status status)376 GlobalAnnotationStatus::GlobalAnnotationStatus(GlobalAnnotationStatus::Status status)
377 : m_status(status)
378 { }
379
setStatus(int statusId)380 void GlobalAnnotationStatus::setStatus(int statusId)
381 {
382 switch (statusId) {
383 case 0: m_status = GlobalAnnotationStatus::Status::InProgress; break;
384 case 1: m_status = GlobalAnnotationStatus::Status::InReview; break;
385 case 2: m_status = GlobalAnnotationStatus::Status::Done; break;
386 case -1:
387 default: m_status = GlobalAnnotationStatus::Status::NoStatus; break;
388 }
389 }
390
setStatus(GlobalAnnotationStatus::Status status)391 void GlobalAnnotationStatus::setStatus(GlobalAnnotationStatus::Status status)
392 {
393 m_status = status;
394 }
395
status() const396 GlobalAnnotationStatus::Status GlobalAnnotationStatus::status() const
397 {
398 return m_status;
399 }
400
toQString() const401 QString GlobalAnnotationStatus::toQString() const
402 {
403 return QString::number(static_cast<int>(m_status));
404 }
405
fromQString(const QString & str)406 void GlobalAnnotationStatus::fromQString(const QString &str)
407 {
408 bool result = false;
409 int conversion = str.toInt(&result);
410
411 if (result) {
412 setStatus(conversion);
413 }
414 else {
415 m_status = GlobalAnnotationStatus::Status::NoStatus;
416 }
417 }
418
419 } // QmlDesigner namespace
420