on dc0c118 help sign in
unity8/plugins/IndicatorsClient/flatmenuproxymodel.cpp
340 lines 9.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 */
20extern "C" {
21#include <gio/gio.h>
24#include "flatmenuproxymodel.h"
25#include <QString>
26#include <QStringList>
28FlatMenuProxyModel::FlatMenuProxyModel(QAbstractItemModel *source)
29 : QAbstractProxyModel(source),
30 m_rowCount(0)
32 m_model = new QDBusMenuModel;
33 setSourceModel(m_model);
36/*! \internal */
37FlatMenuProxyModel::~FlatMenuProxyModel()
39 delete m_model;
42void FlatMenuProxyModel::setSourceModel(QAbstractItemModel *source)
44 if (sourceModel()) {
45 QAbstractItemModel *oldSource = sourceModel();
46 if (oldSource == source) {
47 return;
48 }
50 oldSource->disconnect(this);
51 }
53 QAbstractProxyModel::setSourceModel(source);
55 if (source) {
56 connect(source,
57 SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
58 SLOT(onRowsAboutToBeInserted(QModelIndex,int,int)));
59 connect(source,
60 SIGNAL(rowsInserted(QModelIndex,int,int)),
61 SLOT(onRowsInserted(QModelIndex,int,int)));
63 connect(source,
64 SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
65 SLOT(onRowsAboutToBeRemoved(QModelIndex,int,int)));
66 connect(source,
67 SIGNAL(rowsRemoved(QModelIndex,int,int)),
68 SLOT(onRowsRemoved(QModelIndex,int,int)));
70 connect(source,
71 SIGNAL(modelAboutToBeReset()),
72 SLOT(onModelAboutToBeReset()));
73 connect(source,
74 SIGNAL(modelReset()),
75 SLOT(onModelReset()));
77 connect(source,
78 SIGNAL(rowsInserted(QModelIndex,int,int)),
79 SIGNAL(countChanged()));
80 connect(source,
81 SIGNAL(rowsRemoved(QModelIndex,int,int)),
82 SIGNAL(countChanged()));
83 connect(source,
84 SIGNAL(modelReset()),
85 SIGNAL(countChanged()));
87 // initiliaze rowCount
88 QModelIndex lastItem = source->index(source->rowCount() - 1, 0);
89 m_rowCount = recursiveRowCount(lastItem);
90 } else {
91 m_rowCount = 0;
92 }
94 Q_EMIT countChanged();
97void FlatMenuProxyModel::setBusName(const QString &busName)
99 m_model->setBusName(busName);
102QString FlatMenuProxyModel::busName() const
104 return m_model->busName();
107void FlatMenuProxyModel::setObjectPath(const QString &busPath)
109 m_model->setObjectPath(busPath);
112QString FlatMenuProxyModel::objectPath() const
114 return m_model->objectPath();
117int FlatMenuProxyModel::status() const
119 return m_model->status();
122DBusEnums::BusType FlatMenuProxyModel::busType() const
124 return m_model->busType();
127void FlatMenuProxyModel::setIntBusType(int type)
129 m_model->setBusType((DBusEnums::BusType) type);
132void FlatMenuProxyModel::start()
134 m_model->start();
137void FlatMenuProxyModel::stop()
139 m_model->stop();
142QModelIndex FlatMenuProxyModel::mapFromSource(const QModelIndex &index) const
144 if (!index.isValid()) {
145 return QModelIndex();
146 }
148 QModelIndex result = createIndex(rowOffsetOf(index, index.row()), 0);
149 return result;
152QModelIndex FlatMenuProxyModel::mapToSource(const QModelIndex &index) const
154 if (sourceModel() && m_indexCache.contains(index.row())) {
155 QString key = m_indexCache.value(index.row());
156 QStringList sections = key.split('.', QString::SkipEmptyParts);
157 QModelIndex sourceIndex = QModelIndex();
158 for(int i=0; i < sections.size(); i++) {
159 sourceIndex = sourceModel()->index(sections.at(i).toInt(), 9, sourceIndex);
160 }
161 return sourceIndex;
162 } else {
163 return QModelIndex();
164 }
167QModelIndex FlatMenuProxyModel::index(int row, int sectionRow, const QModelIndex &parent, const QString &key) const
169 for (int i = 0, count = 0; i < sourceModel()->rowCount(parent); i++) {
170 QModelIndex sourceIndex = sourceModel()->index(i, 0, parent);
171 int indexCount = recursiveRowCount(sourceIndex);
173 if (count == sectionRow) {
174 QString sectionKey = key + "." + QString::number(i);
175 m_indexCache.insert(row, sectionKey);
176 return createIndex(row, 0);
177 } else if ((count + indexCount) >= sectionRow) {
178 count++;
179 return index(row, sectionRow - count, sourceIndex, key + "." + QString::number(i));
180 }
182 count += indexCount + 1;
183 }
184 return QModelIndex();
187QModelIndex FlatMenuProxyModel::index(int row, int, const QModelIndex &) const
189 return index(row, row, QModelIndex(), "");
192QModelIndex FlatMenuProxyModel::parent(const QModelIndex &) const
194 return QModelIndex();
197int FlatMenuProxyModel::columnCount(const QModelIndex &) const
199 return 1;
202int FlatMenuProxyModel::rowCount(const QModelIndex &) const
204 return m_rowCount;
207int FlatMenuProxyModel::count() const
209 return rowCount(QModelIndex());
212void FlatMenuProxyModel::onRowsAboutToBeInserted(const QModelIndex &index, int first, int last)
215 if (index.isValid()) {
216 int firstIndex = rowOffsetOf(index, first);
217 int lastIndex = rowOffsetOf(index, last, true);
219 beginInsertRows(QModelIndex(), firstIndex, lastIndex);
220 m_rowCount += (lastIndex - firstIndex + 1);
221 }
224void FlatMenuProxyModel::onRowsAboutToBeRemoved(const QModelIndex &index, int first, int last)
226 if (index.isValid()) {
227 int firstIndex = rowOffsetOf(index, first);
228 int lastIndex = rowOffsetOf(index, last, true);
230 m_indexCache.clear();
231 beginRemoveRows(QModelIndex(), firstIndex, lastIndex);
232 m_rowCount -= (lastIndex - firstIndex + 1);
233 }
236void FlatMenuProxyModel::onModelAboutToBeReset()
238 beginResetModel();
241void FlatMenuProxyModel::onRowsInserted(const QModelIndex &index, int first, int last)
243 if (index.isValid()) {
244 m_indexCache.clear();
245 endInsertRows();
246 for (int i=first; i <= last; i++) {
247 QModelIndex subIndex = sourceModel()->index(i, 0, index.parent());
248 if (subIndex.isValid()) {
249 int subSectionSize = recursiveRowCount(subIndex);
250 if (subSectionSize > 0) {
251 int firstIndex = rowOffsetOf(index, i) + 1;
252 int lastIndex = rowOffsetOf(index, i, true);
254 beginInsertRows(QModelIndex(), firstIndex, lastIndex);
255 m_rowCount += lastIndex - firstIndex + 1;
256 endInsertRows();
257 }
258 }
259 }
260 }
261 Q_EMIT countChanged();
264void FlatMenuProxyModel::onRowsRemoved(const QModelIndex &index, int, int)
266 if (index.isValid()) {
267 endRemoveRows();
268 Q_EMIT countChanged();
269 }
272void FlatMenuProxyModel::onModelReset()
274 // initiliaze rowCount
275 m_rowCount = 0;
276 for (int i = 0, iMax = sourceModel()->rowCount(); i < iMax; i++) {
277 QModelIndex index = sourceModel()->index(i, 0);
278 m_rowCount += recursiveRowCount(index) + 1;
279 }
280 m_indexCache.clear();
281 endResetModel();
282 Q_EMIT countChanged();
285int FlatMenuProxyModel::recursiveRowCount(const QModelIndex &index) const
287 int size = sourceModel()->rowCount(index);
288 for (int i=0, iMax=size; i < iMax; i++) {
289 QModelIndex currentIndex = sourceModel()->index(i, 0, index);
290 size += recursiveRowCount(currentIndex);
291 }
293 return size;
296int FlatMenuProxyModel::rowOffsetOf(const QModelIndex &index, int row, bool inclusive) const
298 int offset = 0;
300 QModelIndex parent = index.parent();
302 // Check row 0 offset
303 while(parent.isValid()) {
304 offset += 1;
305 for (int i = 0; i < parent.row(); i++) {
306 QModelIndex currentIndex = sourceModel()->index(i, 0, parent);
307 offset += recursiveRowCount(currentIndex) + 1;
308 }
309 parent = parent.parent();
310 }
312 // Check index.row() offset
313 for(int i = 0; i < row; i++) {
314 QModelIndex currentIndex = sourceModel()->index(i, 0, index.parent());
315 offset += recursiveRowCount(currentIndex) + 1;
316 }
318 if (inclusive) {
319 // itself
320 QModelIndex currentIndex = sourceModel()->index(row, 0, index.parent());
321 offset += recursiveRowCount(currentIndex);
322 }
324 return offset;
327/*! \for use in qml */
328QVariantMap FlatMenuProxyModel::get(int row) const
330 QVariantMap result;
332 QModelIndex index = this->index(row);
333 if (index.isValid()) {
334 const QHash<int, QByteArray> roleNames = this->roleNames();
335 Q_FOREACH(int i, roleNames.keys()) {
336 result.insert(roleNames[i], data(index, i));
337 }
338 }
339 return result;