~larsu/indicator-messages/dont-use-deprecated-function

54 by Ted Gould
Adding in license headers, GPL v3
1
/*
2
An indicator to show information that is in messaging applications
3
that the user is using.
4
272.3.1 by Charles Kerr
add lars as co-author of app-section
5
Copyright 2012 Canonical Ltd.
54 by Ted Gould
Adding in license headers, GPL v3
6
7
Authors:
272.3.1 by Charles Kerr
add lars as co-author of app-section
8
    Lars Uebernickel <lars.uebernickel@canonical.com>
54 by Ted Gould
Adding in license headers, GPL v3
9
    Ted Gould <ted@canonical.com>
10
11
This program is free software: you can redistribute it and/or modify it 
12
under the terms of the GNU General Public License version 3, as published 
13
by the Free Software Foundation.
14
15
This program is distributed in the hope that it will be useful, but 
16
WITHOUT ANY WARRANTY; without even the implied warranties of 
17
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
18
PURPOSE.  See the GNU General Public License for more details.
19
20
You should have received a copy of the GNU General Public License along 
21
with this program.  If not, see <http://www.gnu.org/licenses/>.
22
*/
23
49 by Ted Gould
Adding in an application menu item to start building those
24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
338.1.2 by Marco Trevisan (Treviño)
AppSection: use the GAppLaunchContext with event timestamp when launching an app
28
#include <gdk/gdk.h>
49 by Ted Gould
Adding in an application menu item to start building those
29
#include <glib/gi18n.h>
61 by Ted Gould
Adding in desktop file support, which required configure changes to get the right headers.
30
#include <gio/gdesktopappinfo.h>
272.2.10 by Lars Uebernickel
Port to gmenu, act I
31
#include <gio/gio.h>
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
32
#include <libindicator/indicator-desktop-shortcuts.h>
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
33
#include "app-section.h"
123.4.24 by Ted Gould
Defining the max number of indicators and telling the server about it.
34
#include "dbus-data.h"
272.2.63 by Lars Uebernickel
messages-service: move gmenu utility functions into gmenuutils.[ch]
35
#include "gmenuutils.h"
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
36
#include "gactionmuxer.h"
49 by Ted Gould
Adding in an application menu item to start building those
37
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
38
struct _AppSectionPrivate
49 by Ted Gould
Adding in an application menu item to start building those
39
{
272.2.7 by Lars Uebernickel
app-menu-item: remove another unneeded priv variable
40
	GDesktopAppInfo * appinfo;
308.1.1 by Lars Uebernickel
Watch desktop files for changes
41
	GFileMonitor *desktop_file_monitor;
162.2.3 by Ted Gould
Fleshing out menu_cb, lots of avenues for expantion in other directions now.
42
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
43
	IndicatorDesktopShortcuts * ids;
272.2.10 by Lars Uebernickel
Port to gmenu, act I
44
45
	GMenu *menu;
272.2.88 by Lars Uebernickel
app-section: rename remote_menu to source_menu
46
	GMenuModel *source_menu;
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
47
272.2.10 by Lars Uebernickel
Port to gmenu, act I
48
	GSimpleActionGroup *static_shortcuts;
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
49
	GActionGroup *source_actions;
50
	GActionMuxer *muxer;
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
51
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
52
	gboolean draws_attention;
272.2.76 by Lars Uebernickel
Only show chat section when necessary
53
	gboolean uses_chat_status;
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
54
	gchar *chat_status;
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
55
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
56
	guint name_watch_id;
49 by Ted Gould
Adding in an application menu item to start building those
57
};
58
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
59
enum {
60
	PROP_0,
61
	PROP_APPINFO,
272.2.29 by Lars Uebernickel
Reexport application actions
62
	PROP_ACTIONS,
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
63
	PROP_DRAWS_ATTENTION,
272.2.76 by Lars Uebernickel
Only show chat section when necessary
64
	PROP_USES_CHAT_STATUS,
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
65
	PROP_CHAT_STATUS,
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
66
	NUM_PROPERTIES
67
};
68
69
static GParamSpec *properties[NUM_PROPERTIES];
308.1.3 by Lars Uebernickel
app-section.c: make destroy_signal static
70
static guint destroy_signal;
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
71
49 by Ted Gould
Adding in an application menu item to start building those
72
/* Prototypes */
272.2.23 by Lars Uebernickel
app-section: fix indentation
73
static void app_section_class_init   (AppSectionClass *klass);
74
static void app_section_init         (AppSection *self);
75
static void app_section_get_property (GObject    *object,
76
				      guint       property_id,
77
				      GValue     *value,
78
				      GParamSpec *pspec);
79
static void app_section_set_property (GObject      *object,
80
				      guint         property_id,
81
				      const GValue *value,
82
				      GParamSpec   *pspec);
83
static void app_section_dispose      (GObject *object);
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
84
static void app_section_finalize     (GObject *object);
272.2.23 by Lars Uebernickel
app-section: fix indentation
85
static void activate_cb              (GSimpleAction *action,
86
				      GVariant *param,
87
				      gpointer userdata);
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
88
static void launch_action_change_state (GSimpleAction *action,
89
					GVariant      *value,
90
					gpointer       user_data);
