File indexing completed on 2024-05-12 05:26:01
0001 /* 0002 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) version 3, or any 0008 * later version accepted by the membership of KDE e.V. (or its 0009 * successor approved by the membership of KDE e.V.), which shall 0010 * act as a proxy defined in Section 6 of version 3 of the license. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Lesser General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Lesser General Public 0018 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #pragma once 0022 0023 #include <QAbstractItemModel> 0024 #include <QModelIndex> 0025 #include <QDebug> 0026 #include <QSharedPointer> 0027 #include <functional> 0028 #include "query.h" 0029 #include "log.h" 0030 #include "resultprovider.h" 0031 #include "threadboundary.h" 0032 0033 namespace Sink { 0034 class Notifier; 0035 } 0036 0037 template <class T, class Ptr> 0038 class ModelResult : public QAbstractItemModel 0039 { 0040 public: 0041 //Update the copy in store.h as well if you modify this 0042 enum Roles 0043 { 0044 DomainObjectRole = Qt::UserRole + 1, 0045 ChildrenFetchedRole, 0046 DomainObjectBaseRole, 0047 StatusRole, //ApplicationDomain::SyncStatus 0048 WarningRole, //ApplicationDomain::Warning, only if status == warning || status == error 0049 ProgressRole //ApplicationDomain::Progress 0050 }; 0051 0052 ModelResult(const Sink::Query &query, const QList<QByteArray> &propertyColumns, const Sink::Log::Context &); 0053 ~ModelResult(); 0054 0055 void setEmitter(const typename Sink::ResultEmitter<Ptr>::Ptr &); 0056 0057 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0058 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 0059 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 0060 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 0061 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 0062 QModelIndex parent(const QModelIndex &index) const override; 0063 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; 0064 0065 bool canFetchMore(const QModelIndex &parent) const override; 0066 void fetchMore(const QModelIndex &parent) override; 0067 0068 void setFetcher(const std::function<void()> &fetcher); 0069 0070 void updateQuery(const Sink::Query &query); 0071 0072 private: 0073 void add(const Ptr &value); 0074 void modify(const Ptr &value); 0075 void remove(const Ptr &value); 0076 bool childrenFetched(const QModelIndex &) const; 0077 0078 qint64 parentId(const Ptr &value); 0079 QModelIndex createIndexFromId(const qint64 &id) const; 0080 bool allParentsAvailable(qint64 id) const; 0081 0082 Sink::Log::Context mLogCtx; 0083 // TODO we should be able to directly use T as index, with an appropriate hash function, and thus have a QMap<T, T> and QList<T> 0084 QMap<qint64 /* entity id */, Ptr> mEntities; 0085 QMap<qint64 /* parent entity id */, QList<qint64> /* child entity id*/> mTree; 0086 QMap<qint64 /* child entity id */, qint64 /* parent entity id*/> mParents; 0087 QMap<qint64 /* entity id */, int /* Status */> mEntityStatus; 0088 QSet<qint64> mEntitiesToRemove; 0089 bool mFetchInProgress{false}; 0090 bool mFetchedAll{false}; 0091 bool mFetchComplete{false}; 0092 QList<QByteArray> mPropertyColumns; 0093 Sink::Query mQuery; 0094 std::function<void()> loadEntities; 0095 typename Sink::ResultEmitter<Ptr>::Ptr mEmitter; 0096 async::ThreadBoundary threadBoundary; 0097 QScopedPointer<Sink::Notifier> mNotifier; 0098 };