@@ -1,5 +1,5 @@
2− * Copyright 2013 Canonical Ltd.
2+ * Copyright 2013-2016 Canonical Ltd.
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -32,6 +32,7 @@ extern "C" {
32ModelActionRootState::ModelActionRootState(QObject *parent)
32ModelActionRootState::ModelActionRootState(QObject *parent)
33 : RootStateObject(parent),
33 : RootStateObject(parent),
34 m_menu(nullptr)
34 m_menu(nullptr)
35+ , m_reentryGuard(false)
@@ -62,6 +63,7 @@ void ModelActionRootState::setMenu(UnityMenuModel* menu)
62 connect(m_menu, &UnityMenuModel::destroyed, this, &ModelActionRootState::reset);
63 connect(m_menu, &UnityMenuModel::destroyed, this, &ModelActionRootState::reset);
64 updateActionState();
65 updateActionState();
66+ updateOtherActions();
65 Q_EMIT menuChanged();
67 Q_EMIT menuChanged();
67 if (wasValid != valid())
69 if (wasValid != valid())
@@ -69,6 +71,21 @@ void ModelActionRootState::setMenu(UnityMenuModel* menu)
74+QString ModelActionRootState::secondaryAction() const
76+ return m_secondaryAction;
79+QString ModelActionRootState::scrollAction() const
81+ return m_scrollAction;
84+QString ModelActionRootState::submenuAction() const
86+ return m_submenuAction;
72bool ModelActionRootState::valid() const
89bool ModelActionRootState::valid() const
74 return !currentState().empty();
91 return !currentState().empty();
@@ -79,6 +96,7 @@ void ModelActionRootState::onModelRowsAdded(const QModelIndex& parent, int start
79 Q_UNUSED(parent);
96 Q_UNUSED(parent);
80 if (start == 0 && end >= 0) {
97 if (start == 0 && end >= 0) {
81 updateActionState();
98 updateActionState();
99+ updateOtherActions();
@@ -87,6 +105,7 @@ void ModelActionRootState::onModelRowsRemoved(const QModelIndex& parent, int sta
87 Q_UNUSED(parent);
105 Q_UNUSED(parent);
88 if (start == 0 && end >= 0) {
106 if (start == 0 && end >= 0) {
89 updateActionState();
107 updateActionState();
108+ updateOtherActions();
@@ -99,6 +118,7 @@ void ModelActionRootState::onModelDataChanged(const QModelIndex& topLeft, const
100 if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
119 if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
101 updateActionState();
120 updateActionState();
121+ updateOtherActions();
@@ -108,10 +128,15 @@ void ModelActionRootState::reset()
109 Q_EMIT menuChanged();
129 Q_EMIT menuChanged();
110 setCurrentState(QVariantMap());
130 setCurrentState(QVariantMap());
132+ updateOtherActions();
113void ModelActionRootState::updateActionState()
135void ModelActionRootState::updateActionState()
137+ if (m_reentryGuard) return;
138+ m_reentryGuard = true;
115 if (m_menu && m_menu->rowCount() > 0) {
140 if (m_menu && m_menu->rowCount() > 0) {
116 ActionStateParser* oldParser = m_menu->actionStateParser();
141 ActionStateParser* oldParser = m_menu->actionStateParser();
117 m_menu->setActionStateParser(&m_parser);
142 m_menu->setActionStateParser(&m_parser);
@@ -126,4 +151,54 @@ void ModelActionRootState::updateActionState()
127 // else if m_menu->rowCount() == 0, let's leave existing cache in place
152 // else if m_menu->rowCount() == 0, let's leave existing cache in place
128 // until the new menu comes in, to avoid flashing the UI empty for a moment
153 // until the new menu comes in, to avoid flashing the UI empty for a moment
155+ m_reentryGuard = false;
158+void ModelActionRootState::updateOtherActions()
160+ if (m_reentryGuard) return;
161+ m_reentryGuard = true;
163+ if (m_menu && m_menu->rowCount() > 0) {
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();
177+ QString scrollAction = extMap.value(QStringLiteral("xCanonicalScrollAction")).toString();
178+ if (m_scrollAction != scrollAction) {
179+ m_scrollAction = scrollAction;
180+ Q_EMIT scrollActionChanged();
183+ QString submenuAction = extMap.value(QStringLiteral("submenuAction")).toString();
184+ if (m_submenuAction != submenuAction) {
185+ m_submenuAction = submenuAction;
186+ Q_EMIT submenuActionChanged();
189+ if (!m_secondaryAction.isEmpty()) {
190+ m_secondaryAction.clear();
191+ Q_EMIT secondaryActionChanged();
193+ if (!m_scrollAction.isEmpty()) {
194+ m_scrollAction.clear();
195+ Q_EMIT scrollActionChanged();
197+ if (!m_submenuAction.isEmpty()) {
198+ m_submenuAction.clear();
199+ Q_EMIT submenuActionChanged();
203+ m_reentryGuard = false;