Skip to content
Snippets Groups Projects
Commit 1b178b25 authored by Emmanuel Lepage Vallee's avatar Emmanuel Lepage Vallee
Browse files

collection: Port the collection model to the new API

Refs #68098
parent 6c3b5b9a
No related branches found
No related tags found
No related merge requests found
......@@ -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)
......
/****************************************************************************
* 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
......@@ -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:
......
......@@ -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
......
......@@ -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>
......@@ -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();
......
......@@ -15,91 +15,51 @@
* 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
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;
#include <QtCore/QObject>
#include <QtCore/QVector>
#include <QtCore/QHash>
if (options & LoadOptions::FORCE_ENABLED) { //TODO check is the backend is checked
class CollectionInterface;
class CollectionModel;
class CollectionExtensionInterface;
//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))
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;
template<class T>
const QVector< CollectionInterface* > BackendManagerInterface<T>::collections() const
{
return d_ptr->m_lBackends;
}
//Helper
void registerNew(CollectionInterface* col);
template<class T>
const QVector< CollectionInterface* > BackendManagerInterface<T>::enabledCollections() const
{
return d_ptr->m_lEnabledBackends;
}
private:
CollectionModel* q_ptr;
/// 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();
}
private Q_SLOTS:
void slotUpdate();
void slotExtensionDataChanged(const QModelIndex& idx);
};
template<class T>
bool BackendManagerInterface<T>::clearAllCollections() const
{
return false;
}
#endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment