on 2e1beb4 help sign in
unity8/modules/Unity/Indicators/indicatorsmodel.cpp
310 lines 8.0 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 "indicator.h"
23#include "paths.h"
25#include <QQmlContext>
26#include <QQmlEngine>
27#include <QDebug>
29/*!
30 \qmltype IndicatorsModel
31 \inherits QAbstractListModel
33 \brief The IndicatorsModel class defines the list model for indicators plugins
35 \b {This component is under heavy development.}
37 This class expose the available indicators.
39 \code
40 IndicatorsModel {
41 id: menuModel
42 }
44 ListView {
45 id: view
46 model: menuModel
47 Component.onCompleted: menuModel.load()
48 }
49 \endcode
50*/
51IndicatorsModel::IndicatorsModel(QObject *parent)
52 : QAbstractListModel(parent)
54 m_manager = new IndicatorsManager(this);
55 QObject::connect(m_manager, SIGNAL(indicatorLoaded(const QString&)), this, SLOT(onIndicatorLoaded(const QString&)));
56 QObject::connect(m_manager, SIGNAL(indicatorAboutToBeUnloaded(const QString&)), this, SLOT(onIndicatorAboutToBeUnloaded(const QString&)));
58 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
59 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
60 QObject::connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
63/*! \internal */
64IndicatorsModel::~IndicatorsModel()
66 disconnect(m_manager, 0, 0, 0);
67 m_manager->deleteLater();
70/*!
71 \qmlproperty IndicatorsModel::count
72 The number of data entries in the model.
74 \b Note: methods should only be called after the Component has completed.
75*/
76int IndicatorsModel::count() const
78 return rowCount();
81/*!
82 \qmlmethod IndicatorsModel::unload()
84 Load all plugins.
85*/
86void IndicatorsModel::load()
88 m_plugins.clear();
89 m_manager->load();
92/*!
93 \qmlmethod IndicatorsModel::unload()
95 Unload all plugins.
96*/
97void IndicatorsModel::unload()
99 m_manager->unload();
102/*! \internal */
103void IndicatorsModel::onIndicatorLoaded(const QString& indicator)
105 Indicator::Ptr plugin = m_manager->indicator(indicator);
106 if (!plugin)
107 return;
109 if (m_plugins.indexOf(plugin) >= 0)
110 return;
112 // find the insert position
113 int pos = 0;
114 while (pos < count()) {
115 // keep going while the existing priority is less.
116 if (indicatorData(plugin, Priority).toInt() < data(index(pos), Priority).toInt())
117 break;
118 pos++;
119 }
121 QObject::connect(plugin.data(), SIGNAL(identifierChanged(const QString&)), this, SLOT(onIdentifierChanged()));
122 QObject::connect(plugin.data(), SIGNAL(indicatorPropertiesChanged(const QVariant&)), this, SLOT(onIndicatorPropertiesChanged()));
124 beginInsertRows(QModelIndex(), pos, pos);
126 m_plugins.insert(pos, plugin);
127 endInsertRows();
130/*! \internal */
131void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator)
133 Indicator::Ptr plugin = m_manager->indicator(indicator);
134 if (!plugin)
135 return;
137 int i = 0;
138 QMutableListIterator<Indicator::Ptr> iter(m_plugins);
139 while(iter.hasNext())
140 {
141 if (plugin == iter.next())
142 {
143 beginRemoveRows(QModelIndex(), i, i);
144 iter.remove();
145 endRemoveRows();
146 }
147 i++;
148 }
152/*! \internal */
153void IndicatorsModel::onIdentifierChanged()
155 notifyDataChanged(QObject::sender(), Identifier);
158/*! \internal */
159void IndicatorsModel::onIndicatorPropertiesChanged()
161 notifyDataChanged(QObject::sender(), IndicatorProperties);
164/*! \internal */
165void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
167 Indicator* plugin = qobject_cast<Indicator*>(sender);
168 if (!plugin)
169 return;
171 int index = 0;
172 QMutableListIterator<Indicator::Ptr> iter(m_plugins);
173 while(iter.hasNext())
174 {
175 if (iter.next().data() == plugin)
176 {
177 QModelIndex changedIndex = this->index(index);
178 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
179 break;
180 }
181 index++;
182 }
185/*! \internal */
186QHash<int, QByteArray> IndicatorsModel::roleNames() const
188 static QHash<int, QByteArray> roles;
189 if (roles.isEmpty())
190 {
191 roles[Identifier] = "identifier";
192 roles[Priority] = "priority";
193 roles[Title] = "title";
194 roles[Description] = "description";
195 roles[WidgetSource] = "widgetSource";
196 roles[PageSource] = "pageSource";
197 roles[IndicatorProperties] = "indicatorProperties";
198 roles[IsValid] = "isValid";
199 }
200 return roles;
203/*! \internal */
204int IndicatorsModel::columnCount(const QModelIndex &) const
206 return 1;
209/*! \internal */
210QVariant IndicatorsModel::defaultData(Indicator::Ptr plugin, int role)
212 switch (role)
213 {
214 case Priority:
215 return 0;
216 case Title:
217 return plugin ? plugin->identifier() : "Unknown";
218 case Description:
219 return "";
220 case WidgetSource:
221 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorWidget.qml";
222 case PageSource:
223 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorPage.qml";
224 }
225 return QVariant();
228Q_INVOKABLE QVariant IndicatorsModel::data(int row, int role) const
230 return data(index(row, 0), role);
233/*! \internal */
234QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
236 if (!index.isValid() || index.row() >= m_plugins.size())
237 return QVariant();
239 Indicator::Ptr plugin = m_plugins[index.row()];
241 switch (role)
242 {
243 case Identifier:
244 if (plugin)
245 {
246 return QVariant(plugin->identifier());
247 }
248 break;
249 case IndicatorProperties:
250 if (plugin)
251 {
252 return QVariant(plugin->indicatorProperties());
253 }
254 break;
255 case IsValid:
256 return (plugin ? true : false);
257 case Priority:
258 case Title:
259 case Description:
260 case WidgetSource:
261 case PageSource:
262 return indicatorData(plugin, role);
263 default:
264 break;
265 }
266 return QVariant();
269QVariant IndicatorsModel::indicatorData(const Indicator::Ptr& plugin, int role) const
271 if (plugin && m_parsed_indicator_data.contains(plugin->identifier()))
272 {
273 QVariantMap data = m_parsed_indicator_data[plugin->identifier()];
274 return data.value(roleNames()[role], QVariant());
275 }
276 return defaultData(plugin, role);
279/*! \internal */
280QModelIndex IndicatorsModel::parent(const QModelIndex&) const
282 return QModelIndex();
285/*! \internal */
286int IndicatorsModel::rowCount(const QModelIndex&) const
288 return m_plugins.count();
291void IndicatorsModel::setIndicatorData(const QVariant& data)
293 m_indicator_data = data;
295 m_parsed_indicator_data.clear();
296 QMap<QString, QVariant> map = data.toMap();
297 QMapIterator<QString, QVariant> iter(map);
298 while(iter.hasNext())
299 {
300 iter.next();
301 m_parsed_indicator_data[iter.key()] = iter.value().toMap();
302 }
304 Q_EMIT indicatorDataChanged(m_indicator_data);
307QVariant IndicatorsModel::indicatorData() const
309 return m_indicator_data;