7#include "collectiontreecache.h"
8#include "akonadiserver_debug.h"
9#include "commandcontext.h"
10#include "selectquerybuilder.h"
12#include "private/scope_p.h"
21using namespace Akonadi::Server;
38CollectionTreeCache::Node::Node()
45CollectionTreeCache::Node::Node(
const Collection &col)
53CollectionTreeCache::Node::~Node()
58void CollectionTreeCache::Node::appendChild(
Node *child)
64void CollectionTreeCache::Node::removeChild(
Node *child)
66 child->parent =
nullptr;
70CollectionTreeCache::CollectionTreeCache()
71 : AkThread(QStringLiteral(
"CollectionTreeCache"))
75CollectionTreeCache::~CollectionTreeCache()
80void CollectionTreeCache::init()
88 mRoot->parent =
nullptr;
89 mNodeLookup.
insert(0, mRoot);
92 qb.addSortColumn(Collection::idFullColumnName(), Query::Ascending);
101 const auto collections =
qb.result();
102 for (
const auto &
col : collections) {
108 parent->appendChild(node);
109 mNodeLookup.
insert(node->id, node);
134 auto node =
it->second;
135 parent->appendChild(node);
136 mNodeLookup.
insert(node->id, node);
154 delete unref->second;
157 qCWarning(
AKONADISERVER_LOG) <<
"Please run \"akonadictl fsck\" to correct the inconsistencies!";
169 Q_ASSERT(mNodeLookup.
size() == collections.count() + 1 );
173void CollectionTreeCache::quit()
180void CollectionTreeCache::collectionAdded(
const Collection &col)
186 qCWarning(
AKONADISERVER_LOG) <<
"Received a new collection (" <<
col.id() <<
") with unknown parent (" <<
col.parentId() <<
")";
191 parent->appendChild(node);
192 mNodeLookup.
insert(node->id, node);
195void CollectionTreeCache::collectionChanged(
const Collection &col)
199 auto node = mNodeLookup.
value(
col.id(),
nullptr);
206 if (node->collection.isValid()) {
207 node->collection =
col;
211void CollectionTreeCache::collectionMoved(
const Collection &col)
215 auto node = mNodeLookup.
value(
col.id(),
nullptr);
224 qCWarning(
AKONADISERVER_LOG) <<
"Received a moved collection (" <<
col.id() <<
") with an unknown move destination (" <<
col.parentId() <<
")";
230 if (node->collection.isValid()) {
231 node->collection =
col;
235void CollectionTreeCache::collectionRemoved(
const Collection &col)
239 auto node = mNodeLookup.
value(
col.id(),
nullptr);
246 parent->removeChild(node);
247 mNodeLookup.
remove(node->id);
251CollectionTreeCache::Node *CollectionTreeCache::findNode(
const QString &rid,
const QString &resource)
const
256 auto root = std::find_if(mRoot->children.
cbegin(), mRoot->children.
cend(), [resource](
Node *node) {
260 return node->collection.resource().name() == resource;
262 if (root == mRoot->children.
cend()) {
266 return findNode((*root), [rid](
Node *node) {
267 return node->collection.remoteId() == rid;
271QList<Collection> CollectionTreeCache::retrieveCollections(CollectionTreeCache::Node *root,
int depth,
int ancestorDepth)
const
278 for (
int i = 0;
i < ancestorDepth &&
parent !=
nullptr; ++
i) {
288 stack.
push({root, 0});
290 auto c = stack.
pop();
291 if (c.depth > depth) {
295 if (c.node->id > 0) {
296 nodes.push_back(c.node);
300 stack.
push({child, c.depth + 1});
306 for (
auto node :
nodes) {
307 if (node->collection.isValid()) {
308 cols.push_back(node->collection);
319 cond.addValueCondition(Collection::idFullColumnName(), Query::Equals, node->id);
323 qCWarning(
AKONADISERVER_LOG) <<
"Failed to retrieve collections from the database";
327 const auto results =
qb.result();
328 if (results.size() !=
missing.size()) {
329 qCWarning(
AKONADISERVER_LOG) <<
"Could not obtain all missing collections! Node tree refers to a non-existent collection";
339 auto it = std::find_if(results.cbegin(), results.cend(), [node](
const Collection &
col) {
340 return node->id == col.id();
346 node->collection = *
it;
354CollectionTreeCache::retrieveCollections(
const Scope &scope,
int depth,
int ancestorDepth,
const QString &resource, CommandContext *context)
const
356 if (scope.isEmpty()) {
357 return retrieveCollections(mRoot, depth, ancestorDepth);
358 }
else if (scope.scope() == Scope::Rid) {
360 Q_ASSERT(!resource.
isEmpty() || (context && context->resource().isValid()));
362 Node *node =
nullptr;
364 node = findNode(scope.rid(), resource);
365 }
else if (context && context->resource().isValid()) {
366 node = findNode(scope.rid(), context->resource().
name());
372 return retrieveCollections(node, depth, ancestorDepth);
374 }
else if (scope.scope() == Scope::Uid) {
375 Node *node = mNodeLookup.
value(scope.uid());
377 return retrieveCollections(node, depth, ancestorDepth);
384#include "moc_collectiontreecache.cpp"
Represents a collection of PIM items.
Represents a WHERE condition tree.
Helper class for creating and executing database SELECT queries.
A glue between Qt and the standard library.
iterator insert(const Key &key, const T &value)
bool remove(const Key &key)
qsizetype size() const const
T value(const Key &key) const const
const_iterator cbegin() const const
const_iterator cend() const const
bool isEmpty() const const
const QObjectList & children() const const
QObject * parent() const const
T qobject_cast(QObject *object)
bool isEmpty() const const