on 2ecb97b help sign in
unity8/plugins/IndicatorsClient/indicatorsmodel.cpp
334 lines 8.8 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 "widgetsmap.h"
23#include "indicatorclientinterface.h"
25#include <QQmlContext>
26#include <QQmlEngine>
27#include <QDebug>
30static bool comparePlugins(const IndicatorClientInterface::Ptr obj1, const IndicatorClientInterface::Ptr obj2)
32 return obj1->priority() < obj2->priority();
35/*!
36 \qmltype IndicatorsModel
37 \inherits QAbstractListModel
39 \brief The IndicatorsModel class defines the list model for indicators plugins
41 \b {This component is under heavy development.}
43 This class expose the available indicators.
45 \code
46 IndicatorsModel {
47 id: menuModel
48 }
50 ListView {
51 id: view
52 model: menuModel
53 Component.onCompleted: menuModel.load()
54 }
55 \endcode
56*/
57IndicatorsModel::IndicatorsModel(QObject *parent)
58 : QAbstractListModel(parent)
60 m_manager = new IndicatorsManager(this);
61 QObject::connect(m_manager, SIGNAL(loaded(const QString&)), this, SLOT(onIndicatorLoaded(const QString&)));
62 QObject::connect(m_manager, SIGNAL(aboutToBeUnloaded(const QString&)), this, SLOT(onIndicatorAboutToBeUnloaded(const QString&)));
63 m_widgetsMap = new WidgetsMap;
65 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
66 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
67 QObject::connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
70/*! \internal */
71IndicatorsModel::~IndicatorsModel()
73 disconnect(m_manager, 0, 0, 0);
74 m_manager->deleteLater();
75 m_widgetsMap->deleteLater();
78/*!
79 \qmlmethod IndicatorsModel::get(int)
81 Returns the item at index in the model. This allows the item data to be accessed from JavaScript:
82 \b Note: methods should only be called after the Component has completed.
83*/
84QVariantMap IndicatorsModel::get(int row) const
86 QVariantMap result;
88 QModelIndex index = this->index(row);
89 if (index.isValid()) {
90 QMap<int, QVariant> data = itemData(index);
91 const QHash<int, QByteArray> roleNames = this->roleNames();
92 Q_FOREACH(int i, roleNames.keys()) {
93 result.insert(roleNames[i], data[i]);
94 }
95 }
96 return result;
99/*!
100 \qmlproperty IndicatorsModel::count
101 The number of data entries in the model.
103 \b Note: methods should only be called after the Component has completed.
104*/
105int IndicatorsModel::count() const
107 return rowCount();
110/*!
111 \qmlproperty WidgetsMap IndicatorsModel::widgetsMap
112 This property holds the map for all new widgets registered by dynamically loaded plugins.
113*/
114WidgetsMap* IndicatorsModel::widgetsMap() const
116 return m_widgetsMap;
119/*!
120 \qmlmethod IndicatorsModel::unload()
122 Load all plugins.
123*/
124void IndicatorsModel::load()
126 m_widgetsMap->clear();
127 m_plugins.clear();
128 m_manager->load();
131/*!
132 \qmlmethod IndicatorsModel::unload()
134 Unload all plugins.
135*/
136void IndicatorsModel::unload()
138 m_widgetsMap->clear();
139 m_manager->unload();
142/*! \internal */
143void IndicatorsModel::onIndicatorLoaded(const QString& indicator)
145 IndicatorClientInterface::Ptr plugin = m_manager->indicator(indicator);
146 if (!plugin)
147 return;
149 QList<IndicatorClientInterface::Ptr>::iterator i = qLowerBound(m_plugins.begin(), m_plugins.end(), plugin, comparePlugins);
150 int insert_pos = qMin(i - m_plugins.begin(), m_plugins.count());
152 beginInsertRows(QModelIndex(), insert_pos, insert_pos);
154 m_widgetsMap->append(plugin->widgets());
156 QObject* obj = dynamic_cast<QObject*>(plugin.get());
157 if (obj)
158 {
159 QObject::connect(obj, SIGNAL(idChanged(const QString&)), this, SLOT(onIdChanged()));
160 QObject::connect(obj, SIGNAL(iconChanged(const QUrl&)), this, SLOT(onIconChanged()));
161 QObject::connect(obj, SIGNAL(titleChanged(const QString&)), this, SLOT(onTitleChanged()));
162 QObject::connect(obj, SIGNAL(labelChanged(const QString&)), this, SLOT(onLabelChanged()));
163 }
165 m_plugins.insert(i, plugin);
167 endInsertRows();
169 Q_EMIT widgetsMapChanged(m_widgetsMap);
172/*! \internal */
173void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator)
175 IndicatorClientInterface::Ptr plugin = m_manager->indicator(indicator);
176 if (!plugin)
177 return;
179 int i = 0;
180 QMutableListIterator<IndicatorClientInterface::Ptr> iter(m_plugins);
181 while(iter.hasNext())
182 {
183 if (plugin == iter.next())
184 {
185 beginRemoveRows(QModelIndex(), i, i);
186 iter.remove();
187 endRemoveRows();
188 }
189 i++;
190 }
194/*! \internal */
195void IndicatorsModel::onIdChanged()
197 notifyDataChanged(QObject::sender(), Identifier);
200/*! \internal */
201void IndicatorsModel::onIconChanged()
203 notifyDataChanged(QObject::sender(), IconSource);
206/*! \internal */
207void IndicatorsModel::onTitleChanged()
209 notifyDataChanged(QObject::sender(), Title);
212/*! \internal */
213void IndicatorsModel::onLabelChanged()
215 notifyDataChanged(QObject::sender(), Label);
218/*! \internal */
219void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
221 IndicatorClientInterface* plugin = dynamic_cast<IndicatorClientInterface*>(sender);
222 if (!plugin)
223 return;
225 int index = 0;
226 QMutableListIterator<IndicatorClientInterface::Ptr> iter(m_plugins);
227 while(iter.hasNext())
228 {
229 if (iter.next().get() == plugin)
230 {
231 QModelIndex changedIndex = this->index(index);
232 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
233 break;
234 }
235 index++;
236 }
239/*! \internal */
240QHash<int, QByteArray> IndicatorsModel::roleNames() const
242 static QHash<int, QByteArray> roles;
243 if (roles.isEmpty()) {
244 roles[Identifier] = "identifier";
245 roles[Title] = "title";
246 roles[IconSource] = "iconSource";
247 roles[Label] = "label";
248 roles[Description] = "description";
249 roles[QMLComponent] = "component";
250 roles[InitialProperties] = "initialProperties";
251 roles[IsValid] = "isValid";
252 }
253 return roles;
256/*! \internal */
257int IndicatorsModel::columnCount(const QModelIndex &) const
259 return 1;
262/*! \internal */
263QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
265 if (!index.isValid() || index.row() >= m_plugins.size())
266 return QVariant();
268 QVariant attribute;
270 IndicatorClientInterface::Ptr plugin = m_plugins[index.row()];
272 switch (role) {
273 case Identifier:
274 if (plugin) {
275 attribute = QVariant(plugin->identifier());
276 }
277 break;
278 case Title:
279 if (plugin) {
280 attribute = QVariant(plugin->title());
281 }
282 break;
283 case IconSource:
284 if (plugin) {
285 return plugin->icon().toString();
286 } else {
287 attribute = QVariant("No plugin");
288 }
289 break;
290 case Label:
291 if (plugin) {
292 attribute = QVariant(plugin->label());
293 }
294 break;
295 case Description:
296 {
297 if (plugin) {
298 attribute = QVariant(plugin->description());
299 }
300 break;
301 }
302 case QMLComponent:
303 if (plugin) {
304 QQmlContext *context = QQmlEngine::contextForObject(this);
305 if (context) {
306 attribute = QVariant::fromValue<QQmlComponent*>(plugin->component(context->parentContext()->engine()));
307 }
308 }
309 break;
310 case InitialProperties:
311 if (plugin) {
312 attribute = plugin->initialProperties();
313 }
314 break;
315 case IsValid:
316 attribute = QVariant(plugin != 0);
317 break;
318 default:
319 break;
320 }
321 return attribute;
324/*! \internal */
325QModelIndex IndicatorsModel::parent(const QModelIndex&) const
327 return QModelIndex();
330/*! \internal */
331int IndicatorsModel::rowCount(const QModelIndex&) const
333 return m_plugins.count();