on fa85355 help sign in
unity8/plugins/IndicatorsClient/indicatorsmodel.cpp
313 lines 8.1 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(iconChanged(const QUrl&)), this, SLOT(onIconChanged()));
145 QObject::connect(obj, SIGNAL(titleChanged(const QString&)), this, SLOT(onTitleChanged()));
146 QObject::connect(obj, SIGNAL(labelChanged(const QString&)), this, SLOT(onLabelChanged()));
147 }
149 m_plugins.insert(i, plugin);
151 endInsertRows();
154/*! \internal */
155void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator)
157 IndicatorClientInterface::Ptr plugin = m_manager->indicator(indicator);
158 if (!plugin)
159 return;
161 int i = 0;
162 QMutableListIterator<IndicatorClientInterface::Ptr> iter(m_plugins);
163 while(iter.hasNext())
164 {
165 if (plugin == iter.next())
166 {
167 beginRemoveRows(QModelIndex(), i, i);
168 iter.remove();
169 endRemoveRows();
170 }
171 i++;
172 }
176/*! \internal */
177void IndicatorsModel::onIdentifierChanged()
179 notifyDataChanged(QObject::sender(), Identifier);
182/*! \internal */
183void IndicatorsModel::onIconChanged()
185 notifyDataChanged(QObject::sender(), IconSource);
188/*! \internal */
189void IndicatorsModel::onTitleChanged()
191 notifyDataChanged(QObject::sender(), Title);
194/*! \internal */
195void IndicatorsModel::onLabelChanged()
197 notifyDataChanged(QObject::sender(), Label);
200/*! \internal */
201void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
203 IndicatorClientInterface* plugin = dynamic_cast<IndicatorClientInterface*>(sender);
204 if (!plugin)
205 return;
207 int index = 0;
208 QMutableListIterator<IndicatorClientInterface::Ptr> iter(m_plugins);
209 while(iter.hasNext())
210 {
211 if (iter.next().get() == plugin)
212 {
213 QModelIndex changedIndex = this->index(index);
214 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
215 break;
216 }
217 index++;
218 }
221/*! \internal */
222QHash<int, QByteArray> IndicatorsModel::roleNames() const
224 static QHash<int, QByteArray> roles;
225 if (roles.isEmpty()) {
226 roles[Identifier] = "identifier";
227 roles[Title] = "title";
228 roles[IconSource] = "iconSource";
229 roles[Label] = "label";
230 roles[Description] = "description";
231 roles[QMLComponent] = "component";
232 roles[InitialProperties] = "initialProperties";
233 roles[IsValid] = "isValid";
234 }
235 return roles;
238/*! \internal */
239int IndicatorsModel::columnCount(const QModelIndex &) const
241 return 1;
244/*! \internal */
245QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
247 if (!index.isValid() || index.row() >= m_plugins.size())
248 return QVariant();
250 QVariant attribute;
252 IndicatorClientInterface::Ptr plugin = m_plugins[index.row()];
254 switch (role) {
255 case Identifier:
256 if (plugin) {
257 attribute = QVariant(plugin->identifier());
258 }
259 break;
260 case Title:
261 if (plugin) {
262 attribute = QVariant(plugin->title());
263 }
264 break;
265 case IconSource:
266 if (plugin) {
267 return plugin->icon().toString();
268 } else {
269 attribute = QVariant("No plugin");
270 }
271 break;
272 case Label:
273 if (plugin) {
274 attribute = QVariant(plugin->label());
275 }
276 break;
277 case Description:
278 {
279 if (plugin) {
280 attribute = QVariant(plugin->description());
281 }
282 break;
283 }
284 case QMLComponent:
285 if (plugin) {
286 return plugin->componentSource();
287 }
288 break;
289 case InitialProperties:
290 if (plugin) {
291 attribute = plugin->initialProperties();
292 }
293 break;
294 case IsValid:
295 attribute = QVariant(plugin != 0);
296 break;
297 default:
298 break;
299 }
300 return attribute;
303/*! \internal */
304QModelIndex IndicatorsModel::parent(const QModelIndex&) const
306 return QModelIndex();
309/*! \internal */
310int IndicatorsModel::rowCount(const QModelIndex&) const
312 return m_plugins.count();