on e2b019b help sign in
unity8/plugins/IndicatorsClient/indicatorsmodel.cpp
306 lines 7.9 kB history raw
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Renato Araujo Oliveira Filho <renato@canonical.com>
18 */
20#include "indicatorsmodel.h"
21#include "indicatorsmanager.h"
22#include "indicatorclientinterface.h"
24#include <QQmlContext>
25#include <QQmlEngine>
26#include <QDebug>
29static bool comparePlugins(const IndicatorClientInterface::Ptr obj1, const IndicatorClientInterface::Ptr obj2)
31 return obj1->priority() < obj2->priority();
34/*!
35 \qmltype IndicatorsModel
36 \inherits QAbstractListModel
38 \brief The IndicatorsModel class defines the list model for indicators plugins
40 \b {This component is under heavy development.}
42 This class expose the available indicators.
44 \code
45 IndicatorsModel {
46 id: menuModel
47 }
49 ListView {
50 id: view
51 model: menuModel
52 Component.onCompleted: menuModel.load()
53 }
54 \endcode
55*/
56IndicatorsModel::IndicatorsModel(QObject *parent)
57 : QAbstractListModel(parent)
59 m_manager = new IndicatorsManager(this);
60 QObject::connect(m_manager, SIGNAL(indicatorLoaded(const QString&)), this, SLOT(onIndicatorLoaded(const QString&)));
61 QObject::connect(m_manager, SIGNAL(indicatorAboutToBeUnloaded(const QString&)), this, SLOT(onIndicatorAboutToBeUnloaded(const QString&)));
63 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
64 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
65 QObject::connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
68/*! \internal */
69IndicatorsModel::~IndicatorsModel()
71 disconnect(m_manager, 0, 0, 0);
72 m_manager->deleteLater();
75/*!
76 \qmlmethod IndicatorsModel::get(int)
78 Returns the item at index in the model. This allows the item data to be accessed from JavaScript:
79 \b Note: methods should only be called after the Component has completed.
80*/
81QVariantMap IndicatorsModel::get(int row) const
83 QVariantMap result;
85 QModelIndex index = this->index(row);
86 if (index.isValid()) {
87 QMap<int, QVariant> data = itemData(index);
88 const QHash<int, QByteArray> roleNames = this->roleNames();
89 Q_FOREACH(int i, roleNames.keys()) {
90 result.insert(roleNames[i], data[i]);
91 }
92 }
93 return result;
96/*!
97 \qmlproperty IndicatorsModel::count
98 The number of data entries in the model.
100 \b Note: methods should only be called after the Component has completed.
101*/
102int IndicatorsModel::count() const
104 return rowCount();
107/*!
108 \qmlmethod IndicatorsModel::unload()
110 Load all plugins.
111*/
112void IndicatorsModel::load()
114 m_plugins.clear();
115 m_manager->load();
118/*!
119 \qmlmethod IndicatorsModel::unload()
121 Unload all plugins.
122*/
123void IndicatorsModel::unload()
125 m_manager->unload();
128/*! \internal */
129void IndicatorsModel::onIndicatorLoaded(const QString& indicator)
131 IndicatorClientInterface::Ptr plugin = m_manager->indicator(indicator);
132 if (!plugin)
133 return;
135 QList<IndicatorClientInterface::Ptr>::iterator i = qLowerBound(m_plugins.begin(), m_plugins.end(), plugin, comparePlugins);
136 int insert_pos = qMin(i - m_plugins.begin(), m_plugins.count());
138 beginInsertRows(QModelIndex(), insert_pos, insert_pos);
140 QObject* obj = dynamic_cast<QObject*>(plugin.get());
141 if (obj)
142 {
143 QObject::connect(obj, SIGNAL(identifierChanged(const QString&)), this, SLOT(onIdentifierChanged()));
144 QObject::connect(obj, SIGNAL(titleChanged(const QString&)), this, SLOT(onTitleChanged()));
145 QObject::connect(obj, SIGNAL(labelChanged(const QString&)), this, SLOT(onLabelChanged()));
146 }
148 m_plugins.insert(i, plugin);
150 endInsertRows();
153/*! \internal */
154void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator)
156 IndicatorClientInterface::Ptr plugin = m_manager->indicator(indicator);
157 if (!plugin)
158 return;
160 int i = 0;
161 QMutableListIterator<IndicatorClientInterface::Ptr> iter(m_plugins);
162 while(iter.hasNext())
163 {
164 if (plugin == iter.next())
165 {
166 beginRemoveRows(QModelIndex(), i, i);
167 iter.remove();
168 endRemoveRows();
169 }
170 i++;
171 }
175/*! \internal */
176void IndicatorsModel::onIdentifierChanged()
178 notifyDataChanged(QObject::sender(), Identifier);
181/*! \internal */
182void IndicatorsModel::onTitleChanged()
184 notifyDataChanged(QObject::sender(), Title);
187/*! \internal */
188void IndicatorsModel::onLabelChanged()
190 notifyDataChanged(QObject::sender(), Label);
193/*! \internal */
194void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
196 IndicatorClientInterface* plugin = dynamic_cast<IndicatorClientInterface*>(sender);
197 if (!plugin)
198 return;
200 int index = 0;
201 QMutableListIterator<IndicatorClientInterface::Ptr> iter(m_plugins);
202 while(iter.hasNext())
203 {
204 if (iter.next().get() == plugin)
205 {
206 QModelIndex changedIndex = this->index(index);
207 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
208 break;
209 }
210 index++;
211 }
214/*! \internal */
215QHash<int, QByteArray> IndicatorsModel::roleNames() const
217 static QHash<int, QByteArray> roles;
218 if (roles.isEmpty()) {
219 roles[Identifier] = "identifier";
220 roles[Title] = "title";
221 roles[Label] = "label";
222 roles[Description] = "description";
223 roles[IconUrl] = "iconUrl";
224 roles[PageUrl] = "pageUrl";
225 roles[InitialProperties] = "initialProperties";
226 roles[IsValid] = "isValid";
227 }
228 return roles;
231/*! \internal */
232int IndicatorsModel::columnCount(const QModelIndex &) const
234 return 1;
237/*! \internal */
238QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
240 if (!index.isValid() || index.row() >= m_plugins.size())
241 return QVariant();
243 QVariant attribute;
245 IndicatorClientInterface::Ptr plugin = m_plugins[index.row()];
247 switch (role) {
248 case Identifier:
249 if (plugin) {
250 attribute = QVariant(plugin->identifier());
251 }
252 break;
253 case Title:
254 if (plugin) {
255 attribute = QVariant(plugin->title());
256 }
257 break;
258 case Label:
259 if (plugin) {
260 attribute = QVariant(plugin->label());
261 }
262 break;
263 case Description:
264 {
265 if (plugin) {
266 attribute = QVariant(plugin->description());
267 }
268 break;
269 }
270 case IconUrl:
271 if (plugin) {
272 return plugin->iconComponentSource().toString();
273 } else {
274 attribute = QVariant("No plugin");
275 }
276 break;
277 case PageUrl:
278 if (plugin) {
279 return plugin->pageComponentSource();
280 }
281 break;
282 case InitialProperties:
283 if (plugin) {
284 attribute = plugin->initialProperties();
285 }
286 break;
287 case IsValid:
288 attribute = QVariant(plugin != 0);
289 break;
290 default:
291 break;
292 }
293 return attribute;
296/*! \internal */
297QModelIndex IndicatorsModel::parent(const QModelIndex&) const
299 return QModelIndex();
302/*! \internal */
303int IndicatorsModel::rowCount(const QModelIndex&) const
305 return m_plugins.count();