7#include "aggregatedfetchscope.h" 
    8#include "shared/akranges.h" 
   10#include <QMutexLocker> 
   11#include <QRecursiveMutex> 
   13#define LOCKED_D(name)                                                                                                                                         \ 
   15    QMutexLocker lock(&d->lock); 
   21class AggregatedFetchScopePrivate
 
   24    AggregatedFetchScopePrivate()
 
   29    inline void addToSet(
const QByteArray &value, QSet<QByteArray> &set, QHash<QByteArray, int> &count)
 
   31        auto it = count.
find(value);
 
   32        if (it == count.
end()) {
 
   33            it = count.
insert(value, 0);
 
   39    inline void removeFromSet(
const QByteArray &value, QSet<QByteArray> &set, QHash<QByteArray, int> &count)
 
   41        auto it = count.
find(value);
 
   42        if (it == count.
end()) {
 
   52    inline void updateBool(
bool newValue, 
int &store)
 
   54        store += newValue ? 1 : -1;
 
   57    inline void applySet(
const QSet<QByteArray> &oldSet, 
const QSet<QByteArray> &newSet, QSet<QByteArray> &set, QHash<QByteArray, int> &count)
 
   59        const auto added = newSet - oldSet;
 
   60        for (
const auto &value : added) {
 
   61            addToSet(value, set, count);
 
   63        const auto removed = oldSet - newSet;
 
   64        for (
const auto &value : removed) {
 
   65            removeFromSet(value, set, count);
 
   70    mutable QRecursiveMutex lock;
 
   73class AggregatedCollectionFetchScopePrivate : 
public AggregatedFetchScopePrivate
 
   76    QSet<QByteArray> attrs;
 
   77    QHash<QByteArray, int> attrsCount;
 
   83class AggregatedTagFetchScopePrivate : 
public AggregatedFetchScopePrivate
 
   86    QSet<QByteArray> attrs;
 
   87    QHash<QByteArray, int> attrsCount;
 
   90    int fetchRemoteId = 0;
 
   91    int doNotFetchAllAttributes = 0;
 
   94class AggregatedItemFetchScopePrivate : 
public AggregatedFetchScopePrivate
 
   97    mutable Protocol::ItemFetchScope mCachedScope;
 
   98    mutable bool mCachedScopeValid = 
false; 
 
  100    QSet<QByteArray> parts;
 
  101    QHash<QByteArray, int> partsCount;
 
  102    QSet<QByteArray> tags;
 
  103    QHash<QByteArray, int> tagsCount;
 
  105    int ancestors[3] = {0, 0, 0}; 
 
  108    int allAttributes = 0;
 
  112    int ignoreErrors = 0;
 
  124using namespace Akonadi::Protocol;
 
  125using namespace Akonadi::Server;
 
  127AggregatedCollectionFetchScope::AggregatedCollectionFetchScope()
 
  128    : d_ptr(new AggregatedCollectionFetchScopePrivate)
 
  132AggregatedCollectionFetchScope::~AggregatedCollectionFetchScope() = 
default;
 
  134void AggregatedCollectionFetchScope::apply(
const Protocol::CollectionFetchScope &oldScope, 
const Protocol::CollectionFetchScope &newScope)
 
  136    LOCKED_D(AggregatedCollectionFetchScope)
 
  138    if (newScope.includeStatistics() != oldScope.includeStatistics()) {
 
  139        d->updateBool(newScope.includeStatistics(), d->fetchStats);
 
  141    if (newScope.fetchIdOnly() != oldScope.fetchIdOnly()) {
 
  142        d->updateBool(newScope.fetchIdOnly(), d->fetchIdOnly);
 
  144    if (newScope.attributes() != oldScope.attributes()) {
 
  145        d->applySet(oldScope.attributes(), newScope.attributes(), d->attrs, d->attrsCount);
 
  149QSet<QByteArray> AggregatedCollectionFetchScope::attributes()
 const 
  151    LOCKED_D(
const AggregatedCollectionFetchScope)
 
  155bool AggregatedCollectionFetchScope::fetchIdOnly()
 const 
  157    LOCKED_D(
const AggregatedCollectionFetchScope)
 
  160    return d->fetchIdOnly == d->subscribers;
 
  163bool AggregatedCollectionFetchScope::fetchStatistics()
 const 
  165    LOCKED_D(
const AggregatedCollectionFetchScope);
 
  167    return d->fetchStats > 0;
 
  170void AggregatedCollectionFetchScope::addSubscriber()
 
  172    LOCKED_D(AggregatedCollectionFetchScope)
 
  176void AggregatedCollectionFetchScope::removeSubscriber()
 
  178    LOCKED_D(AggregatedCollectionFetchScope)
 
  182AggregatedItemFetchScope::AggregatedItemFetchScope()
 
  183    : d_ptr(new AggregatedItemFetchScopePrivate)
 
  187AggregatedItemFetchScope::~AggregatedItemFetchScope() = 
default;
 
  189void AggregatedItemFetchScope::apply(
const Protocol::ItemFetchScope &oldScope, 
const Protocol::ItemFetchScope &newScope)
 
  191    LOCKED_D(AggregatedItemFetchScope);
 
  193    const auto newParts = newScope.requestedParts() | AkRanges::Actions::toQSet;
 
  194    const auto oldParts = oldScope.requestedParts() | AkRanges::Actions::toQSet;
 
  195    if (newParts != oldParts) {
 
  196        d->applySet(oldParts, newParts, d->parts, d->partsCount);
 
  198    if (newScope.ancestorDepth() != oldScope.ancestorDepth()) {
 
  199        updateAncestorDepth(oldScope.ancestorDepth(), newScope.ancestorDepth());
 
  201    if (newScope.cacheOnly() != oldScope.cacheOnly()) {
 
  202        d->updateBool(newScope.cacheOnly(), d->cacheOnly);
 
  204    if (newScope.fullPayload() != oldScope.fullPayload()) {
 
  205        d->updateBool(newScope.fullPayload(), d->fullPayload);
 
  207    if (newScope.allAttributes() != oldScope.allAttributes()) {
 
  208        d->updateBool(newScope.allAttributes(), d->allAttributes);
 
  210    if (newScope.fetchSize() != oldScope.fetchSize()) {
 
  211        d->updateBool(newScope.fetchSize(), d->fetchSize);
 
  213    if (newScope.fetchMTime() != oldScope.fetchMTime()) {
 
  214        d->updateBool(newScope.fetchMTime(), d->fetchMTime);
 
  216    if (newScope.fetchRemoteRevision() != oldScope.fetchRemoteRevision()) {
 
  217        d->updateBool(newScope.fetchRemoteRevision(), d->fetchRRev);
 
  219    if (newScope.ignoreErrors() != oldScope.ignoreErrors()) {
 
  220        d->updateBool(newScope.ignoreErrors(), d->ignoreErrors);
 
  222    if (newScope.fetchFlags() != oldScope.fetchFlags()) {
 
  223        d->updateBool(newScope.fetchFlags(), d->fetchFlags);
 
  225    if (newScope.fetchRemoteId() != oldScope.fetchRemoteId()) {
 
  226        d->updateBool(newScope.fetchRemoteId(), d->fetchRID);
 
  228    if (newScope.fetchGID() != oldScope.fetchGID()) {
 
  229        d->updateBool(newScope.fetchGID(), d->fetchGID);
 
  231    if (newScope.fetchTags() != oldScope.fetchTags()) {
 
  232        d->updateBool(newScope.fetchTags(), d->fetchTags);
 
  234    if (newScope.fetchVirtualReferences() != oldScope.fetchVirtualReferences()) {
 
  235        d->updateBool(newScope.fetchVirtualReferences(), d->fetchVRefs);
 
  238    d->mCachedScopeValid = 
false;
 
  241ItemFetchScope AggregatedItemFetchScope::toFetchScope()
 const 
  243    LOCKED_D(
const AggregatedItemFetchScope);
 
  244    if (d->mCachedScopeValid) {
 
  245        return d->mCachedScope;
 
  248    d->mCachedScope = ItemFetchScope();
 
  249    d->mCachedScope.setRequestedParts(d->parts | AkRanges::Actions::toQVector);
 
  250    d->mCachedScope.setAncestorDepth(ancestorDepth());
 
  252    d->mCachedScope.setFetch(ItemFetchScope::CacheOnly, cacheOnly());
 
  253    d->mCachedScope.setFetch(ItemFetchScope::FullPayload, fullPayload());
 
  254    d->mCachedScope.setFetch(ItemFetchScope::AllAttributes, allAttributes());
 
  255    d->mCachedScope.setFetch(ItemFetchScope::Size, fetchSize());
 
  256    d->mCachedScope.setFetch(ItemFetchScope::MTime, fetchMTime());
 
  257    d->mCachedScope.setFetch(ItemFetchScope::RemoteRevision, fetchRemoteRevision());
 
  258    d->mCachedScope.setFetch(ItemFetchScope::IgnoreErrors, ignoreErrors());
 
  259    d->mCachedScope.setFetch(ItemFetchScope::Flags, fetchFlags());
 
  260    d->mCachedScope.setFetch(ItemFetchScope::RemoteID, fetchRemoteId());
 
  261    d->mCachedScope.setFetch(ItemFetchScope::GID, fetchGID());
 
  262    d->mCachedScope.setFetch(ItemFetchScope::Tags, fetchTags());
 
  263    d->mCachedScope.setFetch(ItemFetchScope::VirtReferences, fetchVirtualReferences());
 
  264    d->mCachedScopeValid = 
true;
 
  265    return d->mCachedScope;
 
  268QSet<QByteArray> AggregatedItemFetchScope::requestedParts()
 const 
  270    LOCKED_D(
const AggregatedItemFetchScope)
 
  274ItemFetchScope::AncestorDepth AggregatedItemFetchScope::ancestorDepth()
 const 
  276    LOCKED_D(
const AggregatedItemFetchScope)
 
  278    if (d->ancestors[ItemFetchScope::AllAncestors] > 0) {
 
  279        return ItemFetchScope::AllAncestors;
 
  280    } 
else if (d->ancestors[ItemFetchScope::ParentAncestor] > 0) {
 
  281        return ItemFetchScope::ParentAncestor;
 
  283        return ItemFetchScope::NoAncestor;
 
  287void AggregatedItemFetchScope::updateAncestorDepth(ItemFetchScope::AncestorDepth oldDepth, ItemFetchScope::AncestorDepth newDepth)
 
  289    LOCKED_D(AggregatedItemFetchScope)
 
  290    if (d->ancestors[oldDepth] > 0) {
 
  291        --d->ancestors[oldDepth];
 
  293    ++d->ancestors[newDepth];
 
  296bool AggregatedItemFetchScope::cacheOnly()
 const 
  298    LOCKED_D(
const AggregatedItemFetchScope)
 
  301    return d->cacheOnly == d->subscribers;
 
  304bool AggregatedItemFetchScope::fullPayload()
 const 
  306    LOCKED_D(
const AggregatedItemFetchScope)
 
  309    return d->fullPayload > 0;
 
  312bool AggregatedItemFetchScope::allAttributes()
 const 
  314    LOCKED_D(
const AggregatedItemFetchScope)
 
  317    return d->allAttributes > 0;
 
  320bool AggregatedItemFetchScope::fetchSize()
 const 
  322    LOCKED_D(
const AggregatedItemFetchScope)
 
  324    return d->fetchSize > 0;
 
  327bool AggregatedItemFetchScope::fetchMTime()
 const 
  329    LOCKED_D(
const AggregatedItemFetchScope)
 
  331    return d->fetchMTime > 0;
 
  334bool AggregatedItemFetchScope::fetchRemoteRevision()
 const 
  336    LOCKED_D(
const AggregatedItemFetchScope)
 
  338    return d->fetchRRev > 0;
 
  341bool AggregatedItemFetchScope::ignoreErrors()
 const 
  343    LOCKED_D(
const AggregatedItemFetchScope)
 
  346    return d->ignoreErrors == d->subscribers;
 
  349bool AggregatedItemFetchScope::fetchFlags()
 const 
  351    LOCKED_D(
const AggregatedItemFetchScope)
 
  353    return d->fetchFlags > 0;
 
  356bool AggregatedItemFetchScope::fetchRemoteId()
 const 
  358    LOCKED_D(
const AggregatedItemFetchScope)
 
  360    return d->fetchRID > 0;
 
  363bool AggregatedItemFetchScope::fetchGID()
 const 
  365    LOCKED_D(
const AggregatedItemFetchScope)
 
  367    return d->fetchGID > 0;
 
  370bool AggregatedItemFetchScope::fetchTags()
 const 
  372    LOCKED_D(
const AggregatedItemFetchScope)
 
  374    return d->fetchTags > 0;
 
  377bool AggregatedItemFetchScope::fetchVirtualReferences()
 const 
  379    LOCKED_D(
const AggregatedItemFetchScope)
 
  381    return d->fetchVRefs > 0;
 
  384void AggregatedItemFetchScope::addSubscriber()
 
  386    LOCKED_D(AggregatedItemFetchScope)
 
  390void AggregatedItemFetchScope::removeSubscriber()
 
  392    LOCKED_D(AggregatedItemFetchScope)
 
  396AggregatedTagFetchScope::AggregatedTagFetchScope()
 
  397    : d_ptr(new AggregatedTagFetchScopePrivate)
 
  401AggregatedTagFetchScope::~AggregatedTagFetchScope() = 
default;
 
  403void AggregatedTagFetchScope::apply(
const Protocol::TagFetchScope &oldScope, 
const Protocol::TagFetchScope &newScope)
 
  405    LOCKED_D(AggregatedTagFetchScope)
 
  407    if (newScope.fetchIdOnly() != oldScope.fetchIdOnly()) {
 
  408        d->updateBool(newScope.fetchIdOnly(), d->fetchIdOnly);
 
  410    if (newScope.fetchRemoteID() != oldScope.fetchRemoteID()) {
 
  411        d->updateBool(newScope.fetchRemoteID(), d->fetchRemoteId);
 
  413    if (newScope.fetchAllAttributes() != oldScope.fetchAllAttributes()) {
 
  415        d->updateBool(!newScope.fetchAllAttributes(), d->doNotFetchAllAttributes);
 
  417    if (newScope.attributes() != oldScope.attributes()) {
 
  418        d->applySet(oldScope.attributes(), newScope.attributes(), d->attrs, d->attrsCount);
 
  422Protocol::TagFetchScope AggregatedTagFetchScope::toFetchScope()
 const 
  424    Protocol::TagFetchScope tfs;
 
  425    tfs.setFetchIdOnly(fetchIdOnly());
 
  426    tfs.setFetchRemoteID(fetchRemoteId());
 
  427    tfs.setFetchAllAttributes(fetchAllAttributes());
 
  428    tfs.setAttributes(attributes());
 
  432bool AggregatedTagFetchScope::fetchIdOnly()
 const 
  434    LOCKED_D(
const AggregatedTagFetchScope)
 
  437    return d->fetchIdOnly == d->subscribers;
 
  440bool AggregatedTagFetchScope::fetchRemoteId()
 const 
  442    LOCKED_D(
const AggregatedTagFetchScope)
 
  443    return d->fetchRemoteId > 0;
 
  446bool AggregatedTagFetchScope::fetchAllAttributes()
 const 
  448    LOCKED_D(
const AggregatedTagFetchScope)
 
  450    return d->doNotFetchAllAttributes != d->subscribers;
 
  453QSet<QByteArray> AggregatedTagFetchScope::attributes()
 const 
  455    LOCKED_D(
const AggregatedTagFetchScope)
 
  459void AggregatedTagFetchScope::addSubscriber()
 
  461    LOCKED_D(AggregatedTagFetchScope)
 
  465void AggregatedTagFetchScope::removeSubscriber()
 
  467    LOCKED_D(AggregatedTagFetchScope)
 
Helper integration between Akonadi and Qt.
 
iterator erase(const_iterator pos)
 
iterator find(const Key &key)
 
iterator insert(const Key &key, const T &value)
 
iterator insert(const T &value)
 
bool remove(const T &value)