on 4bf2e44 help sign in
unity8/plugins/Unity/Indicators/indicatorsmodel.cpp
317 lines 8.4 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 "indicators.h"
24#include "paths.h"
26#include <QQmlContext>
27#include <QQmlEngine>
28#include <QDebug>
30/*!
31 \qmltype IndicatorsModel
32 \inherits QAbstractListModel
34 \brief The IndicatorsModel class defines the list model for indicators
36 \b {This component is under heavy development.}
38 This class expose the available indicators.
40 \code
41 IndicatorsModel {
42 id: menuModel
43 }
45 ListView {
46 id: view
47 model: menuModel
48 Component.onCompleted: menuModel.load()
49 }
50 \endcode
51*/
52IndicatorsModel::IndicatorsModel(QObject *parent)
53 : QAbstractListModel(parent)
55 m_manager = new IndicatorsManager(this);
56 QObject::connect(m_manager, SIGNAL(indicatorLoaded(const QString&)), this, SLOT(onIndicatorLoaded(const QString&)));
57 QObject::connect(m_manager, SIGNAL(indicatorAboutToBeUnloaded(const QString&)), this, SLOT(onIndicatorAboutToBeUnloaded(const QString&)));
59 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
60 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
61 QObject::connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
64/*! \internal */
65IndicatorsModel::~IndicatorsModel()
67 disconnect(m_manager, 0, 0, 0);
68 m_manager->deleteLater();
71/*!
72 \qmlproperty IndicatorsModel::count
73 The number of data entries in the model.
75 \b Note: methods should only be called after the Component has completed.
76*/
77int IndicatorsModel::count() const
79 return rowCount();
82/*!
83 \qmlmethod IndicatorsModel::unload()
85 Load all indicators.
86*/
87void IndicatorsModel::load()
89 m_indicators.clear();
90 m_manager->load();
93/*!
94 \qmlmethod IndicatorsModel::unload()
96 Unload all indicators.
97*/
98void IndicatorsModel::unload()
100 m_manager->unload();
103/*! \internal */
104void IndicatorsModel::onIndicatorLoaded(const QString& indicator_name)
106 Indicator::Ptr indicator = m_manager->indicator(indicator_name);
107 if (!indicator)
108 {
109 return;
110 }
112 if (m_indicators.indexOf(indicator) >= 0)
113 {
114 return;
115 }
117 // find the insert position
118 int pos = 0;
119 while (pos < count())
120 {
121 // keep going while the existing position is greater. (put lower position on end)
122 if (indicator->position() >= data(index(pos), IndicatorsModelRole::Position).toInt())
123 break;
124 pos++;
125 }
127 QObject::connect(indicator.data(), SIGNAL(identifierChanged(const QString&)), this, SLOT(onIdentifierChanged()));
128 QObject::connect(indicator.data(), SIGNAL(indicatorPropertiesChanged(const QVariant&)), this, SLOT(onIndicatorPropertiesChanged()));
130 beginInsertRows(QModelIndex(), pos, pos);
132 m_indicators.insert(pos, indicator);
133 endInsertRows();
136/*! \internal */
137void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator_name)
139 Indicator::Ptr indicator = m_manager->indicator(indicator_name);
140 if (!indicator)
141 {
142 return;
143 }
145 int i = 0;
146 QMutableListIterator<Indicator::Ptr> iter(m_indicators);
147 while(iter.hasNext())
148 {
149 if (indicator == iter.next())
150 {
151 beginRemoveRows(QModelIndex(), i, i);
152 iter.remove();
153 endRemoveRows();
154 break;
155 }
156 i++;
157 }
161/*! \internal */
162void IndicatorsModel::onIdentifierChanged()
164 notifyDataChanged(QObject::sender(), IndicatorsModelRole::Identifier);
167/*! \internal */
168void IndicatorsModel::onIndicatorPropertiesChanged()
170 notifyDataChanged(QObject::sender(), IndicatorsModelRole::IndicatorProperties);
173/*! \internal */
174void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
176 Indicator* indicator = qobject_cast<Indicator*>(sender);
177 if (!indicator)
178 {
179 return;
180 }
182 int index = 0;
183 QMutableListIterator<Indicator::Ptr> iter(m_indicators);
184 while(iter.hasNext())
185 {
186 if (indicator == iter.next())
187 {
188 QModelIndex changedIndex = this->index(index);
189 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
190 break;
191 }
192 index++;
193 }
196/*! \internal */
197QHash<int, QByteArray> IndicatorsModel::roleNames() const
199 static QHash<int, QByteArray> roles;
200 if (roles.isEmpty())
201 {
202 roles[IndicatorsModelRole::Identifier] = "identifier";
203 roles[IndicatorsModelRole::Position] = "position";
204 roles[IndicatorsModelRole::WidgetSource] = "widgetSource";
205 roles[IndicatorsModelRole::PageSource] = "pageSource";
206 roles[IndicatorsModelRole::IndicatorProperties] = "indicatorProperties";
207 }
208 return roles;
211/*! \internal */
212int IndicatorsModel::columnCount(const QModelIndex &) const
214 return 1;
217/*! \internal */
218QVariant IndicatorsModel::defaultData(Indicator::Ptr indicator, int role)
220 switch (role)
221 {
222 case IndicatorsModelRole::Position:
223 return 0;
224 case IndicatorsModelRole::WidgetSource:
225 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorWidget.qml";
226 case IndicatorsModelRole::PageSource:
227 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorPage.qml";
228 }
229 return QVariant();
232Q_INVOKABLE QVariant IndicatorsModel::data(int row, int role) const
234 return data(index(row, 0), role);
237/*! \internal */
238QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
240 if (!index.isValid() || index.row() >= m_indicators.size())
241 return QVariant();
243 Indicator::Ptr indicator = m_indicators[index.row()];
245 switch (role)
246 {
247 case IndicatorsModelRole::Identifier:
248 if (indicator)
249 {
250 return QVariant(indicator->identifier());
251 }
252 break;
253 case IndicatorsModelRole::Position:
254 if (indicator)
255 {
256 return QVariant(indicator->position());
257 }
258 break;
259 case IndicatorsModelRole::IndicatorProperties:
260 if (indicator)
261 {
262 return QVariant(indicator->indicatorProperties());
263 }
264 break;
265 case IndicatorsModelRole::WidgetSource:
266 case IndicatorsModelRole::PageSource:
267 return indicatorData(indicator, role);
268 default:
269 break;
270 }
271 return QVariant();
274QVariant IndicatorsModel::indicatorData(const Indicator::Ptr& indicator, int role) const
276 if (indicator && m_parsed_indicator_data.contains(indicator->identifier()))
277 {
278 QVariantMap data = m_parsed_indicator_data[indicator->identifier()];
279 if (data.contains(roleNames()[role])) {
280 return data[roleNames()[role]];
281 }
282 }
283 return defaultData(indicator, role);
286/*! \internal */
287QModelIndex IndicatorsModel::parent(const QModelIndex&) const
289 return QModelIndex();
292/*! \internal */
293int IndicatorsModel::rowCount(const QModelIndex&) const
295 return m_indicators.count();
298void IndicatorsModel::setIndicatorData(const QVariant& data)
300 m_indicator_data = data;
302 m_parsed_indicator_data.clear();
303 QMap<QString, QVariant> map = data.toMap();
304 QMapIterator<QString, QVariant> iter(map);
305 while(iter.hasNext())
306 {
307 iter.next();
308 m_parsed_indicator_data[iter.key()] = iter.value().toMap();
309 }
311 Q_EMIT indicatorDataChanged(m_indicator_data);
314QVariant IndicatorsModel::indicatorData() const
316 return m_indicator_data;