272.2.23 by Lars Uebernickel
app-section: fix indentation
91
static void app_section_set_app_info (AppSection *self,
92
				      GDesktopAppInfo *appinfo);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
93
static gboolean any_action_draws_attention	(GActionGroup *group,
94
						 const gchar *ignored_action);
95
static void	action_added			(GActionGroup *group,
96
						 const gchar *action_name,
97
						 gpointer user_data);
98
static void	action_state_changed		(GActionGroup *group,
99
						 const gchar *action_name,
100
						 GVariant *value,
101
						 gpointer user_data);
102
static void	action_removed			(GActionGroup *group,
103
						 const gchar *action_name,
104
						 gpointer user_data);
272.2.67 by Lars Uebernickel
Make "Clear" work again
105
static gboolean	action_draws_attention		(GVariant *state);
308.1.1 by Lars Uebernickel
Watch desktop files for changes
106
static void	desktop_file_changed_cb		(GFileMonitor      *monitor,
107
						 GFile             *file,
108
						 GFile             *other_file,
109
						 GFileMonitorEvent  event,
110
						 gpointer           user_data);
49 by Ted Gould
Adding in an application menu item to start building those
111
123.4.40 by Ted Gould
Setting up the listener signal to make it so that we know when the count changes. Using the property call back and just calling that function.
112
/* GObject Boilerplate */
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
113
G_DEFINE_TYPE (AppSection, app_section, G_TYPE_OBJECT);
49 by Ted Gould
Adding in an application menu item to start building those
114
115
static void
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
116
app_section_class_init (AppSectionClass *klass)
49 by Ted Gould
Adding in an application menu item to start building those
117
{
118
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
119
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
120
	g_type_class_add_private (klass, sizeof (AppSectionPrivate));
49 by Ted Gould
Adding in an application menu item to start building those
121
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
122
	object_class->get_property = app_section_get_property;
123
	object_class->set_property = app_section_set_property;
124
	object_class->dispose = app_section_dispose;
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
125
	object_class->finalize = app_section_finalize;
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
126
127
	properties[PROP_APPINFO] = g_param_spec_object ("app-info",
128
							"AppInfo",
129
							"The GAppInfo for the app that this menu represents",
130
							G_TYPE_APP_INFO,
131
							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
132
272.2.29 by Lars Uebernickel
Reexport application actions
133
	properties[PROP_ACTIONS] = g_param_spec_object ("actions",
134
							"Actions",
135
							"The actions exported by this application",
136
							G_TYPE_ACTION_GROUP,
137
							G_PARAM_READABLE);
138
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
139
	properties[PROP_DRAWS_ATTENTION] = g_param_spec_boolean ("draws-attention",
140
								 "Draws attention",
141
								 "Whether the section currently draws attention",
142
								 FALSE,
143
								 G_PARAM_READABLE);
144
272.2.76 by Lars Uebernickel
Only show chat section when necessary
145
	properties[PROP_USES_CHAT_STATUS] = g_param_spec_boolean ("uses-chat-status",
146
								  "Uses chat status",
147
								  "Whether the section uses the global chat status",
148
								  FALSE,
149
								  G_PARAM_READABLE);
150
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
151
	properties[PROP_CHAT_STATUS] = g_param_spec_string ("chat-status",
152
							    "Chat status",
153
							    "Current chat status of the application",
154
							    NULL,
155
							    G_PARAM_READWRITE |
156
							    G_PARAM_STATIC_STRINGS);
157
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
158
	g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
308.1.1 by Lars Uebernickel
Watch desktop files for changes
159
160
	destroy_signal = g_signal_new ("destroy",
161
				       APP_SECTION_TYPE,
162
				       G_SIGNAL_RUN_FIRST,
163
				       0,
164
				       NULL, NULL,
165
				       g_cclosure_marshal_VOID__VOID,
166
				       G_TYPE_NONE, 0);
49 by Ted Gould
Adding in an application menu item to start building those
167
}
168
169
static void
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
170
app_section_init (AppSection *self)
49 by Ted Gould
Adding in an application menu item to start building those
171
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
172
	AppSectionPrivate *priv;
173
174
	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
175
						  APP_SECTION_TYPE,
176
						  AppSectionPrivate);
177
	priv = self->priv;
49 by Ted Gould
Adding in an application menu item to start building those
178
61 by Ted Gould
Adding in desktop file support, which required configure changes to get the right headers.
179
	priv->appinfo = NULL;
49 by Ted Gould
Adding in an application menu item to start building those
180
272.2.10 by Lars Uebernickel
Port to gmenu, act I
181
	priv->menu = g_menu_new ();
182
	priv->static_shortcuts = g_simple_action_group_new ();
183
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
184
	priv->muxer = g_action_muxer_new ();
185
	g_action_muxer_insert (priv->muxer, NULL, G_ACTION_GROUP (priv->static_shortcuts));
186
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
187
	priv->draws_attention = FALSE;
188
272.2.10 by Lars Uebernickel
Port to gmenu, act I
189
	return;
