From 1b178b25ada269b89704a4dcc771f7a6f50c9286 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> Date: Mon, 9 Mar 2015 13:49:46 -0400 Subject: [PATCH] collection: Port the collection model to the new API Refs #68098 --- CMakeLists.txt | 2 + src/backendmanagerinterface.hpp | 105 ------------------------- src/collectionmanagerinterface.cpp | 33 ++++++++ src/collectionmanagerinterface.h | 26 ++++++- src/collectionmanagerinterface.hpp | 4 + src/collectionmodel.cpp | 120 +++++++++++++++-------------- src/collectionmodel.h | 8 +- src/private/collectionmodel_p.h | 65 ++++++++++++++++ 8 files changed, 198 insertions(+), 165 deletions(-) delete mode 100644 src/backendmanagerinterface.hpp create mode 100644 src/collectionmanagerinterface.cpp create mode 100644 src/private/collectionmodel_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1906d59c..c974ab81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,7 @@ SET( libringclient_LIB_SRCS src/securityvalidationmodel.cpp src/personmodel.cpp src/collectionmodel.cpp + src/collectionmanagerinterface.cpp src/networkinterfacemodel.cpp src/certificatemodel.cpp src/ciphermodel.cpp @@ -453,6 +454,7 @@ SET(libringclient_PRIVATE_HDRS src/private/phonedirectorymodel_p.h src/private/instantmessagingmodel_p.h src/private/videorenderer_p.h + src/private/collectionmodel_p.h ) IF(${ENABLE_LIBWRAP} MATCHES true) diff --git a/src/backendmanagerinterface.hpp b/src/backendmanagerinterface.hpp deleted file mode 100644 index 7818eb7e..00000000 --- a/src/backendmanagerinterface.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2014-2015 by Savoir-Faire Linux * - * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 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 * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ - -template <class T> -class BackendManagerInterfacePrivate -{ -public: - BackendManagerInterfacePrivate(BackendManagerInterface<T>* p) : m_pMediator(nullptr),q_ptr(p) - {} - ~BackendManagerInterfacePrivate(); - - QVector< CollectionInterface* > m_lBackends; - QVector< CollectionInterface* > m_lEnabledBackends; - mutable CollectionMediator<T>* m_pMediator; - BackendManagerInterface<T>* q_ptr; - - CollectionMediator<T>* itemMediator() const; -}; - -template<class T> -CollectionMediator<T>* BackendManagerInterfacePrivate<T>::itemMediator() const -{ - if (!m_pMediator) { - m_pMediator = new CollectionMediator<T>(q_ptr); - } - return m_pMediator; -} - -template<class T> -BackendManagerInterfacePrivate<T>::~BackendManagerInterfacePrivate() -{ - if (m_pMediator) - delete m_pMediator; -} - -template<class T> -template <class T2> -CollectionInterface* BackendManagerInterface<T>::addBackend(const LoadOptions options) -{ - T2* backend = new T2(d_ptr->itemMediator()); - d_ptr->m_lBackends << backend; - - if (options & LoadOptions::FORCE_ENABLED) { //TODO check is the backend is checked - - //Some collections can fail to load directly - //eventually it will necessary to add an async version of this - //to load the backend only when it is loaded - if (backend->load()) - d_ptr->m_lEnabledBackends << backend; - } - - return backend; -} - -template<class T> -BackendManagerInterface<T>::BackendManagerInterface() : d_ptr(new BackendManagerInterfacePrivate<T>(this)) -{ - -} - -template<class T> -const QVector< CollectionInterface* > BackendManagerInterface<T>::collections() const -{ - return d_ptr->m_lBackends; -} - -template<class T> -const QVector< CollectionInterface* > BackendManagerInterface<T>::enabledCollections() const -{ - return d_ptr->m_lEnabledBackends; -} - -/// Do this manager have active collections -template<class T> -bool BackendManagerInterface<T>::hasEnabledCollections() const -{ - return d_ptr->m_lEnabledBackends.size(); -} - -template<class T> -bool BackendManagerInterface<T>::hasCollections() const -{ - return d_ptr->m_lBackends.size(); -} - -template<class T> -bool BackendManagerInterface<T>::clearAllCollections() const -{ - return false; -} diff --git a/src/collectionmanagerinterface.cpp b/src/collectionmanagerinterface.cpp new file mode 100644 index 00000000..78782919 --- /dev/null +++ b/src/collectionmanagerinterface.cpp @@ -0,0 +1,33 @@ +/**************************************************************************** + * Copyright (C) 2014-2015 by Savoir-Faire Linux * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "collectionmanagerinterface.h" + +//Ring +#include <collectionmodel.h> +#include "private/collectionmodel_p.h" + +class CollectionManagerInterfaceBasePrivate +{ +public: + +}; + +void CollectionManagerInterfaceBase::registerToModel(CollectionInterface* col) const +{ + CollectionModel::instance()->d_ptr->registerNew(col); +} \ No newline at end of file diff --git a/src/collectionmanagerinterface.h b/src/collectionmanagerinterface.h index 7ead6bc4..ab1e6b6b 100644 --- a/src/collectionmanagerinterface.h +++ b/src/collectionmanagerinterface.h @@ -30,7 +30,6 @@ #include <collectioninterface.h> #include <collectionmediator.h> -class CommonCollectionModel; class QAbstractItemModel; enum LoadOptions { @@ -39,6 +38,29 @@ enum LoadOptions { FORCE_DISABLED = 0x1 << 1, }; +class CollectionManagerInterfaceBasePrivate; + +/** + * Common elements for each CollectionManagerInterface + */ +class CollectionManagerInterfaceBase { +public: + virtual bool hasEnabledCollections (CollectionInterface::SupportedFeatures features = CollectionInterface::SupportedFeatures::NONE) const = 0; + virtual bool hasCollections (CollectionInterface::SupportedFeatures features = CollectionInterface::SupportedFeatures::NONE) const = 0; + + ///Enable / disable a collection + virtual bool enableBackend( CollectionInterface* collection, bool enabled) = 0; + + virtual bool clearAllCollections() const = 0; + +protected: + void registerToModel(CollectionInterface* col) const; + +private: + CollectionManagerInterfaceBasePrivate* d_ptr; + Q_DECLARE_PRIVATE(CollectionManagerInterfaceBase) +}; + template <class T> class CollectionManagerInterfacePrivate; @@ -65,7 +87,7 @@ class CollectionManagerInterfacePrivate; * implement the common logic that should otherwise have been copy pasted in each * collections. */ -template <class T> class LIB_EXPORT CollectionManagerInterface { +template <class T> class LIB_EXPORT CollectionManagerInterface : public CollectionManagerInterfaceBase { friend class CollectionMediator<T>; public: diff --git a/src/collectionmanagerinterface.hpp b/src/collectionmanagerinterface.hpp index d196fce8..c0f7c422 100644 --- a/src/collectionmanagerinterface.hpp +++ b/src/collectionmanagerinterface.hpp @@ -72,6 +72,8 @@ T2* CollectionManagerInterface<T>::addBackend(const LoadOptions options) d_ptr->m_lEnabledCollections << backend; } + registerToModel(backend); + return backend; } #else @@ -93,6 +95,8 @@ T2* CollectionManagerInterface<T>::addBackend(Ts... args, const LoadOptions opti d_ptr->m_lEnabledCollections << collection; } + registerToModel(collection); + return collection; } #endif //Q_OS_DARWIN diff --git a/src/collectionmodel.cpp b/src/collectionmodel.cpp index 535b3af2..05e66d0a 100644 --- a/src/collectionmodel.cpp +++ b/src/collectionmodel.cpp @@ -17,40 +17,16 @@ ***************************************************************************/ #include "collectionmodel.h" +//Qt +#include <QtCore/QCoreApplication> + +//Ring #include "collectionmanagerinterface.h" #include "delegates/itemmodelstateserializationdelegate.h" #include "collectionextensioninterface.h" +#include "private/collectionmodel_p.h" -class CollectionModelPrivate : public QObject -{ - Q_OBJECT -public: - CollectionModelPrivate(CollectionModel* parent); - - /* - * This is not very efficient, it doesn't really have to be given the low - * volume. If it ever have to scale, a better mapToSource using persistent - * index have to be implemented. - */ - struct ProxyItem { - ProxyItem() : parent(nullptr),col(1),row(0),backend(nullptr){} - int row; - int col; - CollectionInterface* backend; - ProxyItem* parent; - QVector<ProxyItem*> m_Children; - }; - QHash<CollectionInterface**,ProxyItem*> m_hBackendsNodes; - QVector<ProxyItem*> m_lTopLevelBackends; - QVector<CollectionExtensionInterface*> m_lExtensions; - -private: - CollectionModel* q_ptr; - -private Q_SLOTS: - void slotUpdate(); - void slotExtensionDataChanged(const QModelIndex& idx); -}; +CollectionModel* CollectionModelPrivate::m_spInstance = nullptr; CollectionModelPrivate::CollectionModelPrivate(CollectionModel* parent) : QObject(parent),q_ptr(parent) {} @@ -77,6 +53,13 @@ CollectionModel::~CollectionModel() } } +CollectionModel* CollectionModel::instance() +{ + if (!CollectionModelPrivate::m_spInstance) + CollectionModelPrivate::m_spInstance = new CollectionModel(QCoreApplication::instance()); + return CollectionModelPrivate::m_spInstance; +} + QHash<int,QByteArray> CollectionModel::roleNames() const { static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); @@ -94,20 +77,20 @@ QVariant CollectionModel::data (const QModelIndex& idx, int role) const CollectionModelPrivate::ProxyItem* item = static_cast<CollectionModelPrivate::ProxyItem*>(idx.internalPointer()); if (idx.column() > 0) - return d_ptr->m_lExtensions[idx.column()-1]->data(item->backend,idx,role); + return d_ptr->m_lExtensions[idx.column()-1]->data(item->collection,idx,role); switch(role) { case Qt::DisplayRole: - return item->backend->name(); + return item->collection->name(); break; case Qt::DecorationRole: - return item->backend->icon(); + return item->collection->icon(); break; // case Qt::CheckStateRole: -// return item->backend->isEnabled()?Qt::Checked:Qt::Unchecked; +// return item->collection->isEnabled()?Qt::Checked:Qt::Unchecked; case Qt::CheckStateRole: { if (ItemModelStateSerializationDelegate::instance()) - return ItemModelStateSerializationDelegate::instance()->isChecked(item->backend)?Qt::Checked:Qt::Unchecked; + return ItemModelStateSerializationDelegate::instance()->isChecked(item->collection)?Qt::Checked:Qt::Unchecked; } }; } @@ -121,18 +104,11 @@ QVariant CollectionModel::data (const QModelIndex& idx, int role) const int CollectionModel::rowCount (const QModelIndex& parent) const { if (!parent.isValid()) { - static bool init = false; //FIXME this doesn't allow dynamic collections - static int result = 0; - if (!init) { - for(int i=0;i<PersonModel::instance()->collections().size();i++) - result += PersonModel::instance()->collections()[i]->parent()==nullptr?1:0; - init = true; - } - return result; + return d_ptr->m_lTopLevelBackends.size(); } else { CollectionModelPrivate::ProxyItem* item = static_cast<CollectionModelPrivate::ProxyItem*>(parent.internalPointer()); - return item->backend->children().size(); + return item->collection->children().size(); } } @@ -149,10 +125,10 @@ Qt::ItemFlags CollectionModel::flags(const QModelIndex& idx) const CollectionModelPrivate::ProxyItem* item = static_cast<CollectionModelPrivate::ProxyItem*>(idx.internalPointer()); if (idx.column() > 0) { //Make sure the cell is disabled if the row is - Qt::ItemFlags f = d_ptr->m_lExtensions[idx.column()-1]->flags(item->backend,idx); - return (((f&Qt::ItemIsEnabled)&&(!item->backend->isEnabled()))?f^Qt::ItemIsEnabled:f); + Qt::ItemFlags f = d_ptr->m_lExtensions[idx.column()-1]->flags(item->collection,idx); + return (((f&Qt::ItemIsEnabled)&&(!item->collection->isEnabled()))?f^Qt::ItemIsEnabled:f); } - const bool checkable = item->backend->supportedFeatures() & (CollectionInterface::SupportedFeatures::ENABLEABLE | + const bool checkable = item->collection->supportedFeatures() & (CollectionInterface::SupportedFeatures::ENABLEABLE | CollectionInterface::SupportedFeatures::DISABLEABLE | CollectionInterface::SupportedFeatures::MANAGEABLE ); return Qt::ItemIsEnabled | Qt::ItemIsSelectable | (checkable?Qt::ItemIsUserCheckable:Qt::NoItemFlags); } @@ -164,14 +140,14 @@ bool CollectionModel::setData (const QModelIndex& idx, const QVariant &value, in Q_UNUSED(role) if (idx.isValid() && idx.column() > 0) { CollectionModelPrivate::ProxyItem* item = static_cast<CollectionModelPrivate::ProxyItem*>(idx.internalPointer()); - return d_ptr->m_lExtensions[idx.column()-1]->setData(item->backend,idx,value,role); + return d_ptr->m_lExtensions[idx.column()-1]->setData(item->collection,idx,value,role); } if (role == Qt::CheckStateRole && idx.column() == 0) { CollectionModelPrivate::ProxyItem* item = static_cast<CollectionModelPrivate::ProxyItem*>(idx.internalPointer()); if (item) { - const bool old = item->backend->isEnabled(); - ItemModelStateSerializationDelegate::instance()->setChecked(item->backend,value==Qt::Checked); + const bool old = item->collection->isEnabled(); + ItemModelStateSerializationDelegate::instance()->setChecked(item->collection,value==Qt::Checked); emit dataChanged(index(idx.row(),0),index(idx.row(),columnCount()-1)); if (old != (value==Qt::Checked)) { emit checkStateChanged(); @@ -203,7 +179,7 @@ QModelIndex CollectionModel::index( int row, int column, const QModelIndex& pare else { item = new CollectionModelPrivate::ProxyItem(); item->parent = parentItem; - item->backend = parentItem->backend->children()[row]; + item->collection = parentItem->collection->children()[row]; parentItem->m_Children << item; } item->row = row; @@ -220,7 +196,7 @@ QModelIndex CollectionModel::index( int row, int column, const QModelIndex& pare return QModelIndex(); item = new CollectionModelPrivate::ProxyItem(); - item->backend = PersonModel::instance()->collections()[row]; + item->collection = PersonModel::instance()->collections()[row]; d_ptr->m_lTopLevelBackends << item; } item->row = row; @@ -251,7 +227,7 @@ bool CollectionModel::save() //Load newly enabled collections foreach(CollectionModelPrivate::ProxyItem* top, d_ptr->m_lTopLevelBackends) { - CollectionInterface* current = top->backend; + CollectionInterface* current = top->collection; bool check = ItemModelStateSerializationDelegate::instance()->isChecked(current); bool wasChecked = current->isEnabled(); if (check && !wasChecked) @@ -261,7 +237,7 @@ bool CollectionModel::save() //TODO implement real tree digging foreach(CollectionModelPrivate::ProxyItem* leaf ,top->m_Children) { - current = leaf->backend; + current = leaf->collection; check = ItemModelStateSerializationDelegate::instance()->isChecked(current); wasChecked = current->isEnabled(); if (check && !wasChecked) @@ -284,12 +260,12 @@ bool CollectionModel::load() return false; } -///Return the backend at a given index -CollectionInterface* CollectionModel::backendAt(const QModelIndex& index) +///Return the collection at a given index +CollectionInterface* CollectionModel::collectionAt(const QModelIndex& index) { if (!index.isValid()) return nullptr; - return static_cast<CollectionModelPrivate::ProxyItem*>(index.internalPointer())->backend; + return static_cast<CollectionModelPrivate::ProxyItem*>(index.internalPointer())->collection; } void CollectionModel::addExtension(CollectionExtensionInterface* extension) @@ -305,4 +281,34 @@ void CollectionModelPrivate::slotExtensionDataChanged(const QModelIndex& idx) emit q_ptr->dataChanged(idx,idx); } +void CollectionModelPrivate::registerNew(CollectionInterface* col) +{ + if (!col) + return; + + ProxyItem* item = new ProxyItem(); + if (col->parent()) { + ProxyItem* p = m_hBackendsNodes[col->parent()]; + item->parent = p; + item->row = p->m_Children.size(); + item->col = 0; + q_ptr->beginInsertRows(q_ptr->createIndex(p->row,p->col,p),p->m_Children.size(),p->m_Children.size()); + p->m_Children << item; + q_ptr->endInsertRows(); + } + else { + item->parent = nullptr; + item->row = m_lTopLevelBackends.size(); + item->col = 0; + + q_ptr->beginInsertRows(QModelIndex(),m_lTopLevelBackends.size(),m_lTopLevelBackends.size()); + m_lTopLevelBackends << item; + q_ptr->endInsertRows(); + } + + + item->collection = col ; + m_hBackendsNodes[col] = item; +} + #include <collectionmodel.moc> diff --git a/src/collectionmodel.h b/src/collectionmodel.h index aaec2659..3710ee63 100644 --- a/src/collectionmodel.h +++ b/src/collectionmodel.h @@ -31,10 +31,14 @@ class CollectionExtensionInterface; class CollectionModelPrivate; +class CollectionManagerInterfaceBase; class LIB_EXPORT CollectionModel : public QAbstractTableModel { Q_OBJECT + + friend class CollectionManagerInterfaceBase; + public: explicit CollectionModel(QObject* parent = nullptr); virtual ~CollectionModel(); @@ -49,13 +53,15 @@ public: virtual QModelIndex index ( int row, int column, const QModelIndex& parent=QModelIndex()) const override; virtual QHash<int,QByteArray> roleNames() const override; - CollectionInterface* backendAt(const QModelIndex& index); + CollectionInterface* collectionAt(const QModelIndex& index); void addExtension(CollectionExtensionInterface* extension); bool save(); bool load(); + static CollectionModel* instance(); + Q_SIGNALS: void checkStateChanged(); diff --git a/src/private/collectionmodel_p.h b/src/private/collectionmodel_p.h new file mode 100644 index 00000000..5dff0d4d --- /dev/null +++ b/src/private/collectionmodel_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * Copyright (C) 2014-2015 by Savoir-Faire Linux * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#ifndef COLLECTIONMODELPRIVATE_H +#define COLLECTIONMODELPRIVATE_H + +#include <QtCore/QObject> +#include <QtCore/QVector> +#include <QtCore/QHash> + +class CollectionInterface; +class CollectionModel; +class CollectionExtensionInterface; + +class CollectionModelPrivate : public QObject +{ + Q_OBJECT +public: + CollectionModelPrivate(CollectionModel* parent); + + /* + * This is not very efficient, it doesn't really have to be given the low + * volume. If it ever have to scale, a better mapToSource using persistent + * index have to be implemented. + */ + struct ProxyItem { + ProxyItem() : parent(nullptr),col(1),row(0),collection(nullptr){} + int row; + int col; + CollectionInterface* collection; + ProxyItem* parent; + QVector<ProxyItem*> m_Children; + }; + + QHash<CollectionInterface*,ProxyItem*> m_hBackendsNodes; + QVector<ProxyItem*> m_lTopLevelBackends; + QVector<CollectionExtensionInterface*> m_lExtensions; + static CollectionModel* m_spInstance; + + //Helper + void registerNew(CollectionInterface* col); + +private: + CollectionModel* q_ptr; + +private Q_SLOTS: + void slotUpdate(); + void slotExtensionDataChanged(const QModelIndex& idx); +}; + +#endif \ No newline at end of file -- GitLab