// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "annotation.h" #include #include #include namespace QmlDesigner { static const QString s_sep = " //;;// "; //separator Comment::Comment() : m_title(QString()) , m_author(QString()) , m_text(QString()) , m_timestamp(0) {} Comment::Comment(const QString &title, const QString &author, const QString &text, qint64 timestamp) : m_title(title) , m_author(author) , m_text(text) , m_timestamp(timestamp) {} QString Comment::title() const { return m_title; } void Comment::setTitle(const QString &title) { m_title = title; } QString Comment::author() const { return m_author; } void Comment::setAuthor(const QString &author) { m_author = author; } QString Comment::text() const { return m_text; } void Comment::setText(const QString &text) { m_text = text; } QString Comment::deescapedText() const { QString result = m_text; result.replace(QStringLiteral("*\\/"), QStringLiteral("*/")); result.replace(QStringLiteral("\\n"), QStringLiteral("\n")); result.replace(QStringLiteral("\\r"), QStringLiteral("\r")); result.replace(QStringLiteral("\\t"), QStringLiteral("\t")); result.replace(QStringLiteral("\\\""), QStringLiteral("\"")); result.replace(QStringLiteral("\\\'"), QStringLiteral("\'")); result.replace(QStringLiteral("\\\\"), QStringLiteral("\\")); return result; } QString Comment::timestampStr() const { return QDateTime::fromSecsSinceEpoch(m_timestamp).toString(); } QString Comment::timestampStr(const QString &format) const { return QDateTime::fromSecsSinceEpoch(m_timestamp).toString(format); } qint64 Comment::timestamp() const { return m_timestamp; } void Comment::setTimestamp(qint64 timestamp) { m_timestamp = timestamp; } void Comment::updateTimestamp() { m_timestamp = QDateTime::currentSecsSinceEpoch(); } bool Comment::sameContent(const Comment &comment) const { return sameContent(*this, comment); } bool Comment::sameContent(const Comment &a, const Comment &b) { return ((a.title() == b.title()) && (a.author() == b.author()) && (a.text() == b.text())); } bool Comment::operator==(const Comment &comment) const { return (sameContent(comment) && (m_timestamp == comment.timestamp())); } bool Comment::isEmpty() const { return sameContent(Comment()); } QString Comment::toQString() const { QStringList result; result.push_back(m_title); result.push_back(m_author); result.push_back(m_text); result.push_back(QString::number(m_timestamp)); return result.join(s_sep); } QJsonValue Comment::toJsonValue() const { return QJsonObject{ {{"title", m_title}, {"author", m_author}, {"text", m_text}, {"timestamp", m_timestamp}}}; }; bool Comment::fromJsonValue(QJsonValue const &v) { if (!v.isObject()) return false; auto obj = v.toObject(); Comment comment; comment.m_title = obj["title"].toString(); comment.m_author = obj["author"].toString(); comment.m_text = obj["text"].toString(); comment.m_timestamp = obj["timestamp"].toInt(); *this = comment; return true; } QDebug &operator<<(QDebug &stream, const Comment &comment) { stream << "\"title: " << comment.m_title << "\" "; stream << "\"author: " << comment.m_author << "\" "; stream << "\"text: " << comment.m_text << "\" "; stream << "\"timestamp: " << comment.m_timestamp << "\" "; stream << "\"date/time: " << QDateTime::fromSecsSinceEpoch(comment.m_timestamp).toString() << "\" "; return stream; } QDataStream &operator<<(QDataStream &stream, const Comment &comment) { stream << comment.m_title; stream << comment.m_author; stream << comment.m_text; stream << comment.m_timestamp; return stream; } QDataStream &operator>>(QDataStream &stream, Comment &comment) { stream >> comment.m_title; stream >> comment.m_author; stream >> comment.m_text; stream >> comment.m_timestamp; return stream; } //Annotation Annotation::Annotation() : m_comments() { } QVector Annotation::comments() const { return m_comments; } bool Annotation::hasComments() const { return !m_comments.isEmpty(); } void Annotation::setComments(const QVector &comments) { m_comments = comments; } void Annotation::removeComments() { m_comments.clear(); } int Annotation::commentsSize() const { return m_comments.size(); } Comment Annotation::comment(int n) const { if (m_comments.size() > n) return m_comments.at(n); else return Comment(); } void Annotation::addComment(const Comment &comment) { m_comments.push_back(comment); } bool Annotation::updateComment(const Comment &comment, int n) { bool result = false; if ((m_comments.size() > n) && (n > 0)) { m_comments[n] = comment; result = true; } return result; } bool Annotation::removeComment(int n) { bool result = false; if (m_comments.size() > n) { m_comments.remove(n); result = true; } return result; } QString Annotation::toQString() const { QStringList result; result.push_back(QString::number(m_comments.size())); for (const Comment &com : m_comments) result.push_back(com.toQString()); return result.join(s_sep); } void Annotation::fromQString(const QString &str) { QStringList strl (str.split(s_sep, Qt::KeepEmptyParts)); removeComments(); const int intro = 1; const int comSize = 4; if (!strl.isEmpty()) { if (strl.size() >= intro) { int size = strl.at(0).toInt(); if (size > 0) { if (strl.size() == (size*comSize) + intro) { for (int i = 0; i < size; i++) { const int offset = intro + (i * comSize); Comment com; com.setTitle(strl.at(offset + 0)); com.setAuthor(strl.at(offset + 1)); com.setText(strl.at(offset + 2)); com.setTimestamp(strl.at(offset + 3).toLongLong()); m_comments.push_back(com); } } } } } } QJsonValue Annotation::toJsonValue() const { QJsonObject obj; QJsonArray comments; for (auto &comment : m_comments) comments.push_back(comment.toJsonValue()); obj["comments"] = comments; return obj; } bool Annotation::fromJsonValue(const QJsonValue &v) { if (!v.isObject()) return false; auto obj = v.toObject(); auto jsonComments = obj["comments"].toArray(); m_comments.clear(); for (auto json : jsonComments) { Comment comment; if (comment.fromJsonValue(json)) m_comments.push_back(comment); } return true; } QDebug &operator<<(QDebug &stream, const Annotation &annotation) { stream << "\"Annotation: " << annotation.m_comments << "\" "; return stream; } QDataStream &operator<<(QDataStream &stream, const Annotation &annotation) { stream << annotation.m_comments; return stream; } QDataStream &operator>>(QDataStream &stream, Annotation &annotation) { stream >> annotation.m_comments; return stream; } GlobalAnnotationStatus::GlobalAnnotationStatus() : m_status(GlobalAnnotationStatus::Status::NoStatus) { } GlobalAnnotationStatus::GlobalAnnotationStatus(GlobalAnnotationStatus::Status status) : m_status(status) { } void GlobalAnnotationStatus::setStatus(int statusId) { switch (statusId) { case 0: m_status = GlobalAnnotationStatus::Status::InProgress; break; case 1: m_status = GlobalAnnotationStatus::Status::InReview; break; case 2: m_status = GlobalAnnotationStatus::Status::Done; break; case -1: default: m_status = GlobalAnnotationStatus::Status::NoStatus; break; } } void GlobalAnnotationStatus::setStatus(GlobalAnnotationStatus::Status status) { m_status = status; } GlobalAnnotationStatus::Status GlobalAnnotationStatus::status() const { return m_status; } QString GlobalAnnotationStatus::toQString() const { return QString::number(static_cast(m_status)); } void GlobalAnnotationStatus::fromQString(const QString &str) { bool result = false; int conversion = str.toInt(&result); if (result) { setStatus(conversion); } else { m_status = GlobalAnnotationStatus::Status::NoStatus; } } } // QmlDesigner namespace