190
}
191
49 by Ted Gould
Adding in an application menu item to start building those
192
static void
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
193
app_section_get_property (GObject    *object,
272.2.23 by Lars Uebernickel
app-section: fix indentation
194
			  guint       property_id,
195
			  GValue     *value,
196
			  GParamSpec *pspec)
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
197
{
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
198
	AppSection *self = APP_SECTION (object);
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
199
200
	switch (property_id)
201
	{
202
	case PROP_APPINFO:
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
203
		g_value_set_object (value, app_section_get_app_info (self));
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
204
		break;
205
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
206
	case PROP_DRAWS_ATTENTION:
207
		g_value_set_boolean (value, app_section_get_draws_attention (self));
208
		break;
209
272.2.76 by Lars Uebernickel
Only show chat section when necessary
210
	case PROP_USES_CHAT_STATUS:
211
		g_value_set_boolean (value, app_section_get_uses_chat_status (self));
212
		break;
213
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
214
	case PROP_CHAT_STATUS:
215
		g_value_set_string (value, app_section_get_status (self));
216
		break;
217
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
218
	default:
219
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
220
	}
221
}
222
223
static void
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
224
app_section_set_property (GObject      *object,
272.2.23 by Lars Uebernickel
app-section: fix indentation
225
			  guint         property_id,
226
			  const GValue *value,
227
			  GParamSpec   *pspec)
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
228
{
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
229
	AppSection *self = APP_SECTION (object);
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
230
231
	switch (property_id)
232
	{
233
	case PROP_APPINFO:
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
234
		app_section_set_app_info (self, g_value_get_object (value));
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
235
		break;
236
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
237
	case PROP_CHAT_STATUS:
238
		app_section_set_status (self, g_value_get_string (value));
239
		break;
240
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
241
	default:
242
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
243
	}
244
}
308.1.1 by Lars Uebernickel
Watch desktop files for changes
245
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
246
static void
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
247
app_section_dispose (GObject *object)
49 by Ted Gould
Adding in an application menu item to start building those
248
{
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
249
	AppSection * self = APP_SECTION(object);
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
250
	AppSectionPrivate * priv = self->priv;
78 by Ted Gould
Disconnecting our signals properly, avoids a crash
251
308.1.1 by Lars Uebernickel
Watch desktop files for changes
252
	if (priv->desktop_file_monitor) {
253
		g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);
254
		g_clear_object (&priv->desktop_file_monitor);
255
	}
256
272.2.10 by Lars Uebernickel
Port to gmenu, act I
257
	g_clear_object (&priv->menu);
258
	g_clear_object (&priv->static_shortcuts);
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
259
272.2.25 by Lars Uebernickel
Listen to menus exported by applications
260
	if (priv->name_watch_id) {
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
261
		g_bus_unwatch_name (priv->name_watch_id);
262
		priv->name_watch_id = 0;
263
	}
264
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
265
	if (priv->source_actions) {
266
		g_action_muxer_remove  (priv->muxer, "source");
267
		g_object_disconnect (priv->source_actions,
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
268
				     "any_signal::action-added", action_added, self,
269
				     "any_signal::action-state-changed", action_state_changed, self,
270
				     "any_signal::action-removed", action_removed, self,
271
				     NULL);
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
272
		g_clear_object (&priv->source_actions);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
273
	}
274
272.3.9 by Charles Kerr
in app-section.c's dispose(), clear the muxer object
275
	g_clear_object (&priv->muxer);
276
272.2.88 by Lars Uebernickel
app-section: rename remote_menu to source_menu
277
	g_clear_object (&priv->source_menu);
272.3.2 by Charles Kerr
in app-section.c's dispose(), use g_clear_object() for priv.ids and priv.keyfile
278
	g_clear_object (&priv->ids);
279
	g_clear_object (&priv->appinfo);
210.1.3 by Ted Gould
Create the keyfile for the application icon as well
280
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
281
	G_OBJECT_CLASS (app_section_parent_class)->dispose (object);
