diff --git a/src/domain/task.h b/src/domain/task.h --- a/src/domain/task.h +++ b/src/domain/task.h @@ -27,6 +27,7 @@ #include "artifact.h" #include +#include namespace Domain { @@ -38,10 +39,51 @@ Q_PROPERTY(QDateTime startDate READ startDate WRITE setStartDate NOTIFY startDateChanged) Q_PROPERTY(QDateTime dueDate READ dueDate WRITE setDueDate NOTIFY dueDateChanged) Q_PROPERTY(Domain::Task::Delegate delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) + Q_PROPERTY(Domain::Task::Attachments attachements READ attachments WRITE setAttachments NOTIFY attachmentsChanged) public: typedef QSharedPointer Ptr; typedef QList List; + class Attachment + { + public: + Attachment(); + explicit Attachment(const QByteArray &data); + explicit Attachment(const QUrl &uri); + Attachment(const Attachment &other); + ~Attachment(); + + Attachment &operator=(const Attachment &other); + bool operator==(const Attachment &other) const; + + bool isValid() const; + bool isUri() const; + + QUrl uri() const; + void setUri(const QUrl &uri); + + QByteArray data() const; + void setData(const QByteArray &data); + + QString label() const; + void setLabel(const QString &label); + + QString mimeType() const; + void setMimeType(const QString &mimeType); + + QString iconName() const; + void setIconName(const QString &iconName); + + private: + QUrl m_uri; + QByteArray m_data; + QString m_label; + QString m_mimeType; + QString m_iconName; + }; + + typedef QList Attachments; + class Delegate { public: @@ -75,37 +117,43 @@ QDateTime startDate() const; QDateTime dueDate() const; QDateTime doneDate() const; + Attachments attachments() const; Delegate delegate() const; public slots: void setRunning(bool running); void setDone(bool done); void setDoneDate(const QDateTime &doneDate); void setStartDate(const QDateTime &startDate); void setDueDate(const QDateTime &dueDate); + void setAttachments(const Domain::Task::Attachments &attachments); void setDelegate(const Domain::Task::Delegate &delegate); signals: void runningChanged(bool isRunning); void doneChanged(bool isDone); void doneDateChanged(const QDateTime &doneDate); void startDateChanged(const QDateTime &startDate); void dueDateChanged(const QDateTime &dueDate); + void attachmentsChanged(const Domain::Task::Attachments &attachments); void delegateChanged(const Domain::Task::Delegate &delegate); private: bool m_running; bool m_done; QDateTime m_startDate; QDateTime m_dueDate; QDateTime m_doneDate; + Attachments m_attachments; Delegate m_delegate; }; } Q_DECLARE_METATYPE(Domain::Task::Ptr) Q_DECLARE_METATYPE(Domain::Task::List) +Q_DECLARE_METATYPE(Domain::Task::Attachment) +Q_DECLARE_METATYPE(Domain::Task::Attachments) Q_DECLARE_METATYPE(Domain::Task::Delegate) #endif // DOMAIN_TASK_H diff --git a/src/domain/task.cpp b/src/domain/task.cpp --- a/src/domain/task.cpp +++ b/src/domain/task.cpp @@ -96,6 +96,11 @@ return m_doneDate; } +Task::Attachments Task::attachments() const +{ + return m_attachments; +} + Task::Delegate Task::delegate() const { return m_delegate; @@ -118,6 +123,15 @@ emit dueDateChanged(dueDate); } +void Task::setAttachments(const Task::Attachments &attachments) +{ + if (m_attachments == attachments) + return; + + m_attachments = attachments; + emit attachmentsChanged(attachments); +} + void Task::setDelegate(const Task::Delegate &delegate) { if (m_delegate == delegate) @@ -128,6 +142,116 @@ } +Task::Attachment::Attachment() +{ +} + +Task::Attachment::Attachment(const QByteArray &data) +{ + setData(data); +} + +Task::Attachment::Attachment(const QUrl &uri) +{ + setUri(uri); +} + +Task::Attachment::Attachment(const Task::Attachment &other) + : m_uri(other.m_uri), + m_data(other.m_data), + m_label(other.m_label), + m_mimeType(other.m_mimeType), + m_iconName(other.m_iconName) +{ +} + +Task::Attachment::~Attachment() +{ +} + +Task::Attachment &Task::Attachment::operator=(const Task::Attachment &other) +{ + Attachment copy(other); + std::swap(m_uri, copy.m_uri); + std::swap(m_data, copy.m_data); + std::swap(m_label, copy.m_label); + std::swap(m_mimeType, copy.m_mimeType); + std::swap(m_iconName, copy.m_iconName); + return *this; +} + +bool Task::Attachment::operator==(const Task::Attachment &other) const +{ + return m_uri == other.m_uri + && m_data == other.m_data + && m_label == other.m_label + && m_mimeType == other.m_mimeType + && m_iconName == other.m_iconName; +} + +bool Task::Attachment::isValid() const +{ + return m_uri.isValid() || !m_data.isEmpty(); +} + +bool Task::Attachment::isUri() const +{ + return m_uri.isValid(); +} + +QUrl Task::Attachment::uri() const +{ + return m_uri; +} + +void Task::Attachment::setUri(const QUrl &uri) +{ + m_uri = uri; + m_data.clear(); +} + +QByteArray Task::Attachment::data() const +{ + return m_data; +} + +void Task::Attachment::setData(const QByteArray &data) +{ + m_data = data; + m_uri.clear(); +} + +QString Task::Attachment::label() const +{ + return m_label; +} + +void Task::Attachment::setLabel(const QString &label) +{ + m_label = label; +} + +QString Task::Attachment::mimeType() const +{ + return m_mimeType; +} + +void Task::Attachment::setMimeType(const QString &mimeType) +{ + m_mimeType = mimeType; +} + +QString Task::Attachment::iconName() const +{ + return m_iconName; +} + +void Task::Attachment::setIconName(const QString &iconName) +{ + m_iconName = iconName; +} + + Task::Delegate::Delegate() { } diff --git a/tests/units/domain/tasktest.cpp b/tests/units/domain/tasktest.cpp --- a/tests/units/domain/tasktest.cpp +++ b/tests/units/domain/tasktest.cpp @@ -36,6 +36,7 @@ explicit TaskTest(QObject *parent = Q_NULLPTR) : QObject(parent) { + qRegisterMetaType(); qRegisterMetaType(); } @@ -49,9 +50,85 @@ QCOMPARE(t.startDate(), QDateTime()); QCOMPARE(t.dueDate(), QDateTime()); QCOMPARE(t.doneDate(), QDateTime()); + QVERIFY(t.attachments().isEmpty()); QVERIFY(!t.delegate().isValid()); } + void shouldHaveValueBasedAttachment() + { + Task::Attachment a; + QVERIFY(!a.isValid()); + QVERIFY(!a.isUri()); + QCOMPARE(a.uri(), QUrl()); + QCOMPARE(a.data(), QByteArray()); + QCOMPARE(a.label(), QString()); + QCOMPARE(a.mimeType(), QString()); + QCOMPARE(a.iconName(), QString()); + + a.setUri(QUrl("https://www.kde.org")); + QVERIFY(a.isValid()); + QVERIFY(a.isUri()); + QCOMPARE(a.uri(), QUrl("https://www.kde.org")); + QCOMPARE(a.data(), QByteArray()); + QCOMPARE(a.label(), QString()); + QCOMPARE(a.mimeType(), QString()); + QCOMPARE(a.iconName(), QString()); + + a.setData(QByteArrayLiteral("foobar")); + QVERIFY(a.isValid()); + QVERIFY(!a.isUri()); + QCOMPARE(a.uri(), QUrl()); + QCOMPARE(a.data(), QByteArrayLiteral("foobar")); + QCOMPARE(a.label(), QString()); + QCOMPARE(a.mimeType(), QString()); + QCOMPARE(a.iconName(), QString()); + + a.setLabel(QStringLiteral("baz")); + QVERIFY(a.isValid()); + QVERIFY(!a.isUri()); + QCOMPARE(a.uri(), QUrl()); + QCOMPARE(a.data(), QByteArrayLiteral("foobar")); + QCOMPARE(a.label(), QStringLiteral("baz")); + QCOMPARE(a.mimeType(), QString()); + QCOMPARE(a.iconName(), QString()); + + a.setMimeType(QStringLiteral("text/plain")); + QVERIFY(a.isValid()); + QVERIFY(!a.isUri()); + QCOMPARE(a.uri(), QUrl()); + QCOMPARE(a.data(), QByteArrayLiteral("foobar")); + QCOMPARE(a.label(), QStringLiteral("baz")); + QCOMPARE(a.mimeType(), QStringLiteral("text/plain")); + QCOMPARE(a.iconName(), QString()); + + a.setIconName(QStringLiteral("text")); + QVERIFY(a.isValid()); + QVERIFY(!a.isUri()); + QCOMPARE(a.uri(), QUrl()); + QCOMPARE(a.data(), QByteArrayLiteral("foobar")); + QCOMPARE(a.label(), QStringLiteral("baz")); + QCOMPARE(a.mimeType(), QStringLiteral("text/plain")); + QCOMPARE(a.iconName(), QStringLiteral("text")); + + a.setUri(QUrl("https://www.kde.org")); + QVERIFY(a.isValid()); + QVERIFY(a.isUri()); + QCOMPARE(a.uri(), QUrl("https://www.kde.org")); + QCOMPARE(a.data(), QByteArray()); + QCOMPARE(a.label(), QStringLiteral("baz")); + QCOMPARE(a.mimeType(), QStringLiteral("text/plain")); + QCOMPARE(a.iconName(), QStringLiteral("text")); + + a.setUri(QUrl()); + QVERIFY(!a.isValid()); + QVERIFY(!a.isUri()); + QCOMPARE(a.uri(), QUrl()); + QCOMPARE(a.data(), QByteArray()); + QCOMPARE(a.label(), QStringLiteral("baz")); + QCOMPARE(a.mimeType(), QStringLiteral("text/plain")); + QCOMPARE(a.iconName(), QStringLiteral("text")); + } + void shouldHaveValueBasedDelegate() { Task::Delegate d; @@ -133,6 +210,32 @@ QCOMPARE(spy.count(), 0); } + void shouldNotifyAttachmentsChanges() + { + Task::Attachments attachments; + attachments.append(Task::Attachment(QByteArrayLiteral("foobar"))); + attachments.append(Task::Attachment(QUrl("https://www.kde.org"))); + + Task t; + QSignalSpy spy(&t, &Task::attachmentsChanged); + t.setAttachments(attachments); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.first().first().value(), attachments); + } + + void shouldNotNotifyIdenticalAttachmentsChanges() + { + Task::Attachments attachments; + attachments.append(Task::Attachment(QByteArrayLiteral("foobar"))); + attachments.append(Task::Attachment(QUrl("https://www.kde.org"))); + + Task t; + t.setAttachments(attachments); + QSignalSpy spy(&t, &Task::attachmentsChanged); + t.setAttachments(attachments); + QCOMPARE(spy.count(), 0); + } + void shouldNotifyDelegateChanges() { Task t;