on 64cc07a help sign in
unity8/tests/mocks/QMenuModel/unitymenumodel.cpp
310 lines 7.7 kB history raw
1/*
2 * Copyright (C) 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 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 General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17 */
19#include "unitymenumodel.h"
21#include <QTimer>
23enum MenuRoles {
24 LabelRole = Qt::DisplayRole + 1,
25 SensitiveRole,
26 IsSeparatorRole,
27 IconRole,
28 TypeRole,
29 ExtendedAttributesRole,
30 ActionRole,
31 ActionStateRole,
32 IsCheckRole,
33 IsRadioRole,
34 IsToggledRole,
35 ShortcutRole,
36 HasSubmenuRole
37};
39UnityMenuModel::UnityMenuModel(QObject *parent)
40 : QAbstractListModel(parent)
41 , m_rowCountStatus(NoRequestMade)
45UnityMenuModel::~UnityMenuModel()
49QVariant UnityMenuModel::modelData() const
51 return m_modelData;
54void UnityMenuModel::setModelData(const QVariant& data)
56 beginResetModel();
58 m_modelData = data.toList();
59 Q_EMIT modelDataChanged();
61 endResetModel();
64void UnityMenuModel::insertRow(int row, const QVariant& data)
66 row = qMin(row, m_modelData.count());
68 beginInsertRows(QModelIndex(), row, row);
70 m_modelData.insert(row, data);
72 endInsertRows();
75void UnityMenuModel::appendRow(const QVariant& data)
77 insertRow(m_modelData.count(), data);
80void UnityMenuModel::removeRow(int row)
82 if (row < 0 || m_modelData.count() <= row) {
83 return;
84 }
86 beginRemoveRows(QModelIndex(), row, row);
88 m_modelData.removeAt(row);
90 endRemoveRows();
93QByteArray UnityMenuModel::busName() const
95 return m_busName;
98void UnityMenuModel::setBusName(const QByteArray &busName)
100 this->m_busName = busName;
103QVariantMap UnityMenuModel::actions() const
105 return m_actions;
108void UnityMenuModel::setActions(const QVariantMap &actions)
110 this->m_actions = actions;
113QByteArray UnityMenuModel::menuObjectPath() const
115 return m_menuObjectPath;
118void UnityMenuModel::setMenuObjectPath(const QByteArray &path)
120 this->m_menuObjectPath = path;
123ActionStateParser* UnityMenuModel::actionStateParser() const
125 return nullptr;
128void UnityMenuModel::setActionStateParser(ActionStateParser*)
132QString UnityMenuModel::nameOwner() const
134 return QString("");
137int UnityMenuModel::rowCount(const QModelIndex&) const
139 // Fake the rowCount to be 0 for a while (100ms)
140 // This emulates menus in real world that don't load immediately
141 if (m_rowCountStatus == TimerRunning)
142 return 0;
144 if (m_rowCountStatus == NoRequestMade) {
145 UnityMenuModel *that = const_cast<UnityMenuModel*>(this);
146 that->m_rowCountStatus = TimerRunning;
147 QTimer::singleShot(100, that, [that] {
148 that->beginInsertRows(QModelIndex(), 0, that->m_modelData.count() - 1);
149 that->m_rowCountStatus = TimerFinished;
150 that->endInsertRows();
151 });
152 return 0;
153 }
155 return m_modelData.count();
158int UnityMenuModel::columnCount(const QModelIndex&) const
160 return 1;
163QVariant UnityMenuModel::data(const QModelIndex &index, int role) const
165 QVariantMap v = rowData(index.row());
166 QString roleName = roleNames()[role];
168 if (v.contains(roleName)) return v[roleName];
170 // defaults
171 switch (role) {
172 case LabelRole: return QString();
173 case SensitiveRole: return true;
174 case IsSeparatorRole: return false;
175 case IconRole: return QString();
176 case TypeRole: return QString();
177 case ExtendedAttributesRole: return QVariantMap();
178 case ActionRole: return QString();
179 case ActionStateRole: return QVariant();
180 case IsCheckRole: return false;
181 case IsRadioRole: return false;
182 case IsToggledRole: return false;
183 case ShortcutRole: return QString();
184 case HasSubmenuRole: return subMenuData(index.row()).isValid();
185 default: break;
186 }
187 return QVariant();
190QVariantMap UnityMenuModel::rowData(int row) const
192 if (m_modelData.count() <= row) {
193 return QVariantMap();
194 }
195 QVariantMap vRow = m_modelData.value(row, QVariantMap()).toMap();
196 return vRow["rowData"].toMap();
199QVariant UnityMenuModel::subMenuData(int row) const
201 QVariantMap v = m_modelData.value(row, QVariantMap()).toMap();
202 return v.value("submenu", QVariant());
205QModelIndex UnityMenuModel::index(int row, int column, const QModelIndex&) const
207 return createIndex(row, column);
210QModelIndex UnityMenuModel::parent(const QModelIndex &) const
212 return QModelIndex();
215QHash<int, QByteArray> UnityMenuModel::roleNames() const
217 QHash<int, QByteArray> names;
219 names[LabelRole] = "label";
220 names[SensitiveRole] = "sensitive";
221 names[IsSeparatorRole] = "isSeparator";
222 names[IconRole] = "icon";
223 names[TypeRole] = "type";
224 names[ExtendedAttributesRole] = "ext";
225 names[ActionRole] = "action";
226 names[ActionStateRole] = "actionState";
227 names[IsCheckRole] = "isCheck";
228 names[IsRadioRole] = "isRadio";
229 names[IsToggledRole] = "isToggled";
230 names[ShortcutRole] = "shortcut";
231 names[HasSubmenuRole] = "hasSubmenu";
233 return names;
236QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
238 if (position < 0 || m_modelData.count() < position) {
239 return nullptr;
240 }
242 while (submenus.count() <= position) {
243 submenus.append(nullptr);
244 }
246 QVariant submenuData = subMenuData(position);
247 if (submenuData.type() == (int)QMetaType::QVariantList) {
248 UnityMenuModel*& model = submenus[position];
249 if (!model) {
250 model = new UnityMenuModel(this);
251 connect(model, &UnityMenuModel::activated, this, &UnityMenuModel::activated);
252 }
253 if (model->modelData() != submenuData) {
254 model->setModelData(submenuData);
255 }
256 return model;
257 }
259 return nullptr;
262bool UnityMenuModel::loadExtendedAttributes(int, const QVariantMap &)
264 return false;
267QVariant UnityMenuModel::get(int row, const QByteArray &role)
269 static QHash<QByteArray, int> roles;
270 if (roles.isEmpty()) {
271 const QHash<int, QByteArray> names = roleNames();
272 for(auto it = names.begin(); it != names.end(); ++it)
273 roles.insert(it.value(), it.key());
274 }
276 return data(index(row, 0), roles[role]);
279void UnityMenuModel::activate(int row, const QVariant&)
281 QVariantMap vModelData = m_modelData.value(row, QVariantMap()).toMap();
282 QVariantMap rd = vModelData["rowData"].toMap();
284 bool isCheckable = rd[roleNames()[IsCheckRole]].toBool() || rd[roleNames()[IsRadioRole]].toBool();
285 if (isCheckable) {
286 rd[roleNames()[IsToggledRole]] = !rd[roleNames()[IsToggledRole]].toBool();
287 vModelData["rowData"] = rd;
288 m_modelData[row] = vModelData;
290 dataChanged(index(row, 0), index(row, 0), QVector<int>() << IsToggledRole);
291 }
292 Q_EMIT activated(rd[roleNames()[ActionRole]].toString());
295void UnityMenuModel::aboutToShow(int index)
297 Q_EMIT aboutToShowCalled(index);
300void UnityMenuModel::changeState(int, const QVariant&)
304void UnityMenuModel::registerAction(UnityMenuAction*)
308void UnityMenuModel::unregisterAction(UnityMenuAction*)