107.2.4 by Ted Gould
Moving signal disconnecting and unref to the dispose function instead of finalize. Fix by Cody Russell on bug 362124.
282
}
283
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
284
static void
285
app_section_finalize (GObject *object)
286
{
287
	AppSection * self = APP_SECTION(object);
288
289
	g_free (self->priv->chat_status);
290
291
	G_OBJECT_CLASS (app_section_parent_class)->dispose (object);
292
}
293
340.1.2 by Marco Trevisan (Treviño)
AppSection: use LaunchContext to exec shortcut nicks
294
static GAppLaunchContext *
295
get_launch_context (guint32 timestamp)
296
{
297
	GdkDisplay *display = gdk_display_get_default();
298
	GdkAppLaunchContext *launch_context = gdk_display_get_app_launch_context (display);
299
300
	gdk_app_launch_context_set_timestamp (launch_context, timestamp);
301
302
	return G_APP_LAUNCH_CONTEXT (launch_context);
303
}
304
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
305
/* Respond to one of the shortcuts getting clicked on. */
306
static void
272.2.10 by Lars Uebernickel
Port to gmenu, act I
307
nick_activate_cb (GSimpleAction *action,
308
		  GVariant *param,
309
		  gpointer userdata)
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
310
{
272.2.10 by Lars Uebernickel
Port to gmenu, act I
311
	const gchar * nick = g_action_get_name (G_ACTION (action));
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
312
	AppSection * mi = APP_SECTION (userdata);
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
313
	AppSectionPrivate * priv = mi->priv;
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
314
315
	g_return_if_fail(priv->ids != NULL);
316
340.1.2 by Marco Trevisan (Treviño)
AppSection: use LaunchContext to exec shortcut nicks
317
	GAppLaunchContext *context = get_launch_context (g_variant_get_uint32 (param));
318
319
	if (!indicator_desktop_shortcuts_nick_exec_with_context(priv->ids, nick, context)) {
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
320
		g_warning("Unable to execute nick '%s' for desktop file '%s'",
321
			  nick, g_desktop_app_info_get_filename (priv->appinfo));
322
	}
340.1.2 by Marco Trevisan (Treviño)
AppSection: use LaunchContext to exec shortcut nicks
323
324
	g_object_unref (context);
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
325
}
326
272.2.8 by Lars Uebernickel
Allow creating an app menu item without associated indicate server
327
static void
272.2.76 by Lars Uebernickel
Only show chat section when necessary
328
keyfile_loaded (GObject *source_object,
329
		GAsyncResult *result,
272.3.3 by Charles Kerr
add sanity checks to args passed in the public API
330
		gpointer user_data)
272.2.76 by Lars Uebernickel
Only show chat section when necessary
331
{
332
	AppSection *self = user_data;
333
	gchar *contents;
334
	gsize length;
335
	GKeyFile *keyfile;
336
	GError *error = NULL;
337
338
	if (!g_file_load_contents_finish (G_FILE (source_object), result,
339
					 &contents, &length, NULL, &error)) {
340
		g_warning ("could not read key file: %s", error->message);
341
		g_error_free (error);
342
		return;
343
	}
344
345
	keyfile = g_key_file_new ();
346
	if (!g_key_file_load_from_data (keyfile, contents, length, 0, &error)) {
347
		g_warning ("could not read key file: %s", error->message);
348
		g_error_free (error);
349
		goto out;
350
	}
351
352
	self->priv->uses_chat_status = g_key_file_get_boolean (keyfile,
353
							       G_KEY_FILE_DESKTOP_GROUP,
272.2.78 by Lars Uebernickel
X-MessagingMenu-UsesChatStatus --> X-MessagingMenu-UsesChatSection
354
							       "X-MessagingMenu-UsesChatSection",
272.2.76 by Lars Uebernickel
Only show chat section when necessary
355
							       &error);
308.1.1 by Lars Uebernickel
Watch desktop files for changes
356
357
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
358
272.2.76 by Lars Uebernickel
Only show chat section when necessary
359
	if (error) {
360
		if (error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
361
			g_warning ("could not read X-MessagingMenu-UsesChatSection: %s",
362
				   error->message);
363
		}
364
		g_error_free (error);
365
		goto out;
366
	}
367
368
out:
369
	g_key_file_free (keyfile);
370
	g_free (contents);
371
}
372
373
static void
308.1.1 by Lars Uebernickel
Watch desktop files for changes
374
g_menu_clear (GMenu *menu)
375
{
376
	gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu));
377
378
	while (n_items--)
379
		g_menu_remove (menu, 0);
380
}
381
382
static void
383
g_simple_action_group_clear (GSimpleActionGroup *group)
384
{
385
	gchar **actions;
386
	gchar **it;
387
388
	actions = g_action_group_list_actions (G_ACTION_GROUP (group));
389
	for (it = actions; *it; it++)
390
		g_simple_action_group_remove (group, *it);
391
392
	g_strfreev (actions);
393
}
394
395
static void
396
app_section_update_menu (AppSection *self)
272.2.8 by Lars Uebernickel
Allow creating an app menu item without associated indicate server
397
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
398
	AppSectionPrivate *priv = self->priv;
272.2.10 by Lars Uebernickel
Port to gmenu, act I
399
	GSimpleAction *launch;
272.2.76 by Lars Uebernickel
Only show chat section when necessary
400
	GFile *keyfile;
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
401
	GMenuItem *item;
272.2.95 by Lars Uebernickel
Show icons in application and source menu items
402
	gchar *iconstr;
308.1.1 by Lars Uebernickel
Watch desktop files for changes
403
	gboolean is_running;
404
405
	g_menu_clear (priv->menu);
406
	g_simple_action_group_clear (priv->static_shortcuts);
407
408
	is_running = priv->name_watch_id > 0;
338.1.2 by Marco Trevisan (Treviño)
AppSection: use the GAppLaunchContext with event timestamp when launching an app
409
	launch = g_simple_action_new_stateful ("launch", G_VARIANT_TYPE_UINT32, g_variant_new_boolean (is_running));
272.2.10 by Lars Uebernickel
Port to gmenu, act I
410
	g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self);
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
411
	g_signal_connect (launch, "change-state", G_CALLBACK (launch_action_change_state), self);
