From b711fa350a4aec9d9584e6b3623290201f7273a2 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 23 Jan 2015 01:11:07 +0100 Subject: loading gsettings --- libmdock/Makefile.am | 2 +- libmdock/com.javispedro.mdock.widget.gschema.xml | 2 +- libmdock/mdock-item.c | 98 +++++++++++++++++------- libmdock/mdock-item.h | 4 + libmdock/mdock-widget.c | 89 +++++++++++++++++++-- 5 files changed, 159 insertions(+), 36 deletions(-) diff --git a/libmdock/Makefile.am b/libmdock/Makefile.am index 2d46925..cb8ca1d 100644 --- a/libmdock/Makefile.am +++ b/libmdock/Makefile.am @@ -1,5 +1,5 @@ lib_LTLIBRARIES = libmdock.la -libmdock_la_SOURCES = mdock-widget.h mdock-widget.c mdock-enums.h mdock-enums.c mdock-item.h mdock-item.c matcher.h matcher.c app-id.h app-id.c thumbnailer.h thumbnailer.c +libmdock_la_SOURCES = mdock-widget.h mdock-widget.c mdock-enums.h mdock-enums.c mdock-item.h mdock-item.c mdock-item-menu.c mdock-item-menu.h matcher.h matcher.c app-id.h app-id.c thumbnailer.h thumbnailer.c libmdock_la_CPPFLAGS = $(GTK_CFLAGS) $(GIO_CFLAGS) $(WNCK_CFLAGS) $(GTOP_CFLAGS) -D_GNU_SOURCE -DG_LOG_DOMAIN=\"libmdock\" libmdock_la_LIBADD = $(GTK_LIBS) $(GIO_LIBS) $(WNCK_LIBS) $(GTOP_LIBS) diff --git a/libmdock/com.javispedro.mdock.widget.gschema.xml b/libmdock/com.javispedro.mdock.widget.gschema.xml index c48dee4..103a94d 100644 --- a/libmdock/com.javispedro.mdock.widget.gschema.xml +++ b/libmdock/com.javispedro.mdock.widget.gschema.xml @@ -1,7 +1,7 @@ - + [] Items in the dock diff --git a/libmdock/mdock-item.c b/libmdock/mdock-item.c index 2c9a836..9f87a6a 100644 --- a/libmdock/mdock-item.c +++ b/libmdock/mdock-item.c @@ -19,6 +19,7 @@ #include "mdock-enums.h" #include "mdock-item.h" +#include "mdock-item-menu.h" #include "thumbnailer.h" #define MDOCK_ITEM_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), MDOCK_TYPE_ITEM, MDockItemPrivate)) @@ -33,7 +34,9 @@ struct _MDockItemPrivate WnckWindow *last_active; - GtkMenu *menu; + MDockItemMenu *menu; + + GtkMenu *right_menu; GtkImageMenuItem *menu_close_all; GtkImageMenuItem *menu_pin; GtkImageMenuItem *menu_launch; @@ -43,6 +46,7 @@ G_DEFINE_TYPE (MDockItem, mdock_item, GTK_TYPE_WIDGET) enum { PROP_0, + PROP_PINNED, PROP_DESKTOP_APP_INFO, PROP_ICON_SIZE, N_PROPERTIES @@ -97,7 +101,7 @@ static void mdock_item_update_icon(MDockItem *self) static void mdock_item_update_tooltip(MDockItem *self) { - gtk_widget_set_tooltip_text(GTK_WIDGET(self), mdock_item_get_display_name(self)); + // TODO gtk_widget_set_tooltip_text(GTK_WIDGET(self), mdock_item_get_display_name(self)); } static void mdock_item_update_menu(MDockItem *self) @@ -196,28 +200,7 @@ static gboolean mdock_item_button_press(GtkWidget *widget, GdkEventButton *event } } else if (self->priv->appinfo) { // No windows, but we have an application to launch! - GError *error = NULL; - if (!g_app_info_launch(G_APP_INFO(self->priv->appinfo), NULL, NULL, &error)) { - GtkWidget *msg; - - g_warning("Cannot launch '%s': %s", - g_app_info_get_display_name(G_APP_INFO(self->priv->appinfo)), - error->message); - - msg = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - "Cannot launch '%s': %s", - g_app_info_get_display_name(G_APP_INFO(self->priv->appinfo)), - error->message); - - g_signal_connect_swapped(msg, "response", - G_CALLBACK(gtk_widget_destroy), msg); - - gtk_widget_show_all(msg); - g_error_free(error); - } + mdock_item_launch(self); } else { g_warning("A MDockItem has no windows and no appinfo to launch"); } @@ -225,7 +208,7 @@ static gboolean mdock_item_button_press(GtkWidget *widget, GdkEventButton *event break; case 3: - gtk_menu_popup(self->priv->menu, + gtk_menu_popup(self->priv->right_menu, NULL, NULL, NULL, NULL, event->button, event->time); break; @@ -256,10 +239,14 @@ static void mdock_item_set_property(GObject *object, { MDockItem *self = MDOCK_ITEM(object); switch (property_id) { + case PROP_PINNED: + self->priv->pinned = g_value_get_boolean(value); + break; case PROP_DESKTOP_APP_INFO: self->priv->appinfo = g_value_dup_object(value); mdock_item_update_icon(self); mdock_item_update_tooltip(self); + mdock_item_update_menu(self); break; case PROP_ICON_SIZE: self->priv->icon_size = g_value_get_uint(value); @@ -279,6 +266,9 @@ static void mdock_item_get_property(GObject *object, { MDockItem *self = MDOCK_ITEM(object); switch (property_id) { + case PROP_PINNED: + g_value_set_boolean(value, self->priv->pinned); + break; case PROP_DESKTOP_APP_INFO: g_value_set_object(value, self->priv->appinfo); break; @@ -297,6 +287,7 @@ static void mdock_item_dispose(GObject *object) g_clear_object(&self->priv->appinfo); g_clear_object(&self->priv->icon); g_clear_object(&self->priv->menu); + g_clear_object(&self->priv->right_menu); g_clear_object(&self->priv->menu_close_all); g_clear_object(&self->priv->menu_pin); g_clear_object(&self->priv->menu_launch); @@ -318,21 +309,26 @@ static void mdock_item_init(MDockItem *self) gtk_widget_add_events(GTK_WIDGET(self), GDK_BUTTON_PRESS_MASK); - self->priv->menu = g_object_ref_sink(gtk_menu_new()); + self->priv->menu = g_object_ref_sink(mdock_item_menu_new()); + gtk_widget_set_tooltip_window(GTK_WIDGET(self), GTK_WINDOW(self->priv->menu)); + + self->priv->right_menu = g_object_ref_sink(gtk_menu_new()); self->priv->menu_close_all = g_object_ref_sink(gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL)); - gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->menu), + gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->right_menu), GTK_WIDGET(self->priv->menu_close_all)); g_signal_connect_swapped(self->priv->menu_close_all, "activate", G_CALLBACK(mdock_item_close_all_windows), self); self->priv->menu_pin = g_object_ref_sink(gtk_image_menu_item_new_with_mnemonic("_Pin")); - gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->menu), + gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->right_menu), GTK_WIDGET(self->priv->menu_pin)); self->priv->menu_launch = g_object_ref_sink(gtk_image_menu_item_new_with_mnemonic("_New instance")); - gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->menu), + gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->right_menu), GTK_WIDGET(self->priv->menu_launch)); + g_signal_connect_swapped(self->priv->menu_launch, "activate", + G_CALLBACK(mdock_item_launch), self); } static void @@ -351,6 +347,12 @@ mdock_item_class_init(MDockItemClass *klass) widget_class->button_press_event = mdock_item_button_press; widget_class->expose_event = mdock_item_expose; + obj_properties[PROP_PINNED] = g_param_spec_boolean("pinned", + "Pinned launcher", + "Set whether this launcher is pinned", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DESKTOP_APP_INFO] = g_param_spec_object("desktop-app-info", "The GDesktopAppInfo this application or launcher refers to", "Set the GDesktopAppInfo this application or launcher refers to", @@ -374,6 +376,16 @@ MDockItem *mdock_item_new() return g_object_new(MDOCK_TYPE_ITEM, NULL); } +gboolean mdock_item_get_pinned(MDockItem *self) +{ + return self->priv->pinned; +} + +void mdock_item_set_pinned(MDockItem *self, gboolean pinned) +{ + g_object_set(self, "pinned", pinned, NULL); +} + GDesktopAppInfo *mdock_item_get_desktop_app_info(MDockItem *self) { return g_object_ref(self->priv->appinfo); @@ -384,6 +396,34 @@ void mdock_item_set_desktop_app_info(MDockItem *self, GDesktopAppInfo *app_info) g_object_set(self, "desktop-app-info", app_info, NULL); } +void mdock_item_launch(MDockItem *self) +{ + g_return_if_fail(self->priv->appinfo); + GError *error = NULL; + g_debug("Launching '%s'", g_app_info_get_commandline(G_APP_INFO(self->priv->appinfo))); + if (!g_app_info_launch(G_APP_INFO(self->priv->appinfo), NULL, NULL, &error)) { + GtkWidget *msg; + + g_warning("Cannot launch '%s': %s", + g_app_info_get_display_name(G_APP_INFO(self->priv->appinfo)), + error->message); + + msg = gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Cannot launch '%s': %s", + g_app_info_get_display_name(G_APP_INFO(self->priv->appinfo)), + error->message); + + g_signal_connect_swapped(msg, "response", + G_CALLBACK(gtk_widget_destroy), msg); + + gtk_widget_show_all(msg); + g_error_free(error); + } +} + void mdock_item_add_window(MDockItem *self, WnckWindow *window) { thumbnailer_enable_for_window(window); diff --git a/libmdock/mdock-item.h b/libmdock/mdock-item.h index 9876ce8..f9fe657 100644 --- a/libmdock/mdock-item.h +++ b/libmdock/mdock-item.h @@ -52,8 +52,12 @@ struct _MDockItemClass { GType mdock_item_get_type(void) G_GNUC_CONST; MDockItem *mdock_item_new(); +gboolean mdock_item_get_pinned(MDockItem *self); +void mdock_item_set_pinned(MDockItem *self, gboolean pinned); + GDesktopAppInfo *mdock_item_get_desktop_app_info(MDockItem *self); void mdock_item_set_desktop_app_info(MDockItem *self, GDesktopAppInfo *app_info); +void mdock_item_launch(MDockItem *self); void mdock_item_add_window(MDockItem *self, WnckWindow *window); void mdock_item_remove_window(MDockItem *self, WnckWindow *window); diff --git a/libmdock/mdock-widget.c b/libmdock/mdock-widget.c index 27f8f50..06080bf 100644 --- a/libmdock/mdock-widget.c +++ b/libmdock/mdock-widget.c @@ -76,8 +76,8 @@ static void handle_window_closed(MDockWidget *self, WnckWindow *window, WnckScre mdock_item_remove_window(item, window); g_hash_table_remove(self->priv->window_to_item, window); - if (mdock_item_get_num_windows(item) == 0) { - // Removing window! + if (mdock_item_get_num_windows(item) == 0 && !mdock_item_get_pinned(item)) { + // Removing item from dock g_hash_table_foreach_remove(self->priv->appid_to_item, filter_deleted_group, iter); g_hash_table_foreach_remove(self->priv->desktopid_to_item, filter_deleted_group, iter); g_sequence_remove(iter); @@ -137,6 +137,81 @@ static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScre gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, FALSE, 0); } +static void load_items_from_settings(MDockWidget *self, GSettings *settings) +{ + GVariantIter *set_iter; + GVariant *set_value; + GSequenceIter *seq_iter = g_sequence_get_begin_iter(self->priv->items); + + g_settings_get(settings, "items", "as", &set_iter); + set_value = g_variant_iter_next_value(set_iter); + + g_debug("Loading settings %p %p", set_value, seq_iter); + + while (set_value || !g_sequence_iter_is_end(seq_iter)) { + gboolean advance_set = FALSE, advance_seq = FALSE; + MDockItem *item = NULL; + GDesktopAppInfo *seq_appinfo = NULL; + GDesktopAppInfo *set_appinfo = NULL; + + g_debug("Iteration %p %p", set_value, seq_iter); + + if (!g_sequence_iter_is_end(seq_iter)) { + item = MDOCK_ITEM(g_sequence_get(seq_iter)); + seq_appinfo = mdock_item_get_desktop_app_info(item); + } + if (set_value) { + set_appinfo = g_desktop_app_info_new_from_filename(g_variant_get_string(set_value, NULL)); + } + + if (set_appinfo && seq_appinfo) { + const gchar *set_desktopid = g_app_info_get_id(G_APP_INFO(set_appinfo)); + const gchar *seq_desktopid = g_app_info_get_id(G_APP_INFO(seq_appinfo)); + const gboolean seq_pinned = mdock_item_get_pinned(item); + + // TODO broken + g_warning("broken"); + } else if (set_appinfo) { + g_debug("from set only"); + item = mdock_item_new(); + mdock_item_set_desktop_app_info(item, set_appinfo); + mdock_item_set_pinned(item, TRUE); + + GSequenceIter *iter = g_sequence_append(self->priv->items, item); + const gchar *desktopid = g_app_info_get_id(G_APP_INFO(set_appinfo)); + g_hash_table_insert(self->priv->desktopid_to_item, g_strdup(desktopid), iter); + gtk_widget_show(GTK_WIDGET(item)); + gtk_box_pack_start(GTK_BOX(self), GTK_WIDGET(item), TRUE, FALSE, 0); + + advance_set = TRUE; + } else if (seq_appinfo) { + g_debug("from seq only"); + if (mdock_item_get_pinned(item)) { + mdock_item_set_pinned(item, FALSE); + } + advance_seq = TRUE; + } + + g_object_unref(set_appinfo); + + if (advance_set && set_appinfo) { + g_variant_unref(set_value); + set_value = g_variant_iter_next_value(set_iter); + + } + if (advance_seq && !g_sequence_iter_is_end(seq_iter)) { + seq_iter = g_sequence_iter_next(seq_iter); + } + } + + g_variant_iter_free(set_iter); +} + +static void handle_settings_items_changed(MDockWidget *self, gchar *key, GSettings *settings) +{ + load_items_from_settings(self, settings); +} + static void mdock_widget_constructed(GObject *obj) { MDockWidget *self = MDOCK_WIDGET(obj); @@ -144,14 +219,16 @@ static void mdock_widget_constructed(GObject *obj) g_debug("Constructing with path: %s", self->priv->settings_path); self->priv->settings = g_settings_new_with_path("com.javispedro.mdock.widget", self->priv->settings_path); + g_signal_connect_object(self->priv->settings, "changed::items", + G_CALLBACK(handle_settings_items_changed), self, G_CONNECT_SWAPPED); self->priv->wnck_screen = wnck_screen_get_default(); g_signal_connect_object(self->priv->wnck_screen, "active-window-changed", - G_CALLBACK(handle_active_window_changed), self, G_CONNECT_SWAPPED); + G_CALLBACK(handle_active_window_changed), self, G_CONNECT_SWAPPED); g_signal_connect_object(self->priv->wnck_screen, "window-closed", - G_CALLBACK(handle_window_closed), self, G_CONNECT_SWAPPED); + G_CALLBACK(handle_window_closed), self, G_CONNECT_SWAPPED); g_signal_connect_object(self->priv->wnck_screen, "window-opened", - G_CALLBACK(handle_window_opened), self, G_CONNECT_SWAPPED); + G_CALLBACK(handle_window_opened), self, G_CONNECT_SWAPPED); self->priv->items = g_sequence_new(NULL); self->priv->appid_to_item = g_hash_table_new_full(app_id_hash, app_id_equal, @@ -161,6 +238,8 @@ static void mdock_widget_constructed(GObject *obj) self->priv->window_to_item = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL); + load_items_from_settings(self, self->priv->settings); + GList *windows = wnck_screen_get_windows_stacked(self->priv->wnck_screen); for (GList *l = windows; l; l = g_list_next(l)) { WnckWindow *window = l->data; -- cgit v1.2.3