1 /***************************************************************************
2  *   Copyright (C) 2004-2018 by Thomas Fischer <fischer@unix-ag.uni-kl.de> *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
16  ***************************************************************************/
17 
18 #include "collectionmodel.h"
19 
20 #include <QHash>
21 
22 #include <QIcon>
23 
24 #include "zotero/collection.h"
25 
26 using namespace Zotero;
27 
28 const int Zotero::CollectionModel::CollectionIdRole = Qt::UserRole + 6681;
29 
30 class Zotero::CollectionModel::Private
31 {
32 public:
Private(Collection * c,Zotero::CollectionModel * parent)33     Private(Collection *c, Zotero::CollectionModel *parent)
34             : collection(c) {
35         Q_UNUSED(parent)
36     }
37 
38     Collection *collection;
39 
40     QHash<QString, QModelIndex> collectionIdToModelIndex;
41 };
42 
CollectionModel(Collection * collection,QObject * parent)43 CollectionModel::CollectionModel(Collection *collection, QObject *parent)
44         : QAbstractItemModel(parent), d(new Zotero::CollectionModel::Private(collection, this))
45 {
46     beginResetModel();
47     connect(collection, &Collection::finishedLoading, this, &CollectionModel::fetchingDone);
48 }
49 
data(const QModelIndex & index,int role) const50 QVariant CollectionModel::data(const QModelIndex &index, int role) const
51 {
52     if (!d->collection->initialized())
53         return QVariant();
54 
55     if (index == QModelIndex())
56         return QVariant();
57 
58     if (role == Qt::DecorationRole) {
59         /// Fancy icons for collections
60         if (index.internalId() == 0) /// root node
61             return QIcon::fromTheme(QStringLiteral("folder-orange"));
62         else /// any other node
63             return QIcon::fromTheme(QStringLiteral("folder-yellow"));
64     } else if (role == Qt::DisplayRole) {
65         /// Show collections' human-readable description
66         const QString collectionId = d->collection->collectionFromNumericId(index.internalId());
67         return d->collection->collectionLabel(collectionId);
68     } else if (role == CollectionIdRole) {
69         if (index.internalId() == 0) /// root node
70             return QString();
71         else /// any other node
72             return d->collection->collectionFromNumericId(index.internalId());
73     }
74 
75     return QVariant();
76 }
77 
index(int row,int column,const QModelIndex & parent) const78 QModelIndex CollectionModel::index(int row, int column, const QModelIndex &parent) const
79 {
80     if (!d->collection->initialized())
81         return QModelIndex();
82 
83     if (parent == QModelIndex()) { ///< root node
84         const QModelIndex result = createIndex(row, column, (quintptr)0);
85         d->collectionIdToModelIndex.insert(d->collection->collectionFromNumericId(0), result);
86         return result;
87     }
88 
89     const QString collectionId = d->collection->collectionFromNumericId(parent.internalId());
90     QVector<QString> children = d->collection->collectionChildren(collectionId);
91     if (row < children.count()) {
92         const QModelIndex result = createIndex(row, column, d->collection->collectionNumericId(children[row]));
93         d->collectionIdToModelIndex.insert(children[row], result);
94         return result;
95     }
96 
97     return QModelIndex();
98 }
99 
parent(const QModelIndex & index) const100 QModelIndex CollectionModel::parent(const QModelIndex &index) const
101 {
102     if (!d->collection->initialized())
103         return QModelIndex();
104 
105     if (index == QModelIndex() || index.internalId() == 0)
106         return QModelIndex(); ///< invalid index or root node
107 
108     const QString parentId = d->collection->collectionParent(d->collection->collectionFromNumericId(index.internalId()));
109     return d->collectionIdToModelIndex[parentId];
110 }
111 
rowCount(const QModelIndex & parent) const112 int CollectionModel::rowCount(const QModelIndex &parent) const
113 {
114     if (!d->collection->initialized())
115         return 0;
116 
117     if (parent == QModelIndex())
118         return 1; ///< just one single root node
119 
120     const QString collectionId = d->collection->collectionFromNumericId(parent.internalId());
121     QVector<QString> children = d->collection->collectionChildren(collectionId);
122     return children.count();
123 }
124 
columnCount(const QModelIndex &) const125 int CollectionModel::columnCount(const QModelIndex &) const
126 {
127     /// Singe column design;
128     return 1;
129 }
130 
hasChildren(const QModelIndex & parent) const131 bool CollectionModel::hasChildren(const QModelIndex &parent) const
132 {
133     if (!d->collection->initialized())
134         return false;
135 
136     return rowCount(parent) > 0;
137 }
138 
fetchingDone()139 void CollectionModel::fetchingDone()
140 {
141     endResetModel();
142 }
143