272.2.10 by Lars Uebernickel
Port to gmenu, act I
412
	g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch));
413
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
414
	item = g_menu_item_new (g_app_info_get_name (G_APP_INFO (priv->appinfo)), "launch");
415
	g_menu_item_set_attribute (item, "x-canonical-type", "s", "ImAppMenuItem");
272.2.95 by Lars Uebernickel
Show icons in application and source menu items
416
	iconstr = g_icon_to_string (g_app_info_get_icon (G_APP_INFO (priv->appinfo)));
417
	g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr);
418
	g_free (iconstr);
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
419
420
	g_menu_append_item (priv->menu, item);
421
	g_object_unref (item);
272.2.10 by Lars Uebernickel
Port to gmenu, act I
422
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
423
	/* Start to build static shortcuts */
424
	priv->ids = indicator_desktop_shortcuts_new(g_desktop_app_info_get_filename (priv->appinfo), "Messaging Menu");
425
	const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->ids);
426
	gint i;
427
	for (i = 0; nicks[i] != NULL; i++) {
272.2.10 by Lars Uebernickel
Port to gmenu, act I
428
		gchar *name;
429
		GSimpleAction *action;
293.1.4 by Lars Uebernickel
IdoMenuItem: don't try to set state on stateless actions
430
		GMenuItem *item;
272.2.10 by Lars Uebernickel
Port to gmenu, act I
431
432
		name = indicator_desktop_shortcuts_nick_get_name(priv->ids, nicks[i]);
433
340.1.2 by Marco Trevisan (Treviño)
AppSection: use LaunchContext to exec shortcut nicks
434
		action = g_simple_action_new (nicks[i], G_VARIANT_TYPE_UINT32);
272.2.10 by Lars Uebernickel
Port to gmenu, act I
435
		g_signal_connect(action, "activate", G_CALLBACK (nick_activate_cb), self);
436
		g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (action));
272.3.10 by Charles Kerr
in app-section's app_section_set_app_info(), don't leak the nicks' actions
437
		g_object_unref (action);
272.2.10 by Lars Uebernickel
Port to gmenu, act I
438
293.1.4 by Lars Uebernickel
IdoMenuItem: don't try to set state on stateless actions
439
		item = g_menu_item_new (name, nicks[i]);
440
		g_menu_item_set_attribute (item, "x-canonical-type", "s", "IdoMenuItem");
441
		g_menu_item_set_attribute (item, "x-canonical-icon", "s", ""); /* empty to get indentation */
442
		g_menu_append_item (priv->menu, item);
272.2.10 by Lars Uebernickel
Port to gmenu, act I
443
293.1.4 by Lars Uebernickel
IdoMenuItem: don't try to set state on stateless actions
444
		g_object_unref (item);
272.2.9 by Lars Uebernickel
Merge launcher- and appmenuitems
445
		g_free(name);
446
	}
447
272.2.76 by Lars Uebernickel
Only show chat section when necessary
448
	keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));
449
	g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);
308.1.1 by Lars Uebernickel
Watch desktop files for changes
450
451
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
452
272.2.76 by Lars Uebernickel
Only show chat section when necessary
453
	g_object_unref (keyfile);
308.1.1 by Lars Uebernickel
Watch desktop files for changes
454
	g_object_unref (launch);
455
}
456
457
static void
458
desktop_file_changed_cb (GFileMonitor      *monitor,
459
			 GFile             *file,
460
			 GFile             *other_file,
461
			 GFileMonitorEvent  event,
462
			 gpointer           user_data)
463
{
464
	AppSection *self = user_data;
465
466
	if (event == G_FILE_MONITOR_EVENT_CHANGED) {
467
		app_section_update_menu (self);
468
	}
469
	else if (event == G_FILE_MONITOR_EVENT_DELETED ||
470
		 event == G_FILE_MONITOR_EVENT_UNMOUNTED) {
471
		g_signal_emit (self, destroy_signal, 0);
472
	}
473
}
474
475
static void
476
app_section_set_app_info (AppSection *self,
477
			  GDesktopAppInfo *appinfo)
478
{
479
	AppSectionPrivate *priv = self->priv;
480
	GFile *desktop_file;
481
	GError *error = NULL;
482
483
	g_return_if_fail (priv->appinfo == NULL);
484
	g_return_if_fail (priv->desktop_file_monitor == NULL);
485
486
	if (appinfo == NULL) {
487
		g_warning ("appinfo must not be NULL");
488
		return;
489
	}
490
491
	priv->appinfo = g_object_ref (appinfo);
492
493
	desktop_file = g_file_new_for_path (g_desktop_app_info_get_filename (appinfo));
494
	priv->desktop_file_monitor = g_file_monitor (desktop_file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
495
	if (priv->desktop_file_monitor == NULL) {
496
		g_warning ("unable to watch desktop file: %s", error->message);
497
		g_error_free (error);
498
	}
499
	g_signal_connect (priv->desktop_file_monitor, "changed",
500
			  G_CALLBACK (desktop_file_changed_cb), self);
272.2.76 by Lars Uebernickel
Only show chat section when necessary
501
272.2.29 by Lars Uebernickel
Reexport application actions
502
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]);
308.1.1 by Lars Uebernickel
Watch desktop files for changes
503
504
	app_section_update_menu (self);
505
506
	g_object_unref (desktop_file);
272.2.8 by Lars Uebernickel
Allow creating an app menu item without associated indicate server
507
}
508
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
509
AppSection *
510
app_section_new (GDesktopAppInfo *appinfo)
272.2.5 by Lars Uebernickel
Allow creating AppMenuItems without initial listener / server
511
{
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
512
	return g_object_new (APP_SECTION_TYPE,
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
513
			     "app-info", appinfo,
514
			     NULL);
272.2.5 by Lars Uebernickel
Allow creating AppMenuItems without initial listener / server
515
}
516
272.2.10 by Lars Uebernickel
Port to gmenu, act I
517
static void
518
activate_cb (GSimpleAction *action,
519
	     GVariant *param,
520
	     gpointer userdata)
521
{
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
522
	AppSection * mi = APP_SECTION (userdata);
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
523
	AppSectionPrivate * priv = mi->priv;
272.2.10 by Lars Uebernickel
Port to gmenu, act I
524
	GError *error = NULL;
340.1.2 by Marco Trevisan (Treviño)
AppSection: use LaunchContext to exec shortcut nicks
525
	GAppLaunchContext *launch_context = get_launch_context (g_variant_get_uint32 (param));
526
527
	if (!g_app_info_launch (G_APP_INFO (priv->appinfo), NULL, launch_context, &error)) {
272.3.11 by Charles Kerr
in app-section.c's activate_cb(), don't leak the GError if we can't launch
528
		g_warning("Unable to execute application for desktop file '%s': %s",
529
			  g_desktop_app_info_get_filename (priv->appinfo),
530
			  error->message);
531
		g_error_free (error);
272.2.10 by Lars Uebernickel
Port to gmenu, act I
532
	}
338.1.2 by Marco Trevisan (Treviño)
AppSection: use the GAppLaunchContext with event timestamp when launching an app
533
534
	g_object_unref (launch_context);
49 by Ted Gould
Adding in an application menu item to start building those
535
}
73 by Ted Gould
Adding in an unread count variable, and then a signal to show it chagned. Also, watching for the indicators on this server to make sure it stays correct.
536
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
537
static void
538
launch_action_change_state (GSimpleAction *action,
539
			    GVariant      *value,
540
			    gpointer       user_data)
541
{
542
	g_simple_action_set_state (action, value);
543
}
544
81 by Ted Gould
Adding functions to make it so that we can get signaled on name changes and also query them in app-menu-items
545
const gchar *
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
546
app_section_get_desktop (AppSection * self)
123.1.20 by Ted Gould
Big commit. Trying to check for eclipses, but first both objects needed to track their desktop file paths. So I had to add that little nugget in as well.
547
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
548
	AppSectionPrivate * priv = self->priv;
272.2.8 by Lars Uebernickel
Allow creating an app menu item without associated indicate server
549
	if (priv->appinfo)
550
		return g_desktop_app_info_get_filename (priv->appinfo);
551
	else
552
		return NULL;
123.1.20 by Ted Gould
Big commit. Trying to check for eclipses, but first both objects needed to track their desktop file paths. So I had to add that little nugget in as well.
553
}
162.2.2 by Ted Gould
Adding API for getting items
554
272.2.29 by Lars Uebernickel
Reexport application actions
555
GActionGroup *
556
app_section_get_actions (AppSection *self)
557
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
558
	AppSectionPrivate * priv = self->priv;
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
559
	return G_ACTION_GROUP (priv->muxer);
272.2.29 by Lars Uebernickel
Reexport application actions
560
}
561
272.2.10 by Lars Uebernickel
Port to gmenu, act I
562
GMenuModel *
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
563
app_section_get_menu (AppSection *self)
162.2.2 by Ted Gould
Adding API for getting items
564
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
565
	AppSectionPrivate * priv = self->priv;
272.2.10 by Lars Uebernickel
Port to gmenu, act I
566
	return G_MENU_MODEL (priv->menu);
162.2.2 by Ted Gould
Adding API for getting items
567
}
272.2.10 by Lars Uebernickel
Port to gmenu, act I
568
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
569
GAppInfo *
272.2.21 by Lars Uebernickel
Rename AppMenuItem to AppSection
570
app_section_get_app_info (AppSection *self)
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
571
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
572
	AppSectionPrivate * priv = self->priv;
272.2.15 by Lars Uebernickel
appmenuitem: make app-info a construct-only property
573
	return G_APP_INFO (priv->appinfo);
