diff --git a/src/bugzillaintegration/libbugzilla/CMakeLists.txt b/src/bugzillaintegration/libbugzilla/CMakeLists.txt --- a/src/bugzillaintegration/libbugzilla/CMakeLists.txt +++ b/src/bugzillaintegration/libbugzilla/CMakeLists.txt @@ -6,6 +6,7 @@ clients/attachmentclient.cpp clients/bugclient.cpp + clients/bugfieldclient.cpp clients/commentclient.cpp clients/clientbase.cpp clients/productclient.cpp @@ -18,6 +19,7 @@ clients/commands/querycommand.cpp models/bug.cpp + models/bugfield.cpp models/comment.cpp models/logindetails.cpp models/product.cpp diff --git a/src/bugzillaintegration/libbugzilla/autotests/CMakeLists.txt b/src/bugzillaintegration/libbugzilla/autotests/CMakeLists.txt --- a/src/bugzillaintegration/libbugzilla/autotests/CMakeLists.txt +++ b/src/bugzillaintegration/libbugzilla/autotests/CMakeLists.txt @@ -12,6 +12,7 @@ ecm_add_tests( attachmenttest.cpp bugtest.cpp + bugfieldtest.cpp bugzillatest.cpp commenttest.cpp connectiontest.cpp diff --git a/src/bugzillaintegration/libbugzilla/autotests/bugfieldtest.cpp b/src/bugzillaintegration/libbugzilla/autotests/bugfieldtest.cpp new file mode 100644 --- /dev/null +++ b/src/bugzillaintegration/libbugzilla/autotests/bugfieldtest.cpp @@ -0,0 +1,111 @@ +/* + Copyright 2019 Harald Sitter + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include + +#include + +#include "jobdouble.h" + +namespace Bugzilla +{ + +class ConnectionDouble : public Connection +{ +public: + using Connection::Connection; + + virtual void setToken(const QString &) override + { + Q_UNREACHABLE(); + } + + virtual APIJob *get(const QString &path, + const QUrlQuery &query = QUrlQuery()) const override + { + if (path == "/field/bug/rep_platform" && query.toString() == "") { + return new JobDouble { QFINDTESTDATA("data/field.rep_platform.json") }; + } + Q_ASSERT_X(false, "get", + qUtf8Printable(QStringLiteral("unmapped: %1; %2").arg(path, query.toString()))); + return nullptr; + } + + virtual APIJob *post(const QString &path, + const QByteArray &, + const QUrlQuery &query = QUrlQuery()) const override + { + Q_ASSERT_X(false, "post", + qUtf8Printable(QStringLiteral("unmapped: %1; %2").arg(path, query.toString()))); + return nullptr; + } + + virtual APIJob *put(const QString &path, + const QByteArray &, + const QUrlQuery &query = QUrlQuery()) const override + { + Q_ASSERT_X(false, "put", + qUtf8Printable(QStringLiteral("unmapped: %1; %2").arg(path, query.toString()))); + return nullptr; + } +}; + +class BugFieldTest : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase() + { + Bugzilla::setConnection(m_doubleConnection); + } + + void testGet() + { + Bugzilla::BugFieldClient client; + KJob *job = client.getField("rep_platform"); + QVERIFY(job); + job->start(); + auto field = client.getField(job); + auto values = field->values(); + QCOMPARE(5, values.size()); + bool containsWindows = false; + for (auto it = values.constBegin(); it != values.constEnd(); ++it) { + if ((*it)->name() == QLatin1String("MS Windows")) { + containsWindows = true; + break; + } + } + QVERIFY(containsWindows); + // Run again to drive up coverage for converter registration + job = client.getField("rep_platform"); + QVERIFY(job); + job->start(); + client.getField(job); + } + +private: + Bugzilla::ConnectionDouble *m_doubleConnection = new Bugzilla::ConnectionDouble; +}; + +} // namespace Bugzilla + +QTEST_MAIN(Bugzilla::BugFieldTest) + +#include "bugfieldtest.moc" diff --git a/src/bugzillaintegration/libbugzilla/autotests/data/field.rep_platform.json b/src/bugzillaintegration/libbugzilla/autotests/data/field.rep_platform.json new file mode 100644 --- /dev/null +++ b/src/bugzillaintegration/libbugzilla/autotests/data/field.rep_platform.json @@ -0,0 +1,49 @@ +{ + "fields" : [ + { + "display_name" : "Platform", + "id" : 5, + "is_custom" : false, + "is_mandatory" : false, + "is_on_bug_entry" : false, + "name" : "rep_platform", + "type" : 2, + "value_field" : null, + "values" : [ + { + "name" : "Unlisted Binaries", + "sort_key" : 100, + "sortkey" : 100, + "visibility_values" : [] + }, + { + "name" : "Compiled Sources", + "sort_key" : 200, + "sortkey" : 200, + "visibility_values" : [] + }, + { + "name" : "MS Windows", + "sort_key" : 930, + "sortkey" : 930, + "visibility_values" : [] + }, + { + "name" : "unspecified", + "sort_key" : 2300, + "sortkey" : 2300, + "visibility_values" : [] + }, + { + "name" : "Other", + "sort_key" : 2350, + "sortkey" : 2350, + "visibility_values" : [] + } + ], + "visibility_field" : null, + "visibility_values" : [] + } + ] +} + diff --git a/src/bugzillaintegration/libbugzilla/clients/bugfieldclient.h b/src/bugzillaintegration/libbugzilla/clients/bugfieldclient.h new file mode 100644 --- /dev/null +++ b/src/bugzillaintegration/libbugzilla/clients/bugfieldclient.h @@ -0,0 +1,44 @@ +/* + Copyright 2019 Harald Sitter + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef BUGFIELDCLIENT_H +#define BUGFIELDCLIENT_H + +#include "clientbase.h" +#include "models/bugfield.h" + +namespace Bugzilla { + +class BugFieldClient : public ClientBase +{ +public: + using ClientBase::ClientBase; + + KJob *getFields(const QString &idOrName = QString()); + QList getFields(KJob *kjob); + + KJob *getField(const QString &idOrName); + /// Ptr may be null if the idOrName matched nothing! + BugField::Ptr getField(KJob *kjob); +}; + +} // namespace Bugzilla + +#endif // BUGFIELDCLIENT_H diff --git a/src/bugzillaintegration/libbugzilla/clients/bugfieldclient.cpp b/src/bugzillaintegration/libbugzilla/clients/bugfieldclient.cpp new file mode 100644 --- /dev/null +++ b/src/bugzillaintegration/libbugzilla/clients/bugfieldclient.cpp @@ -0,0 +1,54 @@ +/* + Copyright 2019 Harald Sitter + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "bugfieldclient.h" + +namespace Bugzilla { + +KJob *BugFieldClient::getFields(const QString &idOrName) +{ + return m_connection.get(QStringLiteral("/field/bug/") + idOrName); +} + +QList BugFieldClient::getFields(KJob *kjob) +{ + APIJob *job = qobject_cast(kjob); + + const auto ary = job->object().value(QStringLiteral("fields")).toArray(); + + QList list; + list.reserve(ary.size()); + for (const auto &bug : qAsConst(ary)) { + list.append(BugField::Ptr(new BugField(bug.toObject().toVariantHash()))); + } + return list; +} + +KJob *BugFieldClient::getField(const QString &idOrName) +{ + return getFields(idOrName); +} + +BugField::Ptr BugFieldClient::getField(KJob *kjob) +{ + return getFields(kjob).value(0, nullptr); +} + +} // namespace Bugzilla diff --git a/src/bugzillaintegration/libbugzilla/models/bugfield.h b/src/bugzillaintegration/libbugzilla/models/bugfield.h new file mode 100644 --- /dev/null +++ b/src/bugzillaintegration/libbugzilla/models/bugfield.h @@ -0,0 +1,99 @@ +/* + Copyright 2019 Harald Sitter + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef BUGFIELD_H +#define BUGFIELD_H + +#include +#include +#include + +namespace Bugzilla { + +/// https://bugzilla.readthedocs.io/en/5.0/api/core/v1/field.html +class BugFieldValue : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName) + // not mapped because of lazyness and lack of need + // Q_PROPERTY(int sort_key READ sort_key WRITE setSort_key) + // // visibility_values not mapped + // Q_PROPERTY(bool is_active READ is_active WRITE setIs_active) + // Q_PROPERTY(QString description READ description WRITE setDescription) + // Q_PROPERTY(bool is_open READ is_open WRITE setIs_open) + // // can_change_to not mapped +public: + explicit BugFieldValue(const QVariantHash &obj, QObject *parent = nullptr); + + QString name() const; + void setName(QString name); + +private: + QString m_name; +}; + +/// https://bugzilla.readthedocs.io/en/5.0/api/core/v1/field.html +class BugField : public QObject +{ + Q_OBJECT + // Not mapped for lazyness and lack of need: + // Q_PROPERTY(int id READ id WRITE setId) + // Q_PROPERTY(Type type READ type WRITE setType) + // Q_PROPERTY(bool is_custom READ is_custom WRITE setIs_custom) + // Q_PROPERTY(QString name READ name WRITE setName) + // Q_PROPERTY(QString display_name READ display_name WRITE setDisplay_name) + // Q_PROPERTY(bool is_mandatory READ is_mandatory WRITE setIs_mandatory) + // Q_PROPERTY(bool is_on_bug_entry READ is_on_bug_entry WRITE setIs_on_bug_entry) + // Q_PROPERTY(QString visibility_field READ visibility_field WRITE setVisibility_field) + // Q_PROPERTY(QString value_field READ value_field WRITE setValue_field) + Q_PROPERTY(QList values READ values WRITE setValues) +public: + enum class Type { + Invalid = -1, + Unknown = 0, + SingleLineString = 1, + SingleValue = 2, + MultipleValue = 3, + MultiLineText = 4, + DateTime = 5, + BugId = 6, + SeeAlso = 7, + Keywords = 8, + Date = 9, + Integer = 10 + }; + + typedef QPointer Ptr; + + explicit BugField(const QVariantHash &obj, QObject *parent = nullptr); + + QList values() const; + + void setValues(QList values); + +private: + static void registerVariantConverters(); + + QList m_values; +}; + +} // namespace Bugzilla + +#endif // BUGFIELD_H diff --git a/src/bugzillaintegration/libbugzilla/models/bugfield.cpp b/src/bugzillaintegration/libbugzilla/models/bugfield.cpp new file mode 100644 --- /dev/null +++ b/src/bugzillaintegration/libbugzilla/models/bugfield.cpp @@ -0,0 +1,83 @@ +/* + Copyright 2019 Harald Sitter + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#include "bugfield.h" + +namespace Bugzilla { + +BugField::BugField(const QVariantHash &obj, QObject *parent) + : QObject(parent) +{ + registerVariantConverters(); + + for (auto it = obj.constBegin(); it != obj.constEnd(); ++it) { + setProperty(qPrintable(it.key()), it.value()); + } +} + +QList BugField::values() const +{ + return m_values; +} + +void BugField::setValues(QList values) +{ + m_values = values; +} + +void BugField::registerVariantConverters() +{ + static bool convertersRegistered = false; + if (convertersRegistered) { + return; + } + convertersRegistered = true; + + QMetaType::registerConverter>( + [](QVariantList v) -> QList + { + QList list; + list.reserve(v.size()); + for (const QVariant &variant : qAsConst(v)) { + list.append(new BugFieldValue(variant.toHash())); + } + return list; + }); +} + +BugFieldValue::BugFieldValue(const QVariantHash &obj, QObject *parent) + : QObject(parent) +{ + for (auto it = obj.constBegin(); it != obj.constEnd(); ++it) { + setProperty(qPrintable(it.key()), it.value()); + } +} + +QString BugFieldValue::name() const +{ + return m_name; +} + +void BugFieldValue::setName(QString name) +{ + m_name = name; +} + +} // namespace Bugzilla