diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -76,3 +76,4 @@ add_libkgapi2_test(drive filecreatejobtest) add_libkgapi2_test(drive filesearchquerytest) add_libkgapi2_test(drive teamdrivefetchjobtest) +add_libkgapi2_test(drive teamdrivesearchquerytest) diff --git a/autotests/drive/teamdrivesearchquerytest.cpp b/autotests/drive/teamdrivesearchquerytest.cpp new file mode 100644 --- /dev/null +++ b/autotests/drive/teamdrivesearchquerytest.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 David Barchiesi + * + * 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 "teamdrivesearchquery.h" + +using namespace KGAPI2; +using namespace KGAPI2::Drive; + +Q_DECLARE_METATYPE(KGAPI2::Drive::TeamdriveSearchQuery) + +class TeamdriveSearchQueryTest: public QObject +{ + Q_OBJECT +public: + explicit TeamdriveSearchQueryTest() {} + + ~TeamdriveSearchQueryTest() {} + +private Q_SLOTS: + void testTeamdriveSearchQuery_data() + { + QTest::addColumn("query"); + QTest::addColumn("expected"); + + { + TeamdriveSearchQuery query; + query.addQuery(TeamdriveSearchQuery::CreatedTime, TeamdriveSearchQuery::Equals, QDateTime(QDate(2019, 3, 5), QTime(6, 36, 0), Qt::UTC)); + QTest::newRow("serialize time") << query + << "((createdTime = '2019-03-05T06:36:00'))"; + } + + { + TeamdriveSearchQuery query; + query.addQuery(TeamdriveSearchQuery::Name, TeamdriveSearchQuery::Contains, QLatin1String("Some String")); + QTest::newRow("contains") << query + << "((name contains 'Some String'))"; + } + + { + TeamdriveSearchQuery query; + query.addQuery(TeamdriveSearchQuery::Name, TeamdriveSearchQuery::Contains, QLatin1String("Name")); + query.addQuery(TeamdriveSearchQuery::MemberCount, TeamdriveSearchQuery::Equals, 5); + QTest::newRow("A and B") << query + << "((name contains 'Name') and (memberCount = 5))"; + } + + { + TeamdriveSearchQuery query(TeamdriveSearchQuery::Or); + query.addQuery(TeamdriveSearchQuery::Name, TeamdriveSearchQuery::Contains, QLatin1String("Name")); + query.addQuery(TeamdriveSearchQuery::OrganizerCount, TeamdriveSearchQuery::Equals, 5); + QTest::newRow("A or B") << query + << "((name contains 'Name') or (organizerCount = 5))"; + } + + { + TeamdriveSearchQuery query(TeamdriveSearchQuery::Or); + query.addQuery(TeamdriveSearchQuery::CreatedTime, TeamdriveSearchQuery::Equals, QDateTime(QDate(2019, 3, 5), QTime(6, 36, 0), Qt::UTC)); + TeamdriveSearchQuery subquery; + subquery.addQuery(TeamdriveSearchQuery::Name, TeamdriveSearchQuery::Equals, QLatin1String("Test")); + subquery.addQuery(TeamdriveSearchQuery::MemberCount, TeamdriveSearchQuery::LessOrEqual, 10); + query.addQuery(subquery); + QTest::newRow("A or (B and C)") << query + << "((createdTime = '2019-03-05T06:36:00') or ((name = 'Test') and (memberCount <= 10)))"; + } + } + + void testTeamdriveSearchQuery() + { + QFETCH(TeamdriveSearchQuery, query); + QFETCH(QString, expected); + + const QString serialized = query.serialize(); + QCOMPARE(serialized, expected); + } +}; + +QTEST_GUILESS_MAIN(TeamdriveSearchQueryTest) + +#include "teamdrivesearchquerytest.moc" diff --git a/examples/teamdrive/mainwindow.cpp b/examples/teamdrive/mainwindow.cpp --- a/examples/teamdrive/mainwindow.cpp +++ b/examples/teamdrive/mainwindow.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -96,7 +97,10 @@ return; } - KGAPI2::Drive::TeamdriveFetchJob *fetchJob = new KGAPI2::Drive::TeamdriveFetchJob(m_account, this); + KGAPI2::Drive::TeamdriveSearchQuery query; + query.addQuery(KGAPI2::Drive::TeamdriveSearchQuery::MemberCount, KGAPI2::Drive::TeamdriveSearchQuery::Less, 10); + + KGAPI2::Drive::TeamdriveFetchJob *fetchJob = new KGAPI2::Drive::TeamdriveFetchJob(query, m_account, this); connect(fetchJob, &KGAPI2::Job::finished, this, &MainWindow::slotFetchJobFinished); diff --git a/src/drive/CMakeLists.txt b/src/drive/CMakeLists.txt --- a/src/drive/CMakeLists.txt +++ b/src/drive/CMakeLists.txt @@ -40,6 +40,7 @@ revisionmodifyjob.cpp teamdrive.cpp teamdrivefetchjob.cpp + teamdrivesearchquery.cpp user.cpp ../debug.cpp @@ -87,6 +88,7 @@ RevisionModifyJob Teamdrive TeamdriveFetchJob + TeamdriveSearchQuery User PREFIX KGAPI/Drive REQUIRED_HEADERS kgapidrive_HEADERS diff --git a/src/drive/teamdrivefetchjob.h b/src/drive/teamdrivefetchjob.h --- a/src/drive/teamdrivefetchjob.h +++ b/src/drive/teamdrivefetchjob.h @@ -26,6 +26,8 @@ #include "fetchjob.h" #include "kgapidrive_export.h" +#include "teamdrivesearchquery.h" + namespace KGAPI2 { @@ -63,6 +65,7 @@ WRITE setUseDomainAdminAccess) public: + TeamdriveFetchJob(const TeamdriveSearchQuery &query, const AccountPtr &account, QObject *parent = nullptr); TeamdriveFetchJob(const AccountPtr &account, QObject *parent = nullptr); TeamdriveFetchJob(const QString &teamdriveId, const AccountPtr &account, QObject *parent = nullptr); diff --git a/src/drive/teamdrivefetchjob.cpp b/src/drive/teamdrivefetchjob.cpp --- a/src/drive/teamdrivefetchjob.cpp +++ b/src/drive/teamdrivefetchjob.cpp @@ -46,6 +46,7 @@ Private(TeamdriveFetchJob *parent); QNetworkRequest createRequest(const QUrl &url); + TeamdriveSearchQuery searchQuery; QString teamdriveId; int maxResults = 0; @@ -79,6 +80,15 @@ d->teamdriveId = teamdriveId; } +TeamdriveFetchJob::TeamdriveFetchJob(const TeamdriveSearchQuery &query, + const AccountPtr &account, QObject *parent): + FetchJob(account, parent), + d(new Private(this)) +{ + d->useDomainAdminAccess = true; + d->searchQuery = query; +} + TeamdriveFetchJob::TeamdriveFetchJob(const AccountPtr &account, QObject *parent): FetchJob(account, parent), d(new Private(this)) @@ -175,5 +185,8 @@ if (d->useDomainAdminAccess != false) { query.addQueryItem(UseDomainAdminAccessAttr, d->useDomainAdminAccess ? True : False); } + if (!d->searchQuery.isEmpty()) { + query.addQueryItem(QStringLiteral("q"), d->searchQuery.serialize()); + } url.setQuery(query); } diff --git a/src/drive/teamdrivesearchquery.h b/src/drive/teamdrivesearchquery.h new file mode 100644 --- /dev/null +++ b/src/drive/teamdrivesearchquery.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 David Barchiesi + * + * 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 KGAPI2_DRIVE_TEAMDRIVESEARCHQUERY_H +#define KGAPI2_DRIVE_TEAMDRIVESEARCHQUERY_H + +#include "kgapidrive_export.h" + +#include "searchquery.h" + +#include +#include + +namespace KGAPI2 +{ +namespace Drive +{ + +/** + * TeamdriveSearchQuery class allows simply building even complex team drive search queries + * for TeamdriveFetchJob. + * + * See https://developers.google.com/drive/web/search-parameters for allowed + * combinations of fields, compare operators, and value types. + * + * @since 2.3 + */ +class KGAPIDRIVE_EXPORT TeamdriveSearchQuery : public SearchQuery +{ +public: + enum Field { + Name, + CreatedTime, + MemberCount, + OrganizerCount + }; + + using SearchQuery::SearchQuery; + + using SearchQuery::addQuery; + void addQuery(Field field, CompareOperator op, const QVariant &value); + +private: + QString fieldToString(Field field); + QString valueToString(TeamdriveSearchQuery::Field field, const QVariant &var); +}; +} +} + +#endif // KGAPI2_DRIVE_TEAMDRIVESEARCHQUERY_H diff --git a/src/drive/teamdrivesearchquery.cpp b/src/drive/teamdrivesearchquery.cpp new file mode 100644 --- /dev/null +++ b/src/drive/teamdrivesearchquery.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 David Barchiesi + * + * 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 "teamdrivesearchquery.h" + +#include +#include + +using namespace KGAPI2; +using namespace KGAPI2::Drive; + + +QString TeamdriveSearchQuery::fieldToString(Field field) +{ + switch (field) { + case Name: + return QStringLiteral("name"); + case CreatedTime: + return QStringLiteral("createdTime"); + case MemberCount: + return QStringLiteral("memberCount"); + case OrganizerCount: + return QStringLiteral("organizerCount"); + } + + Q_ASSERT(false); + return QString(); +} + +QString TeamdriveSearchQuery::valueToString(TeamdriveSearchQuery::Field field, const QVariant &var) +{ + switch (field) { + case Name: + return QStringLiteral("'%1'").arg(var.toString().replace(QLatin1Char('\''), QLatin1String("\\\'"))); + case MemberCount: + case OrganizerCount: + return var.toString(); + case CreatedTime: + return QStringLiteral("'%1'").arg(var.toDateTime().toUTC().toString(QStringLiteral("yyyy-MM-ddThh:mm:ss"))); + } + + Q_ASSERT(false); + return QString(); +} + +void TeamdriveSearchQuery::addQuery(TeamdriveSearchQuery::Field field, TeamdriveSearchQuery::CompareOperator op, const QVariant &value) +{ + switch (field) { + case Name: + Q_ASSERT(op == Contains || op == Equals || op == NotEquals); + Q_ASSERT(value.canConvert()); + break; + case MemberCount: + case OrganizerCount: + Q_ASSERT(op == LessOrEqual || op == Less || op == Equals || op == NotEquals || op == Greater || op == GreaterOrEqual); + Q_ASSERT(value.canConvert()); + break; + case CreatedTime: + Q_ASSERT(op == LessOrEqual || op == Less || op == Equals || op == NotEquals || op == Greater || op == GreaterOrEqual); + Q_ASSERT(value.canConvert()); + break; + } + + SearchQuery::addQuery(fieldToString(field), op, valueToString(field, value)); +}