on 1aca428 help sign in
unity8/plugins/Unity/Indicators/rootactionstate.cpp
252 lines 6.8 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 "rootactionstate.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>
32RootActionState::RootActionState(QObject *parent)
33 : ActionStateParser(parent)
37RootActionState::~RootActionState()
41UnityMenuModel* RootActionState::menu() const
43 return m_menu;
46void RootActionState::setMenu(UnityMenuModel* menu)
48 if (m_menu != menu) {
49 if (!m_menu.isNull()) {
50 m_menu->disconnect(this);
51 }
52 m_menu = menu;
54 if (menu) {
55 connect(menu, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(onModelRowsAdded(const QModelIndex&, int, int)));
56 connect(menu, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(onModelRowsRemoved(const QModelIndex&, int, int)));
57 connect(menu, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(onModelDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
58 }
60 updateActionState();
61 Q_EMIT menuChanged();
62 }
65void RootActionState::onModelRowsAdded(const QModelIndex& parent, int start, int end)
67 Q_UNUSED(parent);
68 if (start == 0 && end >= 0) {
69 updateActionState();
70 }
73void RootActionState::onModelRowsRemoved(const QModelIndex& parent, int start, int end)
75 Q_UNUSED(parent);
76 if (start == 0 && end >= 0) {
77 updateActionState();
78 }
81void RootActionState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
83 Q_UNUSED(roles);
84 if (!topLeft.isValid() || !bottomRight.isValid()) {
85 return;
86 }
88 if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
89 updateActionState();
90 }
93void RootActionState::updateActionState()
95 if (!m_menu.isNull() && m_menu->rowCount() > 0) {
96 ActionStateParser* oldParser = m_menu->actionStateParser();
97 m_menu->setActionStateParser(this);
99 m_cachedState = m_menu->get(0, "actionState").toMap();
101 m_menu->setActionStateParser(oldParser);
102 } else {
103 m_cachedState.clear();
104 }
105 Q_EMIT updated();
109bool RootActionState::isValid() const
111 return !m_menu.isNull() && m_menu->rowCount() > 0;
114QString RootActionState::label() const
116 if (!isValid()) return QString();
118 return m_cachedState.value("label", QVariant::fromValue(QString())).toString();
121QString RootActionState::icon() const
123 if (!isValid()) return QString();
125 return m_cachedState.value("icon", QVariant::fromValue(QString())).toString();
128QString RootActionState::accessibleName() const
130 if (!isValid()) return QString();
132 return m_cachedState.value("accessible-name", QVariant::fromValue(QString())).toString();
135bool RootActionState::isVisible() const
137 if (!isValid()) return false;
139 return m_cachedState.value("visible", QVariant::fromValue(true)).toBool();
142static QString iconUri(GIcon *icon)
144 QString uri;
146 if (G_IS_THEMED_ICON (icon)) {
148 const gchar* const* iconNames = g_themed_icon_get_names (G_THEMED_ICON (icon));
149 guint index = 0;
150 while(iconNames[index] != NULL) {
151 if (QIcon::hasThemeIcon(iconNames[index])) {
152 uri = QString("image://theme/%1").arg(iconNames[index]);
153 break;
154 }
155 index++;
156 }
157 }
158 else if (G_IS_FILE_ICON (icon)) {
159 GFile *file;
161 file = g_file_icon_get_file (G_FILE_ICON (icon));
162 if (g_file_is_native (file)) {
163 gchar *fileuri;
165 fileuri = g_file_get_path (file);
166 uri = QString(fileuri);
168 g_free (fileuri);
169 }
170 }
171 else if (G_IS_BYTES_ICON (icon)) {
172 gsize size;
173 gconstpointer data;
174 gchar *base64;
176 data = g_bytes_get_data (g_bytes_icon_get_bytes (G_BYTES_ICON (icon)), &size);
177 base64 = g_base64_encode ((const guchar *) data, size);
179 uri = QString("data://");
180 uri.append (base64);
182 g_free (base64);
183 }
185 return uri;
188QVariant RootActionState::toQVariant(GVariant* state) const
190 if (!state) {
191 return QVariant();
192 }
194 if (g_variant_is_of_type(state, G_VARIANT_TYPE_VARDICT)) {
195 GVariantIter iter;
196 GVariant *vvalue;
197 gchar *key;
198 QVariantMap qmap;
200 g_variant_iter_init (&iter, state);
201 while (g_variant_iter_loop (&iter, "{sv}", &key, &vvalue))
202 {
203 QString str = QString::fromUtf8(key);
204 if (str == "icon") {
205 // FIXME - should be sending a url.
206 GIcon *icon = g_icon_deserialize (vvalue);
207 if (icon) {
208 qmap.insert(str, iconUri(icon));
209 g_object_unref (icon);
210 }
211 else {
212 qmap.insert(str, QVariant(""));
213 }
214 } else {
215 qmap.insert(str, ActionStateParser::toQVariant(vvalue));
216 }
217 }
219 return QVariant::fromValue(qmap);
221 } else if (g_variant_is_of_type (state, G_VARIANT_TYPE ("(sssb)"))) {
222 QVariantMap qmap;
224 char* label;
225 char* icon;
226 char* accessible_name;
227 gboolean visible;
228 GIcon *gicon;
230 g_variant_get(state, "(sssb)", &label,
231 &icon,
232 &accessible_name,
233 &visible);
235 qmap["label"] = label ? QString::fromUtf8(label) : "";
236 qmap["accessible-name"] = accessible_name ? QString::fromUtf8(accessible_name) : "";
237 qmap["visible"] = visible;
239 gicon = g_icon_new_for_string (icon, NULL);
240 if (gicon) {
241 qmap["icon"] = iconUri(gicon);
242 g_object_unref (gicon);
243 }
245 if (label) g_free(label);
246 if (icon) g_free(icon);
247 if (accessible_name) g_free(accessible_name);
249 return QVariant::fromValue(qmap);
250 }
251 return ActionStateParser::toQVariant(state);