on 574bbde help sign in
unity8/modules/Unity/Indicators/flatmenuproxymodel.cpp
332 lines 9.1 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) {
57 // FIXME - not working correctly with dynamic inserts/removes
59 connect(source,
60 SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
61 SLOT(onModelAboutToBeReset()));
62 connect(source,
63 SIGNAL(rowsInserted(QModelIndex,int,int)),
64 SLOT(onModelReset()));
66 connect(source,
67 SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
68 SLOT(onModelAboutToBeReset()));
69 connect(source,
70 SIGNAL(rowsRemoved(QModelIndex,int,int)),
71 SLOT(onModelReset()));
73 connect(source,
74 SIGNAL(modelAboutToBeReset()),
75 SLOT(onModelAboutToBeReset()));
76 connect(source,
77 SIGNAL(modelReset()),
78 SLOT(onModelReset()));
80 // initiliaze rowCount
81 QModelIndex lastItem = source->index(source->rowCount() - 1, 0);
82 m_rowCount = recursiveRowCount(lastItem);
83 } else {
84 m_rowCount = 0;
85 }
87 Q_EMIT countChanged();
90void FlatMenuProxyModel::setBusName(const QString &busName)
92 m_model->setBusName(busName);
95QString FlatMenuProxyModel::busName() const
97 return m_model->busName();
100void FlatMenuProxyModel::setObjectPath(const QString &busPath)
102 m_model->setObjectPath(busPath);
105QString FlatMenuProxyModel::objectPath() const
107 return m_model->objectPath();
110int FlatMenuProxyModel::status() const
112 return m_model->status();
115DBusEnums::BusType FlatMenuProxyModel::busType() const
117 return m_model->busType();
120void FlatMenuProxyModel::setIntBusType(int type)
122 m_model->setBusType((DBusEnums::BusType) type);
125void FlatMenuProxyModel::start()
127 m_model->start();
130void FlatMenuProxyModel::stop()
132 m_model->stop();
135QModelIndex FlatMenuProxyModel::mapFromSource(const QModelIndex &index) const
137 if (!index.isValid()) {
138 return QModelIndex();
139 }
141 QModelIndex result = createIndex(rowOffsetOf(index, index.row()), 0);
142 return result;
145QModelIndex FlatMenuProxyModel::mapToSource(const QModelIndex &index) const
147 if (sourceModel() && m_indexCache.contains(index.row())) {
148 QString key = m_indexCache.value(index.row());
149 QStringList sections = key.split('.', QString::SkipEmptyParts);
150 QModelIndex sourceIndex = QModelIndex();
151 for(int i=0; i < sections.size(); i++) {
152 sourceIndex = sourceModel()->index(sections.at(i).toInt(), 9, sourceIndex);
153 }
154 return sourceIndex;
155 } else {
156 return QModelIndex();
157 }
160QModelIndex FlatMenuProxyModel::index(int row, int sectionRow, const QModelIndex &parent, const QString &key) const
162 for (int i = 0, count = 0; i < sourceModel()->rowCount(parent); i++) {
163 QModelIndex sourceIndex = sourceModel()->index(i, 0, parent);
164 int indexCount = recursiveRowCount(sourceIndex);
166 if (count == sectionRow) {
167 QString sectionKey = key + "." + QString::number(i);
168 m_indexCache.insert(row, sectionKey);
169 return createIndex(row, 0);
170 } else if ((count + indexCount) >= sectionRow) {
171 count++;
172 return index(row, sectionRow - count, sourceIndex, key + "." + QString::number(i));
173 }
175 count += indexCount + 1;
176 }
177 return QModelIndex();
180QModelIndex FlatMenuProxyModel::index(int row, int, const QModelIndex &) const
182 return index(row, row, QModelIndex(), "");
185QModelIndex FlatMenuProxyModel::parent(const QModelIndex &) const
187 return QModelIndex();
190int FlatMenuProxyModel::columnCount(const QModelIndex &) const
192 return 1;
195int FlatMenuProxyModel::rowCount(const QModelIndex &) const
197 return m_rowCount;
200int FlatMenuProxyModel::count() const
202 return rowCount(QModelIndex());
205void FlatMenuProxyModel::onModelAboutToBeReset()
207 beginResetModel();
210void FlatMenuProxyModel::onModelReset()
212 // initiliaze rowCount
213 m_rowCount = 0;
214 for (int i = 0, iMax = sourceModel()->rowCount(); i < iMax; i++) {
215 QModelIndex index = sourceModel()->index(i, 0);
216 m_rowCount += recursiveRowCount(index) + 1;
217 }
218 m_indexCache.clear();
219 endResetModel();
220 Q_EMIT countChanged();
223// void FlatMenuProxyModel::onRowsAboutToBeInserted(const QModelIndex &index, int first, int last)
224// {
225// if (index.isValid()) {
226// int firstIndex = rowOffsetOf(index, first);
227// int lastIndex = rowOffsetOf(index, last, true);
229// beginInsertRows(QModelIndex(), firstIndex, lastIndex);
230// m_rowCount += (lastIndex - firstIndex + 1);
231// }
232// }
234// void FlatMenuProxyModel::onRowsAboutToBeRemoved(const QModelIndex &index, int first, int last)
235// {
236// if (index.isValid()) {
237// int firstIndex = rowOffsetOf(index, first);
238// int lastIndex = rowOffsetOf(index, last, true);
240// m_indexCache.clear();
241// beginRemoveRows(QModelIndex(), firstIndex, lastIndex);
242// m_rowCount -= (lastIndex - firstIndex + 1);
243// }
244// }
246// void FlatMenuProxyModel::onRowsInserted(const QModelIndex &index, int first, int last)
247// {
248// if (index.isValid()) {
249// m_indexCache.clear();
250// endInsertRows();
251// for (int i=first; i <= last; i++) {
252// QModelIndex subIndex = sourceModel()->index(i, 0, index.parent());
253// if (subIndex.isValid()) {
254// int subSectionSize = recursiveRowCount(subIndex);
255// if (subSectionSize > 0) {
256// int firstIndex = rowOffsetOf(index, i) + 1;
257// int lastIndex = rowOffsetOf(index, i, true);
259// beginInsertRows(QModelIndex(), firstIndex, lastIndex);
260// m_rowCount += lastIndex - firstIndex + 1;
261// endInsertRows();
262// }
263// }
264// }
265// }
266// Q_EMIT countChanged();
267// }
269// void FlatMenuProxyModel::onRowsRemoved(const QModelIndex &index, int, int)
270// {
271// if (index.isValid()) {
272// endRemoveRows();
273// Q_EMIT countChanged();
274// }
275// }
277int FlatMenuProxyModel::recursiveRowCount(const QModelIndex &index) const
279 int size = sourceModel()->rowCount(index);
280 for (int i=0, iMax=size; i < iMax; i++) {
281 QModelIndex currentIndex = sourceModel()->index(i, 0, index);
282 size += recursiveRowCount(currentIndex);
283 }
285 return size;
288int FlatMenuProxyModel::rowOffsetOf(const QModelIndex &index, int row, bool inclusive) const
290 int offset = 0;
292 QModelIndex parent = index.parent();
294 // Check row 0 offset
295 while(parent.isValid()) {
296 offset += 1;
297 for (int i = 0; i < parent.row(); i++) {
298 QModelIndex currentIndex = sourceModel()->index(i, 0, parent);
299 offset += recursiveRowCount(currentIndex) + 1;
300 }
301 parent = parent.parent();
302 }
304 // Check index.row() offset
305 for(int i = 0; i < row; i++) {
306 QModelIndex currentIndex = sourceModel()->index(i, 0, index.parent());
307 offset += recursiveRowCount(currentIndex) + 1;
308 }
310 if (inclusive) {
311 // itself
312 QModelIndex currentIndex = sourceModel()->index(row, 0, index.parent());
313 offset += recursiveRowCount(currentIndex);
314 }
316 return offset;
319/*! \for use in qml */
320QVariantMap FlatMenuProxyModel::get(int row) const
322 QVariantMap result;
324 QModelIndex index = this->index(row);
325 if (index.isValid()) {
326 const QHash<int, QByteArray> roleNames = this->roleNames();
327 Q_FOREACH(int i, roleNames.keys()) {
328 result.insert(roleNames[i], data(index, i));
329 }
330 }
331 return result;