on c7dde77 help sign in
unity8/plugins/Unity/Indicators/unitymenumodelstack.cpp
154 lines 4.1 kB history raw
1/*
2 * Copyright 2013 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 * Nick Dedekind <nick.dedekind@canonical.com>
18 */
20#include "unitymenumodelstack.h"
22#include <QDebug>
23#include <unitymenumodel.h>
25class UnityMenuModelEntry : public QObject {
26 Q_OBJECT
27public:
28 UnityMenuModelEntry(UnityMenuModel* model, UnityMenuModel* parentModel, int index)
29 : m_model(model),
30 m_parentModel(parentModel),
31 m_index(index)
32 {
33 if (m_parentModel) {
34 QObject::connect(m_parentModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onRowsInserted(QModelIndex, int, int)));
35 QObject::connect(m_parentModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(onRowsRemoved(QModelIndex, int, int)));
36 QObject::connect(m_parentModel, SIGNAL(modelReset()), this, SLOT(onModelReset()));
37 }
38 }
40 UnityMenuModel* model() const { return m_model; }
42private Q_SLOTS:
43 void onRowsInserted(const QModelIndex&, int start, int end)
44 {
45 int delta = end-start + 1;
46 if (start <= m_index) {
47 m_index += delta;
48 }
49 }
51 void onRowsRemoved(const QModelIndex&, int start, int end)
52 {
53 int delta = end-start + 1;
54 if (start <= m_index) {
55 if (start + delta >= m_index) {
56 // in the range removed
57 Q_EMIT remove();
58 disconnect(m_parentModel, 0, this, 0);
59 } else {
60 m_index -= delta;
61 }
62 }
63 }
65Q_SIGNALS:
66 void remove();
68private Q_SLOTS:
69 void onModelReset()
70 {
71 Q_EMIT remove();
72 disconnect(m_parentModel, 0, this, 0);
73 }
75private:
76 UnityMenuModel* m_model;
77 UnityMenuModel* m_parentModel;
78 int m_index;
79};
81UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
82 : QObject(parent)
86UnityMenuModelStack::~UnityMenuModelStack()
88 qDeleteAll(m_menuModels);
89 m_menuModels.clear();
92UnityMenuModel* UnityMenuModelStack::head() const
94 return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : NULL;
97void UnityMenuModelStack::setHead(UnityMenuModel* model)
99 if (head() != model) {
100 qDeleteAll(m_menuModels);
101 m_menuModels.clear();
103 push(model, 0);
104 Q_EMIT headChanged(model);
105 }
108UnityMenuModel* UnityMenuModelStack::tail() const
110 return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : NULL;
113void UnityMenuModelStack::push(UnityMenuModel* model, int index)
115 UnityMenuModelEntry* entry = new UnityMenuModelEntry(model, tail(), index);
116 QObject::connect(entry, SIGNAL(remove()), SLOT(onRemove()));
118 m_menuModels << entry;
119 Q_EMIT tailChanged(model);
122UnityMenuModel* UnityMenuModelStack::pop()
124 if (m_menuModels.isEmpty()) {
125 return NULL;
126 }
127 UnityMenuModelEntry* entry = m_menuModels.takeLast();
128 UnityMenuModel* model = entry->model();
129 entry->deleteLater();
131 Q_EMIT tailChanged(tail());
132 if (m_menuModels.isEmpty()) {
133 Q_EMIT headChanged(NULL);
134 }
136 return model;
139void UnityMenuModelStack::onRemove()
141 UnityMenuModelEntry* removed = qobject_cast<UnityMenuModelEntry*>(sender());
142 if (!m_menuModels.contains(removed))
143 return;
145 for (int i = m_menuModels.count() -1; i >= 0; i--) {
146 UnityMenuModelEntry* entry = m_menuModels[i];
147 pop();
148 if (entry == removed) {
149 break;
150 }
151 }
154#include "unitymenumodelstack.moc"