Lomiri
Loading...
Searching...
No Matches
lomirimenumodelstack.cpp
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 */
19
20#include "lomirimenumodelstack.h"
21
22#include <QDebug>
23#include <ayatanamenumodel.h>
24
25class LomiriMenuModelEntry : public QObject {
26 Q_OBJECT
27public:
28 LomiriMenuModelEntry(AyatanaMenuModel* model, AyatanaMenuModel* 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, &AyatanaMenuModel::rowsInserted, this, &LomiriMenuModelEntry::onRowsInserted);
35 QObject::connect(m_parentModel, &AyatanaMenuModel::rowsRemoved, this, &LomiriMenuModelEntry::onRowsRemoved);
36 QObject::connect(m_parentModel, &AyatanaMenuModel::modelReset, this, &LomiriMenuModelEntry::onModelReset);
37 }
38 }
39
40 AyatanaMenuModel* model() const { return m_model; }
41
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 }
50
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 }
64
65 void onModelReset()
66 {
67 Q_EMIT remove();
68 disconnect(m_parentModel, 0, this, 0);
69 }
70
71Q_SIGNALS:
72 void remove();
73
74private:
75 AyatanaMenuModel* m_model;
76 AyatanaMenuModel* m_parentModel;
77 int m_index;
78};
79
80LomiriMenuModelStack::LomiriMenuModelStack(QObject* parent)
81 : QObject(parent)
82{
83}
84
85LomiriMenuModelStack::~LomiriMenuModelStack()
86{
87 qDeleteAll(m_menuModels);
88 m_menuModels.clear();
89}
90
91AyatanaMenuModel* LomiriMenuModelStack::head() const
92{
93 return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : nullptr;
94}
95
96void LomiriMenuModelStack::setHead(AyatanaMenuModel* model)
97{
98 if (head() != model) {
99 qDeleteAll(m_menuModels);
100 m_menuModels.clear();
101
102 push(model, 0);
103 Q_EMIT headChanged(model);
104 }
105}
106
107AyatanaMenuModel* LomiriMenuModelStack::tail() const
108{
109 return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : nullptr;
110}
111
112int LomiriMenuModelStack::count() const
113{
114 return m_menuModels.count();
115}
116
117void LomiriMenuModelStack::push(AyatanaMenuModel* model, int index)
118{
119 LomiriMenuModelEntry* entry = new LomiriMenuModelEntry(model, tail(), index);
120 QObject::connect(entry, &LomiriMenuModelEntry::remove, this, &LomiriMenuModelStack::onRemove);
121
122 m_menuModels << entry;
123 Q_EMIT tailChanged(model);
124 Q_EMIT countChanged(m_menuModels.count());
125}
126
127AyatanaMenuModel* LomiriMenuModelStack::pop()
128{
129 if (m_menuModels.isEmpty()) {
130 return nullptr;
131 }
132 LomiriMenuModelEntry* entry = m_menuModels.takeLast();
133 AyatanaMenuModel* model = entry->model();
134 entry->deleteLater();
135
136 Q_EMIT tailChanged(tail());
137 if (m_menuModels.isEmpty()) {
138 Q_EMIT headChanged(nullptr);
139 }
140 Q_EMIT countChanged(m_menuModels.count());
141
142 return model;
143}
144
145void LomiriMenuModelStack::onRemove()
146{
147 LomiriMenuModelEntry* removed = qobject_cast<LomiriMenuModelEntry*>(sender());
148 if (!m_menuModels.contains(removed))
149 return;
150
151 for (int i = m_menuModels.count() -1; i >= 0; i--) {
152 LomiriMenuModelEntry* entry = m_menuModels[i];
153 pop();
154 if (entry == removed) {
155 break;
156 }
157 }
158}
159
160#include "lomirimenumodelstack.moc"