diff --git a/KF5AkonadiConfig.cmake.in b/KF5AkonadiConfig.cmake.in index 19fa5706e..a29943ce2 100644 --- a/KF5AkonadiConfig.cmake.in +++ b/KF5AkonadiConfig.cmake.in @@ -1,35 +1,35 @@ @PACKAGE_INIT@ # set the directories if(NOT AKONADI_INSTALL_DIR) set(AKONADI_INSTALL_DIR "@CMAKE_INSTALL_PREFIX@") endif(NOT AKONADI_INSTALL_DIR) include(CMakeFindDependencyMacro) -find_dependency(KF5Completion "@KF5_VERSION@") -find_dependency(KF5XmlGui "@KF5_VERSION@") -find_dependency(KF5ItemModels "@KF5_VERSION@") -find_dependency(KF5ConfigWidgets "@KF5_VERSION@") +find_dependency(KF5Completion "@KF5_MIN_VERSION@") +find_dependency(KF5XmlGui "@KF5_MIN_VERSION@") +find_dependency(KF5ItemModels "@KF5_MIN_VERSION@") +find_dependency(KF5ConfigWidgets "@KF5_MIN_VERSION@") find_dependency(Qt5DBus "@QT_REQUIRED_VERSION@") find_dependency(Qt5Network "@QT_REQUIRED_VERSION@") set_and_check(AKONADI_DBUS_INTERFACES_DIR "@PACKAGE_AKONADI_DBUS_INTERFACES_INSTALL_DIR@") set_and_check(AKONADI_INCLUDE_DIR "@PACKAGE_AKONADI_INCLUDE_DIR@") find_dependency(Boost "@Boost_MINIMUM_VERSION@") include(${CMAKE_CURRENT_LIST_DIR}/KF5AkonadiTargets.cmake) include(${CMAKE_CURRENT_LIST_DIR}/KF5AkonadiMacros.cmake) # The directory where akonadi-xml.xsd and kcfg2dbus.xsl are installed set(KF5Akonadi_DATA_DIR "@PACKAGE_KF5Akonadi_DATA_DIR@") #################################################################################### # CMAKE_AUTOMOC if(NOT CMAKE_VERSION VERSION_LESS "3.10.0") # CMake 3.9+ warns about automoc on files without Q_OBJECT, and doesn't know about other macros. # 3.10+ lets us provide more macro names that require automoc. list(APPEND CMAKE_AUTOMOC_MACRO_NAMES AKONADI_AGENTCONFIG_FACTORY) endif() diff --git a/autotests/libs/CMakeLists.txt b/autotests/libs/CMakeLists.txt index be7ed70ee..ab6dc876e 100644 --- a/autotests/libs/CMakeLists.txt +++ b/autotests/libs/CMakeLists.txt @@ -1,188 +1,189 @@ set(QT_REQUIRED_VERSION "5.9.0") find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Test DBus) include(ECMAddTests) if(${EXECUTABLE_OUTPUT_PATH}) set( PREVIOUS_EXEC_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH} ) else() set( PREVIOUS_EXEC_OUTPUT_PATH . ) endif() set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) set( TEST_RESULT_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/testresults ) file(MAKE_DIRECTORY ${TEST_RESULT_OUTPUT_PATH}) option(AKONADI_TESTS_XML "Use XML files for the test results, instead of plain text." FALSE) option(AKONADI_RUN_SQLITE_ISOLATED_TESTS "Run isolated tests with sqlite3 as backend" TRUE) option(AKONADI_RUN_MYSQL_ISOLATED_TESTS "Run isolated tests with MySQL as backend" TRUE) option(AKONADI_RUN_PGSQL_ISOLATED_TESTS "Run isolated tests with PostgreSQL as backend" TRUE) kde_enable_exceptions() include_directories( ${Boost_INCLUDE_DIR} ) # convenience macro to add akonadi qtestlib unit-tests macro(add_akonadi_test _source) set(_test ${_source} ${CMAKE_BINARY_DIR}/src/core/akonadicore_debug.cpp) get_filename_component(_name ${_source} NAME_WE) add_executable( ${_name} ${_test} ) add_test(NAME ${_name} COMMAND ${_name} ) ecm_mark_as_test(akonadi-${_name}) set_tests_properties(${_name} PROPERTIES ENVIRONMENT "QT_HASH_SEED=1;QT_NO_CPU_FEATURE=sse4.2") target_link_libraries(${_name} akonaditestfake Qt5::Test KF5::AkonadiPrivate KF5::DBusAddons KF5::I18n) endmacro() # convenience macro to add akonadi qtestlib unit-tests macro(add_akonadi_test_widgets _source) set(_test ${_source} ${CMAKE_BINARY_DIR}/src/widgets/akonadiwidgets_debug.cpp ${CMAKE_BINARY_DIR}/src/core/akonadicore_debug.cpp ) get_filename_component(_name ${_source} NAME_WE) add_executable( ${_name} ${_test} ) add_test(NAME ${_name} COMMAND ${_name} ) ecm_mark_as_test(akonadi-${_name}) set_tests_properties(${_name} PROPERTIES ENVIRONMENT "QT_HASH_SEED=1;QT_NO_CPU_FEATURE=sse4.2") target_link_libraries(${_name} akonaditestfake Qt5::Test KF5::AkonadiWidgets KF5::AkonadiPrivate KF5::DBusAddons) endmacro() include(../../KF5AkonadiMacros.cmake) # akonadi test fake library set(akonaditestfake_xml ${Akonadi_SOURCE_DIR}/src/interfaces/org.freedesktop.Akonadi.NotificationSource.xml) set_source_files_properties(${akonaditestfake_xml} PROPERTIES INCLUDE "protocol_p.h") qt5_add_dbus_interface( akonaditestfake_srcs ${akonaditestfake_xml} notificationsourceinterface ) add_library(akonaditestfake SHARED ${akonaditestfake_srcs} fakeakonadiservercommand.cpp fakesession.cpp fakemonitor.cpp fakeserverdata.cpp modelspy.cpp fakeentitycache.cpp inspectablemonitor.cpp inspectablechangerecorder.cpp ) generate_export_header(akonaditestfake BASE_NAME akonaditestfake) target_link_libraries(akonaditestfake Qt5::DBus KF5::AkonadiCore Qt5::Test Qt5::Widgets Qt5::Network KF5::DBusAddons KF5::AkonadiPrivate akonadi_shared ) add_executable(akonadi-firstrun ../../src/core/firstrun.cpp firstrunner.cpp ${CMAKE_BINARY_DIR}/src/core/akonadicore_debug.cpp ) target_link_libraries( akonadi-firstrun Qt5::Test Qt5::Core KF5::AkonadiCore KF5::AkonadiPrivate KF5::DBusAddons KF5::ConfigCore Qt5::Widgets) # qtestlib unit tests add_akonadi_test(imapparsertest.cpp) # It need KIMAP add_akonadi_test(imapsettest.cpp) add_akonadi_test(itemhydratest.cpp) add_akonadi_test(itemtest.cpp) add_akonadi_test(itemserializertest.cpp) add_akonadi_test(mimetypecheckertest.cpp) add_akonadi_test(protocolhelpertest.cpp) add_akonadi_test(entitytreemodeltest.cpp) add_akonadi_test(monitornotificationtest.cpp) add_akonadi_test(collectionutilstest.cpp) add_akonadi_test(collectioncolorattributetest.cpp) add_akonadi_test(entitydisplayattributetest.cpp) add_akonadi_test(proxymodelstest.cpp) add_akonadi_test(newmailnotifierattributetest.cpp) add_akonadi_test(pop3resourceattributetest.cpp) add_akonadi_test_widgets(actionstatemanagertest.cpp) add_akonadi_test_widgets(conflictresolvedialogtest.cpp) add_akonadi_test(tagmodeltest.cpp) add_akonadi_test(statisticsproxymodeltest.cpp) add_akonadi_test(sharedvaluepooltest.cpp) add_akonadi_test(jobtest.cpp) add_akonadi_test(tagtest_simple.cpp) add_akonadi_test(cachepolicytest.cpp) # PORT FROM QJSON add_akonadi_test(searchquerytest.cpp) # qtestlib tests that need non-exported stuff from #add_executable( resourceschedulertest resourceschedulertest.cpp ../src/agentbase/resourcescheduler.cpp ) #add_test( resourceschedulertest resourceschedulertest ) #ecm_mark_as_test(akonadi-resourceschedulertest) #target_link_libraries(resourceschedulertest Qt5::Test KF5::AkonadiAgentBase) # testrunner tests add_akonadi_isolated_test(SOURCE testenvironmenttest.cpp) add_akonadi_isolated_test(SOURCE autoincrementtest.cpp) add_akonadi_isolated_test(SOURCE attributefactorytest.cpp) add_akonadi_isolated_test(SOURCE collectionpathresolvertest.cpp) add_akonadi_isolated_test(SOURCE collectionattributetest.cpp) add_akonadi_isolated_test(SOURCE itemfetchtest.cpp) add_akonadi_isolated_test(SOURCE itemappendtest.cpp) add_akonadi_isolated_test(SOURCE itemstoretest.cpp) add_akonadi_isolated_test(SOURCE itemdeletetest.cpp) add_akonadi_isolated_test(SOURCE entitycachetest.cpp) add_akonadi_isolated_test(SOURCE monitortest.cpp) #add_akonadi_isolated_test_advanced(monitorfiltertest.cpp "" "KF5::AkonadiPrivate") # FIXME: this is constantly failling due to broken search: re-enable once the new search code is merged #add_akonadi_isolated_test(SOURCE searchjobtest.cpp) add_akonadi_isolated_test(SOURCE changerecordertest.cpp) add_akonadi_isolated_test(SOURCE resourcetest.cpp) add_akonadi_isolated_test(SOURCE subscriptiontest.cpp) add_akonadi_isolated_test(SOURCE transactiontest.cpp) add_akonadi_isolated_test(SOURCE itemcopytest.cpp) add_akonadi_isolated_test(SOURCE itemmovetest.cpp) +add_akonadi_isolated_test(SOURCE invalidatecachejobtest.cpp) add_akonadi_isolated_test(SOURCE collectioncreatetest.cpp) add_akonadi_isolated_test(SOURCE collectioncopytest.cpp) add_akonadi_isolated_test(SOURCE collectionmovetest.cpp) add_akonadi_isolated_test( SOURCE collectionsynctest.cpp ADDITIONAL_SOURCES ${CMAKE_BINARY_DIR}/src/core/akonadicore_debug.cpp LINK_LIBRARIES KF5::I18n ) add_akonadi_isolated_test(SOURCE itemsynctest.cpp) add_akonadi_isolated_test(SOURCE linktest.cpp) add_akonadi_isolated_test(SOURCE cachetest.cpp) add_akonadi_isolated_test(SOURCE collectionjobtest.cpp) add_akonadi_isolated_test(SOURCE collectionmodifytest.cpp) add_akonadi_isolated_test(SOURCE referencetest.cpp) # FIXME: This is very unstable on Jenkins #add_akonadi_isolated_test(servermanagertest.cpp) add_akonadi_isolated_test( SOURCE tagselectwidgettest.cpp LINK_LIBRARIES KF5::AkonadiWidgets ) # Having a benchmark is cool if you have any reference to compare against, but this # benchmark takes over 40 seconds and does not have any real value to us atm. Major # performance regressions would be spotted by devs anyway, so disabling for now. #add_akonadi_isolated_test(itembenchmark.cpp) #add_akonadi_isolated_test(collectioncreator.cpp) add_akonadi_isolated_test(SOURCE gidtest.cpp) add_akonadi_isolated_test(SOURCE lazypopulationtest.cpp) add_akonadi_isolated_test(SOURCE favoriteproxytest.cpp) # FIXME: this is constantly failing due to broken search: re-enable once the new search code is merged #add_akonadi_isolated_test( # SOURCE itemsearchjobtest.cpp # ADDITIONAL_SOURCES testsearchplugin/testsearchplugin.cpp) add_akonadi_isolated_test(SOURCE tagtest.cpp ADDITIONAL_SOURCES ${CMAKE_BINARY_DIR}/src/core/akonadicore_debug.cpp) add_akonadi_isolated_test(SOURCE tagsynctest.cpp) add_akonadi_isolated_test(SOURCE relationtest.cpp) add_akonadi_isolated_test(SOURCE etmpopulationtest.cpp) diff --git a/autotests/libs/invalidatecachejobtest.cpp b/autotests/libs/invalidatecachejobtest.cpp new file mode 100644 index 000000000..9249f433f --- /dev/null +++ b/autotests/libs/invalidatecachejobtest.cpp @@ -0,0 +1,89 @@ +/* + Copyright (c) 2019 David Faure + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "invalidatecachejob_p.h" + +#include +#include +#include +#include +#include "test_utils.h" +#include "control.h" + +using namespace Akonadi; + +class InvalidateCacheJobTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void shouldClearPayload(); +}; + + +void InvalidateCacheJobTest::initTestCase() +{ + AkonadiTest::checkTestIsIsolated(); + Control::start(); +} + +void InvalidateCacheJobTest::shouldClearPayload() +{ + // Find collection by name + Collection col(collectionIdFromPath(QStringLiteral("res1/foo"))); + const int colId = col.id(); + QVERIFY(colId > 0); + + // Find item with remote id "C" + auto *listJob = new ItemFetchJob(Collection(colId), this); + AKVERIFYEXEC(listJob); + const Item::List items = listJob->items(); + QVERIFY(!items.isEmpty()); + auto it = std::find_if(items.cbegin(), items.cend(), [](const Item &item) { return item.remoteId() == QLatin1String("C"); }); + QVERIFY(it != items.cend()); + const Item::Id itemId = it->id(); + + // Fetch item, from resource, with payload + auto *fetchJob = new ItemFetchJob(Item(itemId), this); + fetchJob->fetchScope().fetchFullPayload(); + AKVERIFYEXEC(fetchJob); + QCOMPARE(fetchJob->items().first().payloadData(), "testmailbody2"); + + // Invalidate cache + auto *invCacheJob = new InvalidateCacheJob(Collection(colId), this); + AKVERIFYEXEC(invCacheJob); + + // Fetch item from cache, should have no payload anymore + auto *fetchFromCacheJob = new ItemFetchJob(Item(itemId), this); + fetchFromCacheJob->fetchScope().fetchFullPayload(); + fetchFromCacheJob->fetchScope().setCacheOnly(true); + AKVERIFYEXEC(fetchFromCacheJob); + QVERIFY(fetchFromCacheJob->items().first().payloadData().isEmpty()); + + // Fetch item from resource again + auto *fetchAgainJob = new ItemFetchJob(Item(itemId), this); + fetchAgainJob->fetchScope().fetchFullPayload(); + AKVERIFYEXEC(fetchAgainJob); + QCOMPARE(fetchAgainJob->items().first().payloadData(), "testmailbody2"); +} + +QTEST_AKONADIMAIN(InvalidateCacheJobTest) + +#include "invalidatecachejobtest.moc" diff --git a/src/core/collectionfetchscope.cpp b/src/core/collectionfetchscope.cpp index d0587703f..e0a989dac 100644 --- a/src/core/collectionfetchscope.cpp +++ b/src/core/collectionfetchscope.cpp @@ -1,210 +1,207 @@ /* Copyright (c) 2008 Kevin Krammer Copyright (c) 2009 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collectionfetchscope.h" #include #include #include namespace Akonadi { class CollectionFetchScopePrivate : public QSharedData { public: CollectionFetchScopePrivate() : ancestorDepth(CollectionFetchScope::None) , listFilter(CollectionFetchScope::Enabled) , statistics(false) - , fetchAllAttributes(false) , fetchIdOnly(true) , mIgnoreRetrievalErrors(false) { } CollectionFetchScopePrivate(const CollectionFetchScopePrivate &other) : QSharedData(other) { resource = other.resource; contentMimeTypes = other.contentMimeTypes; ancestorDepth = other.ancestorDepth; statistics = other.statistics; listFilter = other.listFilter; attributes = other.attributes; if (!ancestorFetchScope && other.ancestorFetchScope) { ancestorFetchScope.reset(new CollectionFetchScope()); *ancestorFetchScope = *other.ancestorFetchScope; } else if (ancestorFetchScope && !other.ancestorFetchScope) { ancestorFetchScope.reset(nullptr); } - fetchAllAttributes = other.fetchAllAttributes; fetchIdOnly = other.fetchIdOnly; mIgnoreRetrievalErrors = other.mIgnoreRetrievalErrors; } public: QString resource; QStringList contentMimeTypes; CollectionFetchScope::AncestorRetrieval ancestorDepth; CollectionFetchScope::ListFilter listFilter; QSet attributes; QScopedPointer ancestorFetchScope; bool statistics; - bool fetchAllAttributes; bool fetchIdOnly; bool mIgnoreRetrievalErrors; }; CollectionFetchScope::CollectionFetchScope() : d(new CollectionFetchScopePrivate()) { } CollectionFetchScope::CollectionFetchScope(const CollectionFetchScope &other) : d(other.d) { } CollectionFetchScope::~CollectionFetchScope() { } CollectionFetchScope &CollectionFetchScope::operator=(const CollectionFetchScope &other) { if (&other != this) { d = other.d; } return *this; } bool CollectionFetchScope::isEmpty() const { return d->resource.isEmpty() && d->contentMimeTypes.isEmpty() && !d->statistics && d->ancestorDepth == None && d->listFilter == Enabled; } bool CollectionFetchScope::includeStatistics() const { return d->statistics; } void CollectionFetchScope::setIncludeStatistics(bool include) { d->statistics = include; } QString CollectionFetchScope::resource() const { return d->resource; } void CollectionFetchScope::setResource(const QString &resource) { d->resource = resource; } QStringList CollectionFetchScope::contentMimeTypes() const { return d->contentMimeTypes; } void CollectionFetchScope::setContentMimeTypes(const QStringList &mimeTypes) { d->contentMimeTypes = mimeTypes; } CollectionFetchScope::AncestorRetrieval CollectionFetchScope::ancestorRetrieval() const { return d->ancestorDepth; } void CollectionFetchScope::setAncestorRetrieval(AncestorRetrieval ancestorDepth) { d->ancestorDepth = ancestorDepth; } CollectionFetchScope::ListFilter CollectionFetchScope::listFilter() const { return d->listFilter; } void CollectionFetchScope::setListFilter(CollectionFetchScope::ListFilter listFilter) { d->listFilter = listFilter; } QSet CollectionFetchScope::attributes() const { return d->attributes; } void CollectionFetchScope::fetchAttribute(const QByteArray &type, bool fetch) { d->fetchIdOnly = false; if (fetch) { d->attributes.insert(type); } else { d->attributes.remove(type); } } void CollectionFetchScope::setFetchIdOnly(bool fetchIdOnly) { d->fetchIdOnly = fetchIdOnly; } bool CollectionFetchScope::fetchIdOnly() const { return d->fetchIdOnly; } void CollectionFetchScope::setIgnoreRetrievalErrors(bool enable) { d->mIgnoreRetrievalErrors = enable; } bool CollectionFetchScope::ignoreRetrievalErrors() const { return d->mIgnoreRetrievalErrors; } void CollectionFetchScope::setAncestorFetchScope(const CollectionFetchScope &scope) { *d->ancestorFetchScope = scope; } CollectionFetchScope CollectionFetchScope::ancestorFetchScope() const { if (!d->ancestorFetchScope) { return CollectionFetchScope(); } return *d->ancestorFetchScope; } CollectionFetchScope &CollectionFetchScope::ancestorFetchScope() { if (!d->ancestorFetchScope) { d->ancestorFetchScope.reset(new CollectionFetchScope()); } return *d->ancestorFetchScope; } } diff --git a/src/core/collectionfetchscope.h b/src/core/collectionfetchscope.h index 2ee426008..4ebbba602 100644 --- a/src/core/collectionfetchscope.h +++ b/src/core/collectionfetchscope.h @@ -1,289 +1,287 @@ /* Copyright (c) 2008 Kevin Krammer Copyright (c) 2009 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_COLLECTIONFETCHSCOPE_H #define AKONADI_COLLECTIONFETCHSCOPE_H #include "akonadicore_export.h" #include #include class QStringList; namespace Akonadi { class CollectionFetchScopePrivate; /** * @short Specifies which parts of a collection should be fetched from the Akonadi storage. * * When collections are fetched from the server either by using CollectionFetchJob * explicitly or when it is being used internally by other classes, e.g. Akonadi::Monitor, * the scope of the fetch operation can be tailored to the application's current needs. * * Note that CollectionFetchScope always includes fetching collection attributes. * * There are two supported ways of changing the currently active CollectionFetchScope * of classes: * - in-place: modify the CollectionFetchScope object the other class holds as a member * - replace: replace the other class' member with a new scope object * * Example: modifying a CollectionFetchJob's scope @c in-place * @code * Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob( collection ); * job->fetchScope().setIncludeUnsubscribed( true ); * @endcode * * Example: @c replacing a CollectionFetchJob's scope * @code * Akonadi::CollectionFetchScope scope; * scope.setIncludeUnsubscribed( true ); * * Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob( collection ); * job->setFetchScope( scope ); * @endcode * * This class is implicitly shared. * * @author Volker Krause * @since 4.4 */ class AKONADICORE_EXPORT CollectionFetchScope { public: /** * Describes the ancestor retrieval depth. */ enum AncestorRetrieval { None, ///< No ancestor retrieval at all (the default) Parent, ///< Only retrieve the immediate parent collection All ///< Retrieve all ancestors, up to Collection::root() }; /** * Creates an empty collection fetch scope. * * Using an empty scope will only fetch the very basic meta data of collections, * e.g. local id, remote id and content mimetypes. */ CollectionFetchScope(); /** * Creates a new collection fetch scope from an @p other. */ CollectionFetchScope(const CollectionFetchScope &other); /** * Destroys the collection fetch scope. */ ~CollectionFetchScope(); /** * Assigns the @p other to this scope and returns a reference to this scope. */ CollectionFetchScope &operator=(const CollectionFetchScope &other); /** * Describes the list filter * * @since 4.14 */ enum ListFilter { NoFilter, ///< No filtering, retrieve all collections Display, ///< Only retrieve collections for display, taking the local preference and enabled into account. Sync, ///< Only retrieve collections for synchronization, taking the local preference and enabled into account. Index, ///< Only retrieve collections for indexing, taking the local preference and enabled into account. Enabled ///< Only retrieve enabled collections, ignoring the local preference. }; /** * Sets a filter for the collections to be listed. * * Note that collections that do not match the filter are included if required to complete the tree. * * @since 4.14 */ void setListFilter(ListFilter); /** * Returns the list filter. * * @see setListFilter() * @since 4.14 */ Q_REQUIRED_RESULT ListFilter listFilter() const; /** * Returns whether collection statistics should be included in the retrieved results. * * @see setIncludeStatistics() */ Q_REQUIRED_RESULT bool includeStatistics() const; /** * Sets whether collection statistics should be included in the retrieved results. * * @param include @c true to include collection statistics, @c false otherwise (the default). */ void setIncludeStatistics(bool include); /** * Returns the resource identifier that is used as filter. * * @see setResource() */ Q_REQUIRED_RESULT QString resource() const; /** * Sets a resource filter, that is only collections owned by the specified resource are * retrieved. * * @param resource The resource identifier. */ void setResource(const QString &resource); /** * Sets a content mimetypes filter, that is only collections that contain at least one of the * given mimetypes (or their parents) are retrieved. * * @param mimeTypes A list of mime types */ void setContentMimeTypes(const QStringList &mimeTypes); /** * Returns the content mimetypes filter. * * @see setContentMimeTypes() */ Q_REQUIRED_RESULT QStringList contentMimeTypes() const; /** * Sets how many levels of ancestor collections should be included in the retrieval. * * Only the ID and the remote ID of the ancestor collections are fetched. If * you want more information about the ancestor collections, like their name, * you will need to do an additional CollectionFetchJob for them. * * @param ancestorDepth The desired ancestor retrieval depth. */ void setAncestorRetrieval(AncestorRetrieval ancestorDepth); /** * Returns the ancestor retrieval depth. * * @see setAncestorRetrieval() */ Q_REQUIRED_RESULT AncestorRetrieval ancestorRetrieval() const; /** * Sets the fetch scope for ancestor retrieval. * * @see setAncestorRetrieval() */ void setAncestorFetchScope(const CollectionFetchScope &scope); /** * Returns the fetch scope for ancestor retrieval. */ Q_REQUIRED_RESULT CollectionFetchScope ancestorFetchScope() const; /** * Returns the fetch scope for ancestor retrieval. */ CollectionFetchScope &ancestorFetchScope(); /** * Returns all explicitly fetched attributes. * - * Undefined if fetchAllAttributes() returns true. - * * @see fetchAttribute() */ Q_REQUIRED_RESULT QSet attributes() const; /** * Sets whether the attribute of the given @p type should be fetched. * * @param type The attribute type to fetch. * @param fetch @c true if the attribute should be fetched, @c false otherwise. */ void fetchAttribute(const QByteArray &type, bool fetch = true); /** * Sets whether the attribute of the requested type should be fetched. * * @param fetch @c true if the attribute should be fetched, @c false otherwise. */ template inline void fetchAttribute(bool fetch = true) { T dummy; fetchAttribute(dummy.type(), fetch); } /** * Sets whether only the id or the complete tag should be fetched. * * The default is @c false. * * @since 4.15 */ void setFetchIdOnly(bool fetchIdOnly); /** * Sets whether only the id of the tags should be retieved or the complete tag. * * @see tagFetchScope() * @since 4.15 */ Q_REQUIRED_RESULT bool fetchIdOnly() const; /** * Ignore retrieval errors while fetching collections, and always deliver what is available. * * This flag is useful to fetch a list of collections, where some might no longer be available. * * @since KF5 */ void setIgnoreRetrievalErrors(bool enabled); /** * Returns whether retrieval errors should be ignored. * * @see setIgnoreRetrievalErrors() * @since KF5 */ Q_REQUIRED_RESULT bool ignoreRetrievalErrors() const; /** * Returns @c true if there is nothing to fetch. */ Q_REQUIRED_RESULT bool isEmpty() const; private: //@cond PRIVATE QSharedDataPointer d; //@endcond }; } #endif diff --git a/src/shared/aktraits.h b/src/shared/aktraits.h index 0393a4b28..2e6e2f817 100644 --- a/src/shared/aktraits.h +++ b/src/shared/aktraits.h @@ -1,163 +1,163 @@ /* Copyright (C) 2019 Daniel Vrátil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_AKTRAITS_H_ #define AKONADI_AKTRAITS_H_ #include #include namespace Akonadi { namespace AkTraits { namespace detail { /// Helpers from C++17 template using void_t = void; template struct conjunction : std::true_type {}; template struct conjunction : T {}; template struct conjunction : std::conditional_t, T> {}; /// Check for presence of member type template> struct hasMember { static constexpr bool value = false; }; template struct hasMember> : std::true_type {}; /// TODO: Use Boost TTI instead? #define DECLARE_HAS_METHOD_GENERIC_IMPL(name, fun, sign) \ template \ struct hasMethod_##name { \ public: \ template \ struct helperClass; \ \ using True = char; \ using False = struct { char dummy_[2]; }; \ \ template \ static True helper(helperClass*);\ template \ static False helper(...); \ public: \ static constexpr bool value = sizeof(helper(nullptr)) == sizeof(True); \ }; #define DECLARE_HAS_METHOD_GENERIC_CONST(fun, R, ...) \ DECLARE_HAS_METHOD_GENERIC_IMPL(fun##_const, fun, R(T::*)(__VA_ARGS__) const) #define DECLARE_HAS_METHOD_GENERIC(fun, R, ...) \ DECLARE_HAS_METHOD_GENERIC_IMPL(fun, fun, R(T::*)(__VA_ARGS__)) - DECLARE_HAS_METHOD_GENERIC_CONST(size, int) + DECLARE_HAS_METHOD_GENERIC_CONST(size, int, void) DECLARE_HAS_METHOD_GENERIC(push_back, void, const typename T::value_type &) DECLARE_HAS_METHOD_GENERIC(insert, typename T::iterator, const typename T::value_type &) DECLARE_HAS_METHOD_GENERIC(reserve, void, int) #define DECLARE_HAS_FUNCTION(name, fun) \ template \ struct has_##name { \ template \ struct helperClass; \ \ using True = char; \ using False = struct { char dummy_[2]; }; \ \ template \ static True helper(helperClass()))>*); \ template \ static False helper(...); \ public: \ static constexpr bool value = sizeof(helper(nullptr)) == sizeof(True); \ }; // For some obscure reason QVector::begin() actually has a default // argument, but QList::begin() does not, thus a regular hasMethod_* check // won't cut it here. Instead we check whether the container object can be // used with std::begin() and std::end() helpers. // Check for constness can be performed by passing "const T" to the type. DECLARE_HAS_FUNCTION(begin, std::begin) DECLARE_HAS_FUNCTION(end, std::end) /// This is a very incomplete set of Container named requirement, but I'm /// too lazy to implement all of them, but this should be good enough to match /// regular Qt containers and /not/ match arbitrary non-container types template struct isContainer : conjunction< std::is_constructible, hasMember, has_begin, has_begin, has_end, has_end, hasMethod_size_const > {}; /// Matches anything that is a container and has push_back() method. template struct isAppendable : conjunction< isContainer, hasMethod_push_back > {}; /// Matches anything that is a container and has insert() method. template struct isInsertable : conjunction< isContainer, hasMethod_insert > {}; /// Matches anything that is a container and has reserve() method. template struct isReservable : conjunction< isContainer, hasMethod_reserve > {}; } template constexpr bool isAppendable = detail::isAppendable::value; template constexpr bool isInsertable = detail::isInsertable::value; template constexpr bool isReservable = detail::isReservable::value; } } #define AK_PP_CAT_(X, Y) X ## Y #define AK_PP_CAT(X, Y) AK_PP_CAT_(X, Y) #define AK_REQUIRES(...) \ bool AK_PP_CAT(_ak_requires_, __LINE__) = false, \ std::enable_if_t< \ AK_PP_CAT(_ak_requires_, __LINE__) || (__VA_ARGS__) \ >* = nullptr #endif