574
}
575
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
576
gboolean
577
app_section_get_draws_attention (AppSection *self)
578
{
579
	AppSectionPrivate * priv = self->priv;
580
	return priv->draws_attention;
581
}
582
272.2.67 by Lars Uebernickel
Make "Clear" work again
583
void
584
app_section_clear_draws_attention (AppSection *self)
585
{
586
	AppSectionPrivate * priv = self->priv;
587
	gchar **action_names;
588
	gchar **it;
589
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
590
	if (priv->source_actions == NULL)
272.2.67 by Lars Uebernickel
Make "Clear" work again
591
		return;
592
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
593
	action_names = g_action_group_list_actions (priv->source_actions);
272.2.67 by Lars Uebernickel
Make "Clear" work again
594
595
	for (it = action_names; *it; it++) {
596
		GVariant *state;
597
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
598
		state = g_action_group_get_action_state (priv->source_actions, *it);
272.2.67 by Lars Uebernickel
Make "Clear" work again
599
		if (!state)
600
			continue;
601
602
		/* clear draws-attention while preserving other state */
603
		if (action_draws_attention (state)) {
604
			guint32 count;
605
			gint64 time;
606
			const gchar *str;
607
			GVariant *new_state;
608
609
			g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL);
610
611
			new_state = g_variant_new ("(uxsb)", count, time, str, FALSE);
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
612
			g_action_group_change_action_state (priv->source_actions, *it, new_state);
272.2.67 by Lars Uebernickel
Make "Clear" work again
613
		}
614
615
		g_variant_unref (state);
616
	}
617
618
	g_strfreev (action_names);
619
}
620
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
621
static void
622
application_vanished (GDBusConnection *bus,
623
		      const gchar *name,
624
		      gpointer user_data)
625
{
626
	AppSection *self = user_data;
627
628
	app_section_unset_object_path (self);
629
}
630
631
/*
632
 * app_section_set_object_path:
633
 * @self: an #AppSection
634
 * @bus: a #GDBusConnection
635
 * @bus_name: the bus name of the application
636
 * @object_path: the object path on which the app exports its actions and menus
637
 *
638
 * Sets the D-Bus object path exported by an instance of the application
639
 * associated with @self.  Actions and menus exported on that path will be
640
 * shown in the section.
641
 */
642
void
643
app_section_set_object_path (AppSection *self,
644
			     GDBusConnection *bus,
645
			     const gchar *bus_name,
646
			     const gchar *object_path)
647
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
648
	AppSectionPrivate *priv = self->priv;
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
649
	GMenuItem *item;
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
650
272.2.54 by Lars Uebernickel
Put launcher and shortcut menu items into the same gmenu section
651
	g_object_freeze_notify (G_OBJECT (self));
652
	app_section_unset_object_path (self);
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
653
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
654
	priv->source_actions = G_ACTION_GROUP (g_dbus_action_group_get (bus, bus_name, object_path));
655
	g_action_muxer_insert (priv->muxer, "source", priv->source_actions);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
656
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
657
	priv->draws_attention = any_action_draws_attention (priv->source_actions, NULL);
658
	g_object_connect (priv->source_actions,
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
659
			  "signal::action-added", action_added, self,
660
			  "signal::action-state-changed", action_state_changed, self,
661
			  "signal::action-removed", action_removed, self,
662
			  NULL);
663
272.2.88 by Lars Uebernickel
app-section: rename remote_menu to source_menu
664
	priv->source_menu = G_MENU_MODEL (g_dbus_menu_model_get (bus, bus_name, object_path));
272.2.25 by Lars Uebernickel
Listen to menus exported by applications
665
272.2.88 by Lars Uebernickel
app-section: rename remote_menu to source_menu
666
	item = g_menu_item_new_section (NULL, priv->source_menu);
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
667
	g_menu_item_set_attribute (item, "action-namespace", "s", "source");
668
	g_menu_append_item (priv->menu, item);
669
	g_object_unref (item);
272.2.33 by Lars Uebernickel
Reexport application menu as a separate section below the shortcuts
670
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
671
	priv->name_watch_id = g_bus_watch_name_on_connection (bus, bus_name, 0,
672
							      NULL, application_vanished,
673
							      self, NULL);
272.2.29 by Lars Uebernickel
Reexport application actions
674
675
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
676
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
272.2.76 by Lars Uebernickel
Only show chat section when necessary
677
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
272.2.54 by Lars Uebernickel
Put launcher and shortcut menu items into the same gmenu section
678
	g_object_thaw_notify (G_OBJECT (self));
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
679
680
	g_action_group_change_action_state (G_ACTION_GROUP (priv->static_shortcuts),
681
					    "launch", g_variant_new_boolean (TRUE));
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
682
}
683
684
/*
685
 * app_section_unset_object_path:
686
 * @self: an #AppSection
687
 *
688
 * Unsets the object path set with app_section_set_object_path().  The section
689
 * will return to only showing application name and static shortcuts in the
690
 * menu.
691
 */
692
void
693
app_section_unset_object_path (AppSection *self)
694
{
272.2.32 by Lars Uebernickel
app-section: replace G_TYPE_INSTANCE_GET_PRIVATE calls with a priv member
695
	AppSectionPrivate *priv = self->priv;
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
696
272.2.26 by Lars Uebernickel
app-section: only call g_bus_unwatch_name if we're watching a name
697
	if (priv->name_watch_id) {
272.2.24 by Lars Uebernickel
Listen to actions exported by applications
698
		g_bus_unwatch_name (priv->name_watch_id);
272.2.26 by Lars Uebernickel
app-section: only call g_bus_unwatch_name if we're watching a name
699
		priv->name_watch_id = 0;
700
	}
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
701
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
702
	if (priv->source_actions) {
703
		g_object_disconnect (priv->source_actions,
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
704
				     "any_signal::action-added", action_added, self,
705
				     "any_signal::action-state-changed", action_state_changed, self,
706
				     "any_signal::action-removed", action_removed, self,
707
				     NULL);
272.2.87 by Lars Uebernickel
Export both static shortcuts also when the app is running
708
		g_clear_object (&priv->source_actions);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
709
	}
272.2.33 by Lars Uebernickel
Reexport application menu as a separate section below the shortcuts
710
272.2.88 by Lars Uebernickel
app-section: rename remote_menu to source_menu
711
	if (priv->source_menu) {
272.2.54 by Lars Uebernickel
Put launcher and shortcut menu items into the same gmenu section
712
		/* the last menu item points is linked to the app's menumodel */
713
		gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (priv->menu));
714
		g_menu_remove (priv->menu, n_items -1);
272.2.88 by Lars Uebernickel
app-section: rename remote_menu to source_menu
715
		g_clear_object (&priv->source_menu);
272.2.33 by Lars Uebernickel
Reexport application menu as a separate section below the shortcuts
716
	}
272.2.29 by Lars Uebernickel
Reexport application actions
717
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
718
	priv->draws_attention = FALSE;
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
719
	g_clear_pointer (&priv->chat_status, g_free);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
720
272.2.29 by Lars Uebernickel
Reexport application actions
721
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
722
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
272.2.76 by Lars Uebernickel
Only show chat section when necessary
723
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
724
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHAT_STATUS]);
272.2.86 by Lars Uebernickel
Use a custom menu item for application items
725
726
	g_action_group_change_action_state (G_ACTION_GROUP (priv->static_shortcuts),
727
					    "launch", g_variant_new_boolean (FALSE));
272.2.66 by Lars Uebernickel
Add draws-attention flag to source actions
728
}
729
730
static gboolean
731
action_draws_attention (GVariant *state)
732
{
733
	gboolean attention;
734
735
	if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)")))
736
		g_variant_get_child (state, 3, "b", &attention);
737
	else
738
		attention = FALSE;
739
740
	return attention;
741
}
742
743
static gboolean
744
any_action_draws_attention (GActionGroup *group,
745
			    const gchar *ignored_action)
746
{
747
	gchar **actions;
748
	gchar **it;
749
	gboolean attention = FALSE;
750
751
	actions = g_action_group_list_actions (group);
752
753
	for (it = actions; *it && !attention; it++) {
754
		GVariant *state;
755
756
		if (ignored_action && g_str_equal (ignored_action, *it))
757
			continue;
758
759
		state = g_action_group_get_action_state (group, *it);
760
		if (state) {
761
			attention = action_draws_attention (state);
762
			g_variant_unref (state);
763
		}
764
	}
765
766
	g_strfreev (actions);
767
	return attention;
768
}
769
770
static void
771
action_added (GActionGroup *group,
772
	      const gchar *action_name,
773
	      gpointer user_data)
774
{
775
	AppSection *self = user_data;
776
	GVariant *state;
777
778
	state = g_action_group_get_action_state (group, action_name);
779
	if (state) {
780
		self->priv->draws_attention |= action_draws_attention (state);
781
		g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
782
		g_variant_unref (state);
783
	}
784
}
785
786
static void
787
action_state_changed (GActionGroup *group,
788
		      const gchar *action_name,
789
		      GVariant *value,
790
		      gpointer user_data)
791
{
792
	AppSection *self = user_data;
793
794
	self->priv->draws_attention = any_action_draws_attention (group, NULL);
795
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
796
}
797
798
static void
799
action_removed (GActionGroup *group,
800
		const gchar *action_name,
801
		gpointer user_data)
802
{
803
	AppSection *self = user_data;
804
805
	self->priv->draws_attention = any_action_draws_attention (group, action_name);
806
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]);
807
}
272.2.76 by Lars Uebernickel
Only show chat section when necessary
808
809
gboolean
810
app_section_get_uses_chat_status (AppSection *self)
811
{
812
	AppSectionPrivate * priv = self->priv;
813
289 by Lars Uebernickel
Request showing the chat section also when the app is not running
814
	return priv->uses_chat_status;
272.2.76 by Lars Uebernickel
Only show chat section when necessary
815
}
313.1.3 by Lars Uebernickel
Set the global chat status more intelligently
816
817
const gchar *
818
app_section_get_status (AppSection *self)
819
{
820
	AppSectionPrivate * priv = self->priv;
821
822
	return priv->chat_status;
823
}
824
825
void
826
app_section_set_status (AppSection  *self,
827
			const gchar *status)
828
{
829
	AppSectionPrivate * priv = self->priv;
830
831
	g_free (priv->chat_status);
832
	priv->chat_status = g_strdup (status);
833
834
	g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHAT_STATUS]);
835
}