@@ -0,0 +1,261 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+#include <gio/gio.h>
17+#include <stdio.h>
18+#include <stdlib.h>
19+
20+G_DEFINE_QUARK (SLIDER_VALUE, slider_value)
21+
22+typedef struct
23+{
24+ GSimpleActionGroup *actions;
25+ GMenu *menu;
26+
27+ guint actions_export_id;
28+ guint menu_export_id;
29+ int action_delay;
30+} IndicatorTestService;
31+
32+static void
33+bus_acquired (GDBusConnection *connection,
34+ const gchar *name,
35+ gpointer user_data)
36+{
37+ (void) name;
38+ IndicatorTestService *indicator = user_data;
39+ GError *error = NULL;
40+
41+ indicator->actions_export_id = g_dbus_connection_export_action_group (connection,
42+ "/com/canonical/indicator/mock",
43+ G_ACTION_GROUP (indicator->actions),
44+ &error);
45+ if (indicator->actions_export_id == 0)
46+ {
47+ g_warning ("cannot export action group: %s", error->message);
48+ g_error_free (error);
49+ return;
50+ }
51+
52+ indicator->menu_export_id = g_dbus_connection_export_menu_model (connection,
53+ "/com/canonical/indicator/mock/desktop",
54+ G_MENU_MODEL (indicator->menu),
55+ &error);
56+ if (indicator->menu_export_id == 0)
57+ {
58+ g_warning ("cannot export menu: %s", error->message);
59+ g_error_free (error);
60+ return;
61+ }
62+}
63+
64+static void
65+name_lost (GDBusConnection *connection,
66+ const gchar *name,
67+ gpointer user_data)
68+{
69+ (void) name;
70+ IndicatorTestService *indicator = user_data;
71+
72+ if (indicator->actions_export_id)
73+ g_dbus_connection_unexport_action_group (connection, indicator->actions_export_id);
74+
75+ if (indicator->menu_export_id)
76+ g_dbus_connection_unexport_menu_model (connection, indicator->menu_export_id);
77+}
78+
79+static void
80+activate_show (GSimpleAction *action,
81+ GVariant *parameter,
82+ gpointer user_data)
83+{
84+ (void) action;
85+ (void) parameter;
86+ (void) user_data;
87+ g_message ("showing");
88+}
89+
90+static gboolean
91+actual_switch (gpointer user_data)
92+{
93+ GSimpleAction *action = user_data;
94+
95+ GVariant* v = g_action_get_state(G_ACTION(action));
96+ gboolean state = g_variant_get_boolean (v);
97+ GVariant *new_state = g_variant_new_boolean (state == TRUE ? FALSE : TRUE);
98+
99+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
100+
101+ g_variant_unref (v);
102+ g_message ("switching");
103+ return FALSE;
104+}
105+
106+static void
107+activate_switch (GSimpleAction *action,
108+ GVariant *parameter,
109+ gpointer user_data)
110+{
111+ (void) action;
112+ (void) parameter;
113+
114+ IndicatorTestService *indicator = user_data;
115+
116+ g_timeout_add(indicator->action_delay, actual_switch, action);
117+ g_message ("switch delay");
118+}
119+
120+static gboolean
121+actual_slide (gpointer user_data)
122+{
123+ GSimpleAction *action = user_data;
124+
125+ GVariant* new_state = g_object_get_qdata (G_OBJECT (action), slider_value_quark ());
126+
127+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
128+
129+ g_message ("switching");
130+ return FALSE;
131+}
132+
133+void change_slider (GSimpleAction *action,
134+ GVariant *value,
135+ gpointer user_data)
136+{
137+ IndicatorTestService *indicator = user_data;
138+
139+ g_object_set_qdata (G_OBJECT (action), slider_value_quark (), g_variant_ref(value));
140+
141+ g_timeout_add(indicator->action_delay, actual_slide, action);
142+ g_message ("slide delay %.03f", g_variant_get_double(value));
143+}
144+
145+int
146+main (int argc, char **argv)
147+{
148+ IndicatorTestService indicator = { 0 };
149+ indicator.action_delay = -1;
150+ GMenuItem *item;
151+ GMenu *submenu;
152+ GActionEntry entries[] = {
153+ { "_header", NULL, NULL, "{'title': <'Test'>,"
154+ " 'label': <'Test'>,"
155+ " 'visible': <true>,"
156+ " 'accessible-desc': <'Test indicator'> }", NULL },
157+ { "action.show", activate_show, NULL, NULL, NULL },
158+ { "action.switch", activate_switch, NULL, "true", NULL },
159+ { "action.checkbox", activate_switch, NULL, "true", NULL },
160+ { "action.accessPoint", activate_switch, NULL, "false", NULL },
161+ { "action.slider", NULL, NULL, "0.5", change_slider }
162+ };
163+ GMainLoop *loop;
164+
165+ int help = 0;
166+ if (argc > 1)
167+ {
168+ int i;
169+ for (i = 1; i < argc; i++) {
170+ const char *arg = argv[i];
171+
172+ if (arg[0] == '-') {
173+ switch (arg[1])
174+ {
175+ case 't':
176+ {
177+ arg += 2;
178+ if (!arg[0] && i < argc-1) {
179+ i++;
180+ int delay = -1;
181+
182+ if (sscanf(argv[i], "%d", &delay) == 1) {
183+ indicator.action_delay = delay;
184+ } else {
185+ printf("Invalid action delay value: %s\n", argv[i]);
186+ help = 1;
187+ }
188+ } else {
189+ printf("Invalid action delay value: %s\n", argv[i]);
190+ help = 1;
191+ }
192+ break;
193+ }
194+ case 'h':
195+ help = 1;
196+ break;
197+ }
198+ }
199+ }
200+ }
201+
202+ if (help) {
203+ printf("Usage: %s [<options>]\n"
204+ " -t DELAY Action activation delay\n"
205+ " -h Show this help text\n"
206+ , argv[0]);
207+ return 0;
208+ }
209+
210+ indicator.actions = g_simple_action_group_new ();
211+ g_action_map_add_action_entries (G_ACTION_MAP (indicator.actions), entries, G_N_ELEMENTS (entries), &indicator);
212+
213+ submenu = g_menu_new ();
214+ g_menu_append (submenu, "Show", "indicator.action.show");
215+
216+ // Switch
217+ item = g_menu_item_new("Switch", "indicator.action.switch");
218+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.switch");
219+ g_menu_append_item(submenu, item);
220+
221+ // Checkbox
222+ item = g_menu_item_new("Checkbox", "indicator.action.checkbox");
223+ g_menu_append_item(submenu, item);
224+
225+ // Slider
226+ item = g_menu_item_new("Slider", "indicator.action.slider");
227+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.slider");
228+ g_menu_append_item(submenu, item);
229+
230+ // Access Point
231+ item = g_menu_item_new("Access Point", "indicator.action.accessPoint");
232+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "unity.widgets.systemsettings.tablet.accesspoint");
233+ g_menu_append_item(submenu, item);
234+
235+
236+ item = g_menu_item_new (NULL, "indicator._header");
237+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.root");
238+ g_menu_item_set_submenu (item, G_MENU_MODEL (submenu));
239+ indicator.menu = g_menu_new ();
240+ g_menu_append_item (indicator.menu, item);
241+
242+ g_bus_own_name (G_BUS_TYPE_SESSION,
243+ "com.canonical.indicator.mock",
244+ G_BUS_NAME_OWNER_FLAGS_NONE,
245+ bus_acquired,
246+ NULL,
247+ name_lost,
248+ &indicator,
249+ NULL);
250+
251+ loop = g_main_loop_new (NULL, FALSE);
252+ g_main_loop_run (loop);
253+
254+ g_object_unref (submenu);
255+ g_object_unref (item);
256+ g_object_unref (indicator.actions);
257+ g_object_unref (indicator.menu);
258+ g_object_unref (loop);
259+
260+ return 1;
261+}