Commit fb7c24d8 authored by Volker Krause's avatar Volker Krause
Browse files

Move IncidenceTreeModel from eventviews here

This is a prerequisite for moving TodoModel from eventviews here as well,
which matters for Kalendar.

The code is unchanged apart from adapting to debug categories and export
macros, and adding the Akonadi namespace.
parent c7f651b2
Pipeline #159814 passed with stage
in 2 minutes and 44 seconds
......@@ -3,7 +3,7 @@
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set(PIM_VERSION "5.20.40")
set(PIM_VERSION "5.20.41")
project(Akonadi-Calendar VERSION ${PIM_VERSION})
# ECM setup
......@@ -47,6 +47,9 @@ target_sources(KF5AkonadiCalendar PRIVATE
......@@ -143,6 +146,7 @@ ecm_generate_headers(AkonadiCalendar_CamelCase_HEADERS
This diff is collapsed.
SPDX-FileCopyrightText: 2012 Sérgio Martins <>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
#pragma once
#include "akonadi-calendar_export.h"
#include <Akonadi/Item>
#include <QAbstractProxyModel>
#include <memory>
namespace Akonadi
class IncidenceTreeModelPrivate;
/** Hierachical incidence model.
* Useful as a source for TodoModel for example.
class AKONADI_CALENDAR_EXPORT IncidenceTreeModel : public QAbstractProxyModel
* Constructs a new IncidenceTreeModel.
explicit IncidenceTreeModel(QObject *parent = nullptr);
* Constructs a new IncidenceTreeModel which will only show incidences of
* type @p mimeTypes. Common use case is a to-do tree.
* This constructor is offered for performance reasons. The filtering has
* zero overhead, and we avoid stacking mime type filter proxy models.
* If you're more concerned about clean design than performance, use the default
* constructor and stack a Akonadi::EntityMimeTypeFilterModel on top of this one.
explicit IncidenceTreeModel(const QStringList &mimeTypes, QObject *parent = nullptr);
~IncidenceTreeModel() override;
Q_REQUIRED_RESULT int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Q_REQUIRED_RESULT int columnCount(const QModelIndex &parent = QModelIndex()) const override;
Q_REQUIRED_RESULT QVariant data(const QModelIndex &index, int role) const override;
Q_REQUIRED_RESULT QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
Q_REQUIRED_RESULT QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
Q_REQUIRED_RESULT QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
Q_REQUIRED_RESULT QModelIndex parent(const QModelIndex &child) const override;
void setSourceModel(QAbstractItemModel *sourceModel) override;
Q_REQUIRED_RESULT bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
* Returns the akonadi item containing the incidence with @p incidenceUid.
Q_REQUIRED_RESULT Akonadi::Item item(const QString &incidenceUid) const;
* This signal is emitted whenever an index changes parent.
* The view can then expand the parent if desired.
* This is better than the view waiting for "rows moved" signals because those
* signals are also sent when the model is initially populated.
void indexChangedParent(const QModelIndex &index);
* Signals that we finished doing a batch of insertions.
* One rowsInserted() signal from the ETM, will make IncidenceTreeModel generate
* several rowsInserted(), layoutChanged() or rowsMoved() signals.
* A tree view can use this signal to know when to call KConfigViewStateSaver::restore()
* to restore expansion states. Listening to rowsInserted() signals would be a
* performance problem.
void batchInsertionFinished();
friend class IncidenceTreeModelPrivate;
std::unique_ptr<IncidenceTreeModelPrivate> const d;
SPDX-FileCopyrightText: 2012 Sérgio Martins <>
SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
#pragma once
#include "incidencetreemodel.h"
#include <Akonadi/Item>
#include <KCalendarCore/Incidence>
#include <QHash>
#include <QModelIndex>
#include <QObject>
#include <QPersistentModelIndex>
#include <QSharedPointer>
#include <QStringList>
#include <QVector>
namespace Akonadi
using Uid = QString;
using ParentUid = QString;
struct Node {
using Ptr = QSharedPointer<Node>;
using Map = QMap<Akonadi::Item::Id, Ptr>;
using List = QVector<Ptr>;
QPersistentModelIndex sourceIndex; // because ETM::modelIndexesForItem is so slow
Akonadi::Item::Id id;
Node::Ptr parentNode;
QString parentUid;
QString uid;
List directChilds;
int depth;
/** Just a struct to contain some data before we create the node */
struct PreNode {
using Ptr = QSharedPointer<PreNode>;
using List = QVector<Ptr>;
KCalendarCore::Incidence::Ptr incidence;
QPersistentModelIndex sourceIndex;
Akonadi::Item item;
int depth;
: depth(-1)
class IncidenceTreeModelPrivate : public QObject
IncidenceTreeModelPrivate(IncidenceTreeModel *qq, const QStringList &mimeTypes);
void reset(bool silent = false);
void insertNode(const PreNode::Ptr &node, bool silent = false);
void insertNode(const QModelIndex &sourceIndex, bool silent = false);
void removeNode(const Node::Ptr &node);
QModelIndex indexForNode(const Node::Ptr &node) const;
int rowForNode(const Node::Ptr &node) const;
bool indexBeingRemoved(const QModelIndex &) const; // Is it being removed?
void dumpTree();
void assert_and_dump(bool condition, const QString &message);
Node::List sorted(const Node::List &nodes) const;
PreNode::Ptr prenodeFromSourceRow(int sourceRow) const;
void setSourceModel(QAbstractItemModel *model);
Node::Map m_nodeMap;
Node::List m_toplevelNodeList;
QHash<Uid, Node::Ptr> m_uidMap;
QHash<Uid, Akonadi::Item> m_itemByUid;
QMultiHash<ParentUid, Node::Ptr> m_waitingForParent;
QList<Node *> m_removedNodes;
const QStringList m_mimeTypes;
private Q_SLOTS:
void onHeaderDataChanged(Qt::Orientation orientation, int first, int last);
void onDataChanged(const QModelIndex &begin, const QModelIndex &end);
void onRowsAboutToBeInserted(const QModelIndex &parent, int begin, int end);
void onRowsInserted(const QModelIndex &parent, int begin, int end);
void onRowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
void onRowsRemoved(const QModelIndex &parent, int begin, int end);
void onRowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
void onModelAboutToBeReset();
void onModelReset();
void onLayoutAboutToBeChanged();
void onLayoutChanged();
IncidenceTreeModel *const q;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment