on 574bbde help sign in
unity8/modules/Unity/Indicators/indicatorsmodel.cpp
326 lines 8.5 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 \qmlmethod IndicatorsModel::get(int)
73 Returns the item at index in the model. This allows the item data to be accessed from JavaScript:
74 \b Note: methods should only be called after the Component has completed.
75*/
76QVariantMap IndicatorsModel::get(int row) const
78 QVariantMap result;
80 QModelIndex index = this->index(row);
81 if (index.isValid()) {
82 QMap<int, QVariant> data = itemData(index);
83 const QHash<int, QByteArray> roleNames = this->roleNames();
84 Q_FOREACH(int i, roleNames.keys()) {
85 result.insert(roleNames[i], data[i]);
86 }
87 }
88 return result;
91/*!
92 \qmlproperty IndicatorsModel::count
93 The number of data entries in the model.
95 \b Note: methods should only be called after the Component has completed.
96*/
97int IndicatorsModel::count() const
99 return rowCount();
102/*!
103 \qmlmethod IndicatorsModel::unload()
105 Load all plugins.
106*/
107void IndicatorsModel::load()
109 m_plugins.clear();
110 m_manager->load();
113/*!
114 \qmlmethod IndicatorsModel::unload()
116 Unload all plugins.
117*/
118void IndicatorsModel::unload()
120 m_manager->unload();
123/*! \internal */
124void IndicatorsModel::onIndicatorLoaded(const QString& indicator)
126 Indicator::Ptr plugin = m_manager->indicator(indicator);
127 if (!plugin)
128 return;
130 if (m_plugins.indexOf(plugin) >= 0)
131 return;
133 // find the insert position
134 int pos = 0;
135 while (pos < count()) {
136 // keep going while the existing priority is less.
137 if (indicatorData(plugin, Priority).toInt() < data(index(pos), Priority).toInt())
138 break;
139 pos++;
140 }
142 QObject::connect(plugin.data(), SIGNAL(identifierChanged(const QString&)), this, SLOT(onIdentifierChanged()));
143 QObject::connect(plugin.data(), SIGNAL(indicatorPropertiesChanged(const QVariant&)), this, SLOT(onIndicatorPropertiesChanged()));
145 beginInsertRows(QModelIndex(), pos, pos);
147 m_plugins.insert(pos, plugin);
148 endInsertRows();
151/*! \internal */
152void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator)
154 Indicator::Ptr plugin = m_manager->indicator(indicator);
155 if (!plugin)
156 return;
158 int i = 0;
159 QMutableListIterator<Indicator::Ptr> iter(m_plugins);
160 while(iter.hasNext())
161 {
162 if (plugin == iter.next())
163 {
164 beginRemoveRows(QModelIndex(), i, i);
165 iter.remove();
166 endRemoveRows();
167 }
168 i++;
169 }
173/*! \internal */
174void IndicatorsModel::onIdentifierChanged()
176 notifyDataChanged(QObject::sender(), Identifier);
179/*! \internal */
180void IndicatorsModel::onIndicatorPropertiesChanged()
182 notifyDataChanged(QObject::sender(), IndicatorProperties);
185/*! \internal */
186void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
188 Indicator* plugin = qobject_cast<Indicator*>(sender);
189 if (!plugin)
190 return;
192 int index = 0;
193 QMutableListIterator<Indicator::Ptr> iter(m_plugins);
194 while(iter.hasNext())
195 {
196 if (iter.next().data() == plugin)
197 {
198 QModelIndex changedIndex = this->index(index);
199 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
200 break;
201 }
202 index++;
203 }
206/*! \internal */
207QHash<int, QByteArray> IndicatorsModel::roleNames() const
209 static QHash<int, QByteArray> roles;
210 if (roles.isEmpty())
211 {
212 roles[Identifier] = "identifier";
213 roles[Priority] = "priority";
214 roles[Title] = "title";
215 roles[Description] = "description";
216 roles[WidgetSource] = "widgetSource";
217 roles[PageSource] = "pageSource";
218 roles[IndicatorProperties] = "indicatorProperties";
219 roles[IsValid] = "isValid";
220 }
221 return roles;
224/*! \internal */
225int IndicatorsModel::columnCount(const QModelIndex &) const
227 return 1;
230/*! \internal */
231QVariant IndicatorsModel::defaultData(Indicator::Ptr plugin, int role)
233 switch (role)
234 {
235 case Priority:
236 return 0;
237 case Title:
238 return plugin ? plugin->identifier() : "Unknown";
239 case Description:
240 return "";
241 case WidgetSource:
242 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorWidget.qml";
243 case PageSource:
244 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorPage.qml";
245 }
246 return QVariant();
249/*! \internal */
250QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
252 if (!index.isValid() || index.row() >= m_plugins.size())
253 return QVariant();
255 Indicator::Ptr plugin = m_plugins[index.row()];
257 switch (role)
258 {
259 case Identifier:
260 if (plugin)
261 {
262 return QVariant(plugin->identifier());
263 }
264 break;
265 case IndicatorProperties:
266 if (plugin)
267 {
268 return QVariant(plugin->indicatorProperties());
269 }
270 break;
271 case IsValid:
272 return (plugin ? true : false);
273 case Priority:
274 case Title:
275 case Description:
276 case WidgetSource:
277 case PageSource:
278 return indicatorData(plugin, role);
279 default:
280 break;
281 }
282 return QVariant();
285QVariant IndicatorsModel::indicatorData(const Indicator::Ptr& plugin, int role) const
287 if (plugin && m_parsed_indicator_data.contains(plugin->identifier()))
288 {
289 QVariantMap data = m_parsed_indicator_data[plugin->identifier()];
290 return data.value(roleNames()[role], QVariant());
291 }
292 return defaultData(plugin, role);
295/*! \internal */
296QModelIndex IndicatorsModel::parent(const QModelIndex&) const
298 return QModelIndex();
301/*! \internal */
302int IndicatorsModel::rowCount(const QModelIndex&) const
304 return m_plugins.count();
307void IndicatorsModel::setIndicatorData(const QVariant& data)
309 m_indicator_data = data;
311 m_parsed_indicator_data.clear();
312 QMap<QString, QVariant> map = data.toMap();
313 QMapIterator<QString, QVariant> iter(map);
314 while(iter.hasNext())
315 {
316 iter.next();
317 m_parsed_indicator_data[iter.key()] = iter.value().toMap();
318 }
320 Q_EMIT indicatorDataChanged(m_indicator_data);
323QVariant IndicatorsModel::indicatorData() const
325 return m_indicator_data;