on bionic help sign in
unity8/plugins/Unity/Indicators/modelactionrootstate.cpp
204 lines 5.7 kB history raw
1/*
2 * Copyright 2013-2016 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 "modelactionrootstate.h"
21#include "indicators.h"
23#include <unitymenumodel.h>
24#include <QVariant>
25#include <QIcon>
27extern "C" {
28#include <glib.h>
29#include <gio/gio.h>
32ModelActionRootState::ModelActionRootState(QObject *parent)
33 : RootStateObject(parent),
34 m_menu(nullptr)
35 , m_reentryGuard(false)
39ModelActionRootState::~ModelActionRootState()
43UnityMenuModel* ModelActionRootState::menu() const
45 return m_menu;
48void ModelActionRootState::setMenu(UnityMenuModel* menu)
50 if (m_menu != menu) {
51 bool wasValid = valid();
53 if (m_menu) {
54 m_menu->disconnect(this);
55 }
56 m_menu = menu;
58 if (m_menu) {
59 connect(m_menu, &UnityMenuModel::rowsInserted, this, &ModelActionRootState::onModelRowsAdded);
60 connect(m_menu, &UnityMenuModel::rowsRemoved, this, &ModelActionRootState::onModelRowsRemoved);
61 connect(m_menu, &UnityMenuModel::dataChanged, this, &ModelActionRootState::onModelDataChanged);
63 connect(m_menu, &UnityMenuModel::destroyed, this, &ModelActionRootState::reset);
64 }
65 updateActionState();
66 updateOtherActions();
67 Q_EMIT menuChanged();
69 if (wasValid != valid())
70 Q_EMIT validChanged();
71 }
74QString ModelActionRootState::secondaryAction() const
76 return m_secondaryAction;
79QString ModelActionRootState::scrollAction() const
81 return m_scrollAction;
84QString ModelActionRootState::submenuAction() const
86 return m_submenuAction;
89bool ModelActionRootState::valid() const
91 return !currentState().empty();
94void ModelActionRootState::onModelRowsAdded(const QModelIndex& parent, int start, int end)
96 Q_UNUSED(parent);
97 if (start == 0 && end >= 0) {
98 updateActionState();
99 updateOtherActions();
100 }
103void ModelActionRootState::onModelRowsRemoved(const QModelIndex& parent, int start, int end)
105 Q_UNUSED(parent);
106 if (start == 0 && end >= 0) {
107 updateActionState();
108 updateOtherActions();
109 }
112void ModelActionRootState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
114 Q_UNUSED(roles);
115 if (!topLeft.isValid() || !bottomRight.isValid()) {
116 return;
117 }
119 if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
120 updateActionState();
121 updateOtherActions();
122 }
125void ModelActionRootState::reset()
127 m_menu = nullptr;
129 Q_EMIT menuChanged();
130 setCurrentState(QVariantMap());
132 updateOtherActions();
135void ModelActionRootState::updateActionState()
137 if (m_reentryGuard) return;
138 m_reentryGuard = true;
140 if (m_menu && m_menu->rowCount() > 0) {
141 ActionStateParser* oldParser = m_menu->actionStateParser();
142 m_menu->setActionStateParser(&m_parser);
144 QVariantMap state = m_menu->get(0, "actionState").toMap();
146 m_menu->setActionStateParser(oldParser);
148 setCurrentState(state);
149 } else if (!m_menu) {
150 setCurrentState(QVariantMap());
151 }
152 // else if m_menu->rowCount() == 0, let's leave existing cache in place
153 // until the new menu comes in, to avoid flashing the UI empty for a moment
155 m_reentryGuard = false;
158void ModelActionRootState::updateOtherActions()
160 if (m_reentryGuard) return;
161 m_reentryGuard = true;
163 if (m_menu && m_menu->rowCount() > 0) {
164 QVariantMap map;
165 map[QStringLiteral("submenu-action")] = QStringLiteral("string");
166 map[QStringLiteral("x-canonical-scroll-action")] = QStringLiteral("string");
167 map[QStringLiteral("x-canonical-secondary-action")] = QStringLiteral("string");
168 m_menu->loadExtendedAttributes(0, map);
169 QVariantMap extMap = m_menu->get(0, "ext").toMap();
171 QString secondaryAction = extMap.value(QStringLiteral("xCanonicalSecondaryAction")).toString();
172 if (m_secondaryAction != secondaryAction) {
173 m_secondaryAction = secondaryAction;
174 Q_EMIT secondaryActionChanged();
175 }
177 QString scrollAction = extMap.value(QStringLiteral("xCanonicalScrollAction")).toString();
178 if (m_scrollAction != scrollAction) {
179 m_scrollAction = scrollAction;
180 Q_EMIT scrollActionChanged();
181 }
183 QString submenuAction = extMap.value(QStringLiteral("submenuAction")).toString();
184 if (m_submenuAction != submenuAction) {
185 m_submenuAction = submenuAction;
186 Q_EMIT submenuActionChanged();
187 }
188 } else {
189 if (!m_secondaryAction.isEmpty()) {
190 m_secondaryAction.clear();
191 Q_EMIT secondaryActionChanged();
192 }
193 if (!m_scrollAction.isEmpty()) {
194 m_scrollAction.clear();
195 Q_EMIT scrollActionChanged();
196 }
197 if (!m_submenuAction.isEmpty()) {
198 m_submenuAction.clear();
199 Q_EMIT submenuActionChanged();
200 }
201 }
203 m_reentryGuard = false;