on be81ccf help sign in
unity8/modules/Unity/Indicators/indicatorsmodel.cpp
320 lines 8.2 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
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 indicators.
85*/
86void IndicatorsModel::load()
88 m_indicators.clear();
89 m_manager->load();
92/*!
93 \qmlmethod IndicatorsModel::unload()
95 Unload all indicators.
96*/
97void IndicatorsModel::unload()
99 m_manager->unload();
102/*! \internal */
103void IndicatorsModel::onIndicatorLoaded(const QString& indicator_name)
105 Indicator::Ptr indicator = m_manager->indicator(indicator_name);
106 if (!indicator)
107 {
108 return;
109 }
111 if (m_indicators.indexOf(indicator) >= 0)
112 {
113 return;
114 }
116 // find the insert position
117 int pos = 0;
118 while (pos < count())
119 {
120 // keep going while the existing priority is less.
121 if (indicatorData(indicator, Priority).toInt() < data(index(pos), Priority).toInt())
122 break;
123 pos++;
124 }
126 QObject::connect(indicator.data(), SIGNAL(identifierChanged(const QString&)), this, SLOT(onIdentifierChanged()));
127 QObject::connect(indicator.data(), SIGNAL(indicatorPropertiesChanged(const QVariant&)), this, SLOT(onIndicatorPropertiesChanged()));
129 beginInsertRows(QModelIndex(), pos, pos);
131 m_indicators.insert(pos, indicator);
132 endInsertRows();
135/*! \internal */
136void IndicatorsModel::onIndicatorAboutToBeUnloaded(const QString& indicator_name)
138 Indicator::Ptr indicator = m_manager->indicator(indicator_name);
139 if (!indicator)
140 {
141 return;
142 }
144 int i = 0;
145 QMutableListIterator<Indicator::Ptr> iter(m_indicators);
146 while(iter.hasNext())
147 {
148 if (indicator == iter.next())
149 {
150 beginRemoveRows(QModelIndex(), i, i);
151 iter.remove();
152 endRemoveRows();
153 break;
154 }
155 i++;
156 }
160/*! \internal */
161void IndicatorsModel::onIdentifierChanged()
163 notifyDataChanged(QObject::sender(), Identifier);
166/*! \internal */
167void IndicatorsModel::onIndicatorPropertiesChanged()
169 notifyDataChanged(QObject::sender(), IndicatorProperties);
172/*! \internal */
173void IndicatorsModel::notifyDataChanged(QObject *sender, int role)
175 Indicator* indicator = qobject_cast<Indicator*>(sender);
176 if (!indicator)
177 {
178 return;
179 }
181 int index = 0;
182 QMutableListIterator<Indicator::Ptr> iter(m_indicators);
183 while(iter.hasNext())
184 {
185 if (indicator == iter.next())
186 {
187 QModelIndex changedIndex = this->index(index);
188 dataChanged(changedIndex, changedIndex, QVector<int>() << role);
189 break;
190 }
191 index++;
192 }
195/*! \internal */
196QHash<int, QByteArray> IndicatorsModel::roleNames() const
198 static QHash<int, QByteArray> roles;
199 if (roles.isEmpty())
200 {
201 roles[Identifier] = "identifier";
202 roles[Priority] = "priority";
203 roles[Title] = "title";
204 roles[Description] = "description";
205 roles[WidgetSource] = "widgetSource";
206 roles[PageSource] = "pageSource";
207 roles[IndicatorProperties] = "indicatorProperties";
208 roles[IsValid] = "isValid";
209 }
210 return roles;
213/*! \internal */
214int IndicatorsModel::columnCount(const QModelIndex &) const
216 return 1;
219/*! \internal */
220QVariant IndicatorsModel::defaultData(Indicator::Ptr indicator, int role)
222 switch (role)
223 {
224 case Priority:
225 return 0;
226 case Title:
227 return indicator ? indicator->identifier() : "Unknown";
228 case Description:
229 return "";
230 case WidgetSource:
231 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorWidget.qml";
232 case PageSource:
233 return shellAppDirectory()+"/Panel/Indicators/DefaultIndicatorPage.qml";
234 }
235 return QVariant();
238Q_INVOKABLE QVariant IndicatorsModel::data(int row, int role) const
240 return data(index(row, 0), role);
243/*! \internal */
244QVariant IndicatorsModel::data(const QModelIndex &index, int role) const
246 if (!index.isValid() || index.row() >= m_indicators.size())
247 return QVariant();
249 Indicator::Ptr indicator = m_indicators[index.row()];
251 switch (role)
252 {
253 case Identifier:
254 if (indicator)
255 {
256 return QVariant(indicator->identifier());
257 }
258 break;
259 case IndicatorProperties:
260 if (indicator)
261 {
262 return QVariant(indicator->indicatorProperties());
263 }
264 break;
265 case IsValid:
266 return (indicator ? true : false);
267 case Priority:
268 case Title:
269 case Description:
270 case WidgetSource:
271 case PageSource:
272 return indicatorData(indicator, role);
273 default:
274 break;
275 }
276 return QVariant();
279QVariant IndicatorsModel::indicatorData(const Indicator::Ptr& indicator, int role) const
281 if (indicator && m_parsed_indicator_data.contains(indicator->identifier()))
282 {
283 QVariantMap data = m_parsed_indicator_data[indicator->identifier()];
284 return data.value(roleNames()[role], QVariant());
285 }
286 return defaultData(indicator, role);
289/*! \internal */
290QModelIndex IndicatorsModel::parent(const QModelIndex&) const
292 return QModelIndex();
295/*! \internal */
296int IndicatorsModel::rowCount(const QModelIndex&) const
298 return m_indicators.count();
301void IndicatorsModel::setIndicatorData(const QVariant& data)
303 m_indicator_data = data;
305 m_parsed_indicator_data.clear();
306 QMap<QString, QVariant> map = data.toMap();
307 QMapIterator<QString, QVariant> iter(map);
308 while(iter.hasNext())
309 {
310 iter.next();
311 m_parsed_indicator_data[iter.key()] = iter.value().toMap();
312 }
314 Q_EMIT indicatorDataChanged(m_indicator_data);
317QVariant IndicatorsModel::indicatorData() const
319 return m_indicator_data;