aboutsummaryrefslogtreecommitdiff
path: root/src/app-section.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/app-section.c')
-rw-r--r--src/app-section.c121
1 files changed, 105 insertions, 16 deletions
diff --git a/src/app-section.c b/src/app-section.c
index bed1302..58f1612 100644
--- a/src/app-section.c
+++ b/src/app-section.c
@@ -37,6 +37,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
struct _AppSectionPrivate
{
GDesktopAppInfo * appinfo;
+ GFileMonitor *desktop_file_monitor;
guint unreadcount;
IndicatorDesktopShortcuts * ids;
@@ -64,6 +65,7 @@ enum {
};
static GParamSpec *properties[NUM_PROPERTIES];
+guint destroy_signal;
/* Prototypes */
static void app_section_class_init (AppSectionClass *klass);
@@ -98,6 +100,11 @@ static void action_removed (GActionGroup *group,
const gchar *action_name,
gpointer user_data);
static gboolean action_draws_attention (GVariant *state);
+static void desktop_file_changed_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data);
/* GObject Boilerplate */
G_DEFINE_TYPE (AppSection, app_section, G_TYPE_OBJECT);
@@ -138,6 +145,14 @@ app_section_class_init (AppSectionClass *klass)
G_PARAM_READABLE);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+
+ destroy_signal = g_signal_new ("destroy",
+ APP_SECTION_TYPE,
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
static void
@@ -209,12 +224,18 @@ app_section_set_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
+
static void
app_section_dispose (GObject *object)
{
AppSection * self = APP_SECTION(object);
AppSectionPrivate * priv = self->priv;
+ if (priv->desktop_file_monitor) {
+ g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);
+ g_clear_object (&priv->desktop_file_monitor);
+ }
+
g_clear_object (&priv->menu);
g_clear_object (&priv->static_shortcuts);
@@ -289,6 +310,9 @@ keyfile_loaded (GObject *source_object,
G_KEY_FILE_DESKTOP_GROUP,
"X-MessagingMenu-UsesChatSection",
&error);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
+
if (error) {
if (error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
g_warning ("could not read X-MessagingMenu-UsesChatSection: %s",
@@ -298,34 +322,48 @@ keyfile_loaded (GObject *source_object,
goto out;
}
- if (self->priv->uses_chat_status)
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
-
out:
g_key_file_free (keyfile);
g_free (contents);
}
static void
-app_section_set_app_info (AppSection *self,
- GDesktopAppInfo *appinfo)
+g_menu_clear (GMenu *menu)
+{
+ gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu));
+
+ while (n_items--)
+ g_menu_remove (menu, 0);
+}
+
+static void
+g_simple_action_group_clear (GSimpleActionGroup *group)
+{
+ gchar **actions;
+ gchar **it;
+
+ actions = g_action_group_list_actions (G_ACTION_GROUP (group));
+ for (it = actions; *it; it++)
+ g_simple_action_group_remove (group, *it);
+
+ g_strfreev (actions);
+}
+
+static void
+app_section_update_menu (AppSection *self)
{
AppSectionPrivate *priv = self->priv;
GSimpleAction *launch;
GFile *keyfile;
GMenuItem *item;
gchar *iconstr;
+ gboolean is_running;
- g_return_if_fail (priv->appinfo == NULL);
+ g_menu_clear (priv->menu);
+ g_simple_action_group_clear (priv->static_shortcuts);
- if (appinfo == NULL) {
- g_warning ("appinfo must not be NULL");
- return;
- }
-
- priv->appinfo = g_object_ref (appinfo);
-
- launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (FALSE));
+ is_running = priv->name_watch_id > 0;
+ launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (is_running));
g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self);
g_signal_connect (launch, "change-state", G_CALLBACK (launch_action_change_state), self);
g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch));
@@ -366,14 +404,65 @@ app_section_set_app_info (AppSection *self,
keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));
g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);
- g_object_unref (keyfile);
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
+ g_object_unref (keyfile);
g_object_unref (launch);
}
+static void
+desktop_file_changed_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data)
+{
+ AppSection *self = user_data;
+
+ if (event == G_FILE_MONITOR_EVENT_CHANGED) {
+ app_section_update_menu (self);
+ }
+ else if (event == G_FILE_MONITOR_EVENT_DELETED ||
+ event == G_FILE_MONITOR_EVENT_UNMOUNTED) {
+ g_signal_emit (self, destroy_signal, 0);
+ }
+}
+
+static void
+app_section_set_app_info (AppSection *self,
+ GDesktopAppInfo *appinfo)
+{
+ AppSectionPrivate *priv = self->priv;
+ GFile *desktop_file;
+ GError *error = NULL;
+
+ g_return_if_fail (priv->appinfo == NULL);
+ g_return_if_fail (priv->desktop_file_monitor == NULL);
+
+ if (appinfo == NULL) {
+ g_warning ("appinfo must not be NULL");
+ return;
+ }
+
+ priv->appinfo = g_object_ref (appinfo);
+
+ desktop_file = g_file_new_for_path (g_desktop_app_info_get_filename (appinfo));
+ priv->desktop_file_monitor = g_file_monitor (desktop_file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
+ if (priv->desktop_file_monitor == NULL) {
+ g_warning ("unable to watch desktop file: %s", error->message);
+ g_error_free (error);
+ }
+ g_signal_connect (priv->desktop_file_monitor, "changed",
+ G_CALLBACK (desktop_file_changed_cb), self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]);
+
+ app_section_update_menu (self);
+
+ g_object_unref (desktop_file);
+}
+
AppSection *
app_section_new (GDesktopAppInfo *appinfo)
{