From c4499405e511d94005c58cf64489199cbb9e5a86 Mon Sep 17 00:00:00 2001 From: rbuj Date: Wed, 2 Dec 2020 10:41:47 +0100 Subject: drivemount: Use common subdirs - data, src --- drivemount/Makefile.am | 83 +- drivemount/data/Makefile.am | 45 + drivemount/data/drivemount-applet-menu.xml | 3 + drivemount/data/drivemount-resources.gresource.xml | 6 + ...riveMountApplet.mate-panel-applet.desktop.in.in | 17 + drivemount/data/org.mate.drivemount.gschema.xml.in | 9 + ...panel.applet.DriveMountAppletFactory.service.in | 3 + drivemount/drive-button.c | 982 --------------------- drivemount/drive-button.h | 71 -- drivemount/drive-list.c | 522 ----------- drivemount/drive-list.h | 73 -- drivemount/drivemount-applet-menu.xml | 3 - drivemount/drivemount-resources.gresource.xml | 6 - drivemount/drivemount.c | 230 ----- ...riveMountApplet.mate-panel-applet.desktop.in.in | 17 - drivemount/org.mate.drivemount.gschema.xml.in | 9 - ...panel.applet.DriveMountAppletFactory.service.in | 3 - drivemount/src/Makefile.am | 43 + drivemount/src/drive-button.c | 982 +++++++++++++++++++++ drivemount/src/drive-button.h | 71 ++ drivemount/src/drive-list.c | 522 +++++++++++ drivemount/src/drive-list.h | 73 ++ drivemount/src/drivemount.c | 230 +++++ 23 files changed, 2005 insertions(+), 1998 deletions(-) create mode 100644 drivemount/data/Makefile.am create mode 100644 drivemount/data/drivemount-applet-menu.xml create mode 100644 drivemount/data/drivemount-resources.gresource.xml create mode 100644 drivemount/data/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in create mode 100644 drivemount/data/org.mate.drivemount.gschema.xml.in create mode 100644 drivemount/data/org.mate.panel.applet.DriveMountAppletFactory.service.in delete mode 100644 drivemount/drive-button.c delete mode 100644 drivemount/drive-button.h delete mode 100644 drivemount/drive-list.c delete mode 100644 drivemount/drive-list.h delete mode 100644 drivemount/drivemount-applet-menu.xml delete mode 100644 drivemount/drivemount-resources.gresource.xml delete mode 100644 drivemount/drivemount.c delete mode 100644 drivemount/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in delete mode 100644 drivemount/org.mate.drivemount.gschema.xml.in delete mode 100644 drivemount/org.mate.panel.applet.DriveMountAppletFactory.service.in create mode 100644 drivemount/src/Makefile.am create mode 100644 drivemount/src/drive-button.c create mode 100644 drivemount/src/drive-button.h create mode 100644 drivemount/src/drive-list.c create mode 100644 drivemount/src/drive-list.h create mode 100644 drivemount/src/drivemount.c (limited to 'drivemount') diff --git a/drivemount/Makefile.am b/drivemount/Makefile.am index 16088a47..04c1df64 100644 --- a/drivemount/Makefile.am +++ b/drivemount/Makefile.am @@ -1,84 +1,3 @@ -NULL = - -SUBDIRS = help - -AM_CPPFLAGS = \ - -I. \ - -I$(srcdir) \ - -DDRIVEMOUNT_RESOURCE_PATH=\""/org/mate/mate-applets/drivemount/"\" \ - ${WARN_CFLAGS} \ - $(MATE_APPLETS4_CFLAGS) \ - $(NULL) - -libexec_PROGRAMS = mate-drivemount-applet - -BUILT_SOURCES = \ - drivemount-resources.c \ - drivemount-resources.h \ - $(NULL) - -nodist_mate_drivemount_applet_SOURCES = \ - $(BUILT_SOURCES) \ - $(NULL) - -mate_drivemount_applet_SOURCES = \ - drivemount.c \ - drive-list.c \ - drive-list.h \ - drive-button.c \ - drive-button.h \ - $(NULL) - -mate_drivemount_applet_LDADD = \ - $(MATE_APPLETS4_LIBS) - -drivemount-resources.c: drivemount-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/drivemount-resources.gresource.xml) - $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate --c-name drivemount $< - -drivemount-resources.h: drivemount-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/drivemount-resources.gresource.xml) - $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate --c-name drivemount $< - -drivemount_gschema_in_files = org.mate.drivemount.gschema.xml.in -gsettings_SCHEMAS = $(drivemount_gschema_in_files:.xml.in=.xml) -@GSETTINGS_RULES@ - -appletdir = $(datadir)/mate-panel/applets -applet_in_files = org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in -applet_DATA = $(applet_in_files:.mate-panel-applet.desktop.in=.mate-panel-applet) - -$(applet_in_files): $(applet_in_files).in Makefile - $(AM_V_GEN)sed \ - -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ - -e "s|\@VERSION\@|$(PACKAGE_VERSION)|" \ - $< > $@ - -$(applet_DATA): $(applet_in_files) Makefile - $(AM_V_GEN) $(MSGFMT) --desktop --keyword=Name --keyword=Description --template $< -d $(top_srcdir)/po -o $@ - -servicedir = $(datadir)/dbus-1/services -service_in_files = org.mate.panel.applet.DriveMountAppletFactory.service.in -service_DATA = $(service_in_files:.service.in=.service) - -org.mate.panel.applet.DriveMountAppletFactory.service: $(service_in_files) - $(AM_V_GEN)sed \ - -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ - $< > $@ - -CLEANFILES = \ - $(applet_DATA) \ - $(applet_in_files) \ - $(service_DATA) \ - $(gsettings_SCHEMAS) \ - $(BUILT_SOURCES) \ - *.gschema.valid \ - $(NULL) - -EXTRA_DIST = \ - $(applet_in_files).in \ - $(service_in_files) \ - $(drivemount_gschema_in_files) \ - drivemount-applet-menu.xml \ - drivemount-resources.gresource.xml \ - $(NULL) +SUBDIRS = help data src -include $(top_srcdir)/git.mk diff --git a/drivemount/data/Makefile.am b/drivemount/data/Makefile.am new file mode 100644 index 00000000..b0dc7718 --- /dev/null +++ b/drivemount/data/Makefile.am @@ -0,0 +1,45 @@ +NULL = + +drivemount_gschema_in_files = org.mate.drivemount.gschema.xml.in +gsettings_SCHEMAS = $(drivemount_gschema_in_files:.xml.in=.xml) +@GSETTINGS_RULES@ + +appletdir = $(datadir)/mate-panel/applets +applet_in_files = org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in +applet_DATA = $(applet_in_files:.mate-panel-applet.desktop.in=.mate-panel-applet) + +$(applet_in_files): $(applet_in_files).in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + -e "s|\@VERSION\@|$(PACKAGE_VERSION)|" \ + $< > $@ + +$(applet_DATA): $(applet_in_files) Makefile + $(AM_V_GEN) $(MSGFMT) --desktop --keyword=Name --keyword=Description --template $< -d $(top_srcdir)/po -o $@ + +servicedir = $(datadir)/dbus-1/services +service_in_files = org.mate.panel.applet.DriveMountAppletFactory.service.in +service_DATA = $(service_in_files:.service.in=.service) + +org.mate.panel.applet.DriveMountAppletFactory.service: $(service_in_files) + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + $< > $@ + +CLEANFILES = \ + $(applet_DATA) \ + $(applet_in_files) \ + $(service_DATA) \ + $(gsettings_SCHEMAS) \ + *.gschema.valid \ + $(NULL) + +EXTRA_DIST = \ + $(applet_in_files:=.in) \ + $(drivemount_gschema_in_files) \ + $(service_in_files) \ + drivemount-applet-menu.xml \ + drivemount-resources.gresource.xml \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/drivemount/data/drivemount-applet-menu.xml b/drivemount/data/drivemount-applet-menu.xml new file mode 100644 index 00000000..efc26591 --- /dev/null +++ b/drivemount/data/drivemount-applet-menu.xml @@ -0,0 +1,3 @@ + + + diff --git a/drivemount/data/drivemount-resources.gresource.xml b/drivemount/data/drivemount-resources.gresource.xml new file mode 100644 index 00000000..3a8c57a8 --- /dev/null +++ b/drivemount/data/drivemount-resources.gresource.xml @@ -0,0 +1,6 @@ + + + + drivemount-applet-menu.xml + + diff --git a/drivemount/data/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in b/drivemount/data/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in new file mode 100644 index 00000000..637628d2 --- /dev/null +++ b/drivemount/data/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in @@ -0,0 +1,17 @@ +[Applet Factory] +Id=DriveMountAppletFactory +Location=@LIBEXECDIR@/mate-drivemount-applet +Name=Drive Mount Applet Factory +Description=Factory for drive mount applet + +[DriveMountApplet] +Name=Disk Mounter +Description=Mount local disks and devices +# Translators: Do NOT translate or transliterate this text (this is an icon file name)! +Icon=media-floppy +MateComponentId=OAFIID:MATE_DriveMountApplet +X-MATE-Bugzilla-Bugzilla=MATE +X-MATE-Bugzilla-Product=mate-applets +X-MATE-Bugzilla-Component=Disk Mounter (drivemount) +X-MATE-Bugzilla-Version=@VERSION@ +X-MATE-Bugzilla-OtherBinaries=drivemount_applet2 diff --git a/drivemount/data/org.mate.drivemount.gschema.xml.in b/drivemount/data/org.mate.drivemount.gschema.xml.in new file mode 100644 index 00000000..24ffe871 --- /dev/null +++ b/drivemount/data/org.mate.drivemount.gschema.xml.in @@ -0,0 +1,9 @@ + + + + '#00e300' + Checkmark color for mounted drive or share + Default color in a hex value. + + + diff --git a/drivemount/data/org.mate.panel.applet.DriveMountAppletFactory.service.in b/drivemount/data/org.mate.panel.applet.DriveMountAppletFactory.service.in new file mode 100644 index 00000000..90d44b42 --- /dev/null +++ b/drivemount/data/org.mate.panel.applet.DriveMountAppletFactory.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.mate.panel.applet.DriveMountAppletFactory +Exec=@LIBEXECDIR@/mate-drivemount-applet diff --git a/drivemount/drive-button.c b/drivemount/drive-button.c deleted file mode 100644 index f64f38c4..00000000 --- a/drivemount/drive-button.c +++ /dev/null @@ -1,982 +0,0 @@ -/* -*- mode: C; c-basic-offset: 4 -*- - * Drive Mount Applet - * Copyright (c) 2004 Canonical Ltd - * Copyright 2008 Pierre Ossman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * James Henstridge - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "drive-button.h" -#include -#include -#include - -#include - -enum { - CMD_NONE, - CMD_MOUNT_OR_PLAY, - CMD_UNMOUNT, - CMD_EJECT -}; - -/* type registration boilerplate code */ -G_DEFINE_TYPE (DriveButton, drive_button, GTK_TYPE_BUTTON) - -static void drive_button_set_volume (DriveButton *self, - GVolume *volume); -static void drive_button_set_mount (DriveButton *self, - GMount *mount); -static void drive_button_reset_popup (DriveButton *self); -static void drive_button_ensure_popup (DriveButton *self); - -static void drive_button_dispose (GObject *object); -#if 0 -static void drive_button_unrealize (GtkWidget *widget); -#endif /* 0 */ -static gboolean drive_button_button_press (GtkWidget *widget, - GdkEventButton *event); -static gboolean drive_button_key_press (GtkWidget *widget, - GdkEventKey *event); -static void drive_button_theme_change (GtkIconTheme *icon_theme, - gpointer data); - -static void -drive_button_class_init (DriveButtonClass *class) -{ - G_OBJECT_CLASS (class)->dispose = drive_button_dispose; - GTK_WIDGET_CLASS (class)->button_press_event = drive_button_button_press; - GTK_WIDGET_CLASS (class)->key_press_event = drive_button_key_press; - - GtkCssProvider *provider; - - provider = gtk_css_provider_new (); - - gtk_css_provider_load_from_data (provider, - "#drive-button {\n" - " border-width: 0px;\n" - " padding: 0px;\n" - " margin: 0px;\n" - "}", - -1, NULL); - - gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), - GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - g_object_unref (provider); -} - -static void -drive_button_init (DriveButton *self) -{ - GtkWidget *image; - - image = gtk_image_new (); - gtk_container_add (GTK_CONTAINER (self), image); - gtk_widget_show (image); - - self->volume = NULL; - self->mount = NULL; - self->icon_size = 24; - self->update_tag = 0; - - self->popup_menu = NULL; - - gtk_widget_set_name (GTK_WIDGET (self), "drive-button"); -} - -GtkWidget * -drive_button_new (GVolume *volume) -{ - DriveButton *self; - - self = g_object_new (DRIVE_TYPE_BUTTON, NULL); - if (volume != NULL) { - drive_button_set_volume (self, volume); - g_signal_connect (gtk_icon_theme_get_default (), - "changed", G_CALLBACK (drive_button_theme_change), - self); - } - - return (GtkWidget *)self; -} - -GtkWidget * -drive_button_new_from_mount (GMount *mount) -{ - DriveButton *self; - - self = g_object_new (DRIVE_TYPE_BUTTON, NULL); - drive_button_set_mount (self, mount); - - g_signal_connect (gtk_icon_theme_get_default (), - "changed", G_CALLBACK (drive_button_theme_change), - self); - - return (GtkWidget *)self; -} - -static void -drive_button_dispose (GObject *object) -{ - DriveButton *self = DRIVE_BUTTON (object); - - drive_button_set_volume (self, NULL); - - if (self->update_tag) - g_source_remove (self->update_tag); - self->update_tag = 0; - - drive_button_reset_popup (self); - - if (G_OBJECT_CLASS (drive_button_parent_class)->dispose) - (* G_OBJECT_CLASS (drive_button_parent_class)->dispose) (object); -} - -static gboolean -drive_button_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - DriveButton *self = DRIVE_BUTTON (widget); - - /* don't consume non-button1 presses */ - if (event->button == 1) { - drive_button_ensure_popup (self); - if (self->popup_menu) { - gtk_menu_popup_at_widget (GTK_MENU (self->popup_menu), - widget, - GDK_GRAVITY_SOUTH_WEST, - GDK_GRAVITY_NORTH_WEST, - (const GdkEvent*) event); - } - return TRUE; - } - return FALSE; -} - -static gboolean -drive_button_key_press (GtkWidget *widget, - GdkEventKey *event) -{ - DriveButton *self = DRIVE_BUTTON (widget); - - switch (event->keyval) { - case GDK_KEY_KP_Space: - case GDK_KEY_space: - case GDK_KEY_KP_Enter: - case GDK_KEY_Return: - drive_button_ensure_popup (self); - if (self->popup_menu) { - gtk_menu_popup_at_widget (GTK_MENU (self->popup_menu), - widget, - GDK_GRAVITY_SOUTH_WEST, - GDK_GRAVITY_NORTH_WEST, - (const GdkEvent*) event); - } - return TRUE; - } - return FALSE; -} - -static void -drive_button_theme_change (GtkIconTheme *icon_theme, - gpointer data) -{ - drive_button_queue_update (data); -} - -static void -drive_button_set_volume (DriveButton *self, - GVolume *volume) -{ - g_return_if_fail (DRIVE_IS_BUTTON (self)); - - if (self->volume) { - g_object_unref (self->volume); - } - self->volume = NULL; - if (self->mount) { - g_object_unref (self->mount); - } - self->mount = NULL; - - if (volume) { - self->volume = g_object_ref (volume); - } - drive_button_queue_update (self); -} - -static void -drive_button_set_mount (DriveButton *self, - GMount *mount) -{ - g_return_if_fail (DRIVE_IS_BUTTON (self)); - - if (self->volume) { - g_object_unref (self->volume); - } - self->volume = NULL; - if (self->mount) { - g_object_unref (self->mount); - } - self->mount = NULL; - - if (mount) { - self->mount = g_object_ref (mount); - } - drive_button_queue_update (self); -} - -static gboolean -drive_button_update (gpointer user_data) -{ - DriveButton *self; - GdkScreen *screen; - GtkIconTheme *icon_theme; - GtkIconInfo *icon_info; - GIcon *icon; - int width, height, scale; - cairo_t *cr; - cairo_surface_t *surface = NULL; - cairo_surface_t *tmp_surface = NULL; - GtkRequisition button_req, image_req; - char *display_name, *tip; - - g_return_val_if_fail (DRIVE_IS_BUTTON (user_data), FALSE); - self = DRIVE_BUTTON (user_data); - self->update_tag = 0; - - /* base the icon size on the desired button size */ - drive_button_reset_popup (self); - scale = gtk_widget_get_scale_factor (GTK_WIDGET (self)); - gtk_widget_get_preferred_size (GTK_WIDGET (self), NULL, &button_req); - gtk_widget_get_preferred_size (gtk_bin_get_child (GTK_BIN (self)), NULL, &image_req); - width = (self->icon_size - (button_req.width - image_req.width)) / scale; - height = (self->icon_size - (button_req.height - image_req.height)) / scale; - - /* if no volume or mount, display general image */ - if (!self->volume && !self->mount) - { - gtk_widget_set_tooltip_text (GTK_WIDGET (self), _("nothing to mount")); - screen = gtk_widget_get_screen (GTK_WIDGET (self)); - icon_theme = gtk_icon_theme_get_for_screen (screen); //m - // note - other good icon would be emblem-unreadable - icon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, "media-floppy", - MIN (width, height), scale, - GTK_ICON_LOOKUP_USE_BUILTIN); - if (icon_info) { - surface = gtk_icon_info_load_surface (icon_info, NULL, NULL); - g_object_unref (icon_info); - } - - if (!surface) - return FALSE; - - if (gtk_bin_get_child (GTK_BIN (self)) != NULL) - gtk_image_set_from_surface (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (self))), surface); - - return FALSE; - } - - gboolean is_mounted = FALSE; - - if (self->volume) - { - GMount *mount; - - display_name = g_volume_get_name (self->volume); - mount = g_volume_get_mount (self->volume); - - if (mount) - { - is_mounted = TRUE; - tip = g_strdup_printf ("%s\n%s", display_name, _("(mounted)")); - icon = g_mount_get_icon (mount); - g_object_unref (mount); - } - else - { - is_mounted = FALSE; - tip = g_strdup_printf ("%s\n%s", display_name, _("(not mounted)")); - icon = g_volume_get_icon (self->volume); - } - } else - { - is_mounted = TRUE; - display_name = g_mount_get_name (self->mount); - tip = g_strdup_printf ("%s\n%s", display_name, _("(mounted)")); - icon = g_mount_get_icon (self->mount); - } - - gtk_widget_set_tooltip_text (GTK_WIDGET (self), tip); - g_free (tip); - g_free (display_name); - - screen = gtk_widget_get_screen (GTK_WIDGET (self)); - icon_theme = gtk_icon_theme_get_for_screen (screen); - icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, icon, - MIN (width, height), scale, - GTK_ICON_LOOKUP_USE_BUILTIN); - if (icon_info) - { - surface = gtk_icon_info_load_surface (icon_info, NULL, NULL); - g_object_unref (icon_info); - } - - g_object_unref (icon); - - if (!surface) - return FALSE; - - // create a new surface because icon image can be shared by system - tmp_surface = cairo_surface_create_similar (surface, - cairo_surface_get_content (surface), - cairo_image_surface_get_width (surface) / scale, - cairo_image_surface_get_height (surface) / scale); - - // if mounted, change icon - if (is_mounted) - { - int icon_width, icon_height, rowstride, n_channels, x, y; - guchar *pixels, *p; - gboolean has_alpha; - - has_alpha = cairo_surface_get_content (tmp_surface) != CAIRO_CONTENT_COLOR; - n_channels = 3; - if (has_alpha) - n_channels++; - - icon_width = cairo_image_surface_get_width (tmp_surface); - icon_height = cairo_image_surface_get_height (tmp_surface); - - rowstride = cairo_image_surface_get_stride (tmp_surface); - pixels = cairo_image_surface_get_data (tmp_surface); - - GdkRGBA color; - GSettings *settings; - settings = g_settings_new ("org.mate.drivemount"); - gchar *color_string = g_settings_get_string (settings, "drivemount-checkmark-color"); - if (!color_string) - color_string = g_strdup ("#00ff00"); - gdk_rgba_parse (&color, color_string); - g_free (color_string); - g_object_unref (settings); - - guchar red = color.red*255; - guchar green = color.green*255; - guchar blue = color.blue*255; - - const gdouble ratio = 0.65; - gdouble y_start = icon_height * ratio; - gdouble x_start = icon_height * (1 + ratio); - - for (y = y_start; y < icon_height; y++) - for (x = x_start - y; x < icon_width; x++) - { - p = pixels + y * rowstride + x * n_channels; - p[0] = red; - p[1] = green; - p[2] = blue; - if (has_alpha) - p[3] = 255; - } - } - - cr = cairo_create (tmp_surface); - cairo_set_operator (cr, CAIRO_OPERATOR_OVERLAY); - cairo_set_source_surface (cr, surface, 0, 0); - cairo_paint (cr); - - gtk_image_set_from_surface (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (self))), tmp_surface); - - cairo_surface_destroy (surface); - cairo_surface_destroy (tmp_surface); - - gtk_widget_get_preferred_size (GTK_WIDGET (self), NULL, &button_req); - - return FALSE; -} - -void -drive_button_queue_update (DriveButton *self) -{ - if (!self->update_tag) { - self->update_tag = g_idle_add (drive_button_update, self); - } -} - -void -drive_button_set_size (DriveButton *self, - int icon_size) -{ - g_return_if_fail (DRIVE_IS_BUTTON (self)); - - if (self->icon_size != icon_size) { - self->icon_size = icon_size; - drive_button_queue_update (self); - } -} - -void -drive_button_redraw (gpointer key, - gpointer value, - gpointer user_data) -{ - DriveButton *button = value; - drive_button_queue_update (button); -} - -int -drive_button_compare (DriveButton *button, - DriveButton *other_button) -{ - /* sort drives before driveless volumes volumes */ - if (button->volume) { - if (other_button->volume) { - int cmp; - gchar *str1, *str2; - - str1 = g_volume_get_name (button->volume); - str2 = g_volume_get_name (other_button->volume); - cmp = g_utf8_collate (str1, str2); - g_free (str2); - g_free (str1); - - return cmp; - } else { - return -1; - } - } else { - if (other_button->volume) { - return 1; - } else { - int cmp; - gchar *str1, *str2; - - str1 = g_mount_get_name (button->mount); - str2 = g_mount_get_name (other_button->mount); - cmp = g_utf8_collate (str1, str2); - g_free (str2); - g_free (str1); - - return cmp; - } - } -} - -static void -drive_button_reset_popup (DriveButton *self) -{ - if (self->popup_menu) - gtk_widget_destroy (GTK_WIDGET (self->popup_menu)); - self->popup_menu = NULL; -} - -#if 0 -static void -popup_menu_detach (GtkWidget *attach_widget, GtkMenu *menu) -{ - DRIVE_BUTTON (attach_widget)->popup_menu = NULL; -} -#endif /* 0 */ - -static char * -escape_underscores (const char *str) -{ - char *new_str; - int i, j, count; - - /* count up how many underscores are in the string */ - count = 0; - for (i = 0; str[i] != '\0'; i++) { - if (str[i] == '_') - count++; - } - /* copy to new string, doubling up underscores */ - new_str = g_new (char, i + count + 1); - for (i = j = 0; str[i] != '\0'; i++, j++) { - new_str[j] = str[i]; - if (str[i] == '_') - new_str[++j] = '_'; - } - new_str[j] = '\0'; - return new_str; -} -static GtkWidget * -create_menu_item (DriveButton *self, - const gchar *icon_name, - const gchar *label, - GCallback callback, - gboolean sensitive) -{ - GtkWidget *item, *image; - - item = gtk_image_menu_item_new_with_mnemonic (label); - if (icon_name) { - image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_widget_show (image); - } - if (callback) - g_signal_connect_object (item, "activate", callback, self, - G_CONNECT_SWAPPED); - gtk_widget_set_sensitive (item, sensitive); - gtk_widget_show (item); - return item; -} - -static void -open_drive (DriveButton *self, - GtkWidget *item) -{ - GdkScreen *screen; - GtkWidget *dialog; - GError *error = NULL; - GFile *file = NULL; - GList *files = NULL; - GdkAppLaunchContext *launch_context; - GAppInfo *app_info; - - if (self->volume) { - GMount *mount; - - mount = g_volume_get_mount (self->volume); - if (mount) { - file = g_mount_get_root (mount); - g_object_unref (mount); - } - } else if (self->mount) { - file = g_mount_get_root (self->mount); - } else - g_return_if_reached (); - - app_info = g_app_info_get_default_for_type ("inode/directory", FALSE); - if (!app_info) - app_info = G_APP_INFO (g_desktop_app_info_new ("caja.desktop")); - - if (app_info) { - GdkDisplay *display = gtk_widget_get_display (item); - launch_context = gdk_display_get_app_launch_context (display); - screen = gtk_widget_get_screen (GTK_WIDGET (self)); - gdk_app_launch_context_set_screen (launch_context, screen); - files = g_list_prepend (files, file); - g_app_info_launch (app_info, - files, - G_APP_LAUNCH_CONTEXT (launch_context), - &error); - - g_object_unref (launch_context); - g_list_free (files); - } - - if (!app_info || error) { - dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Cannot execute Caja")); - if (error) - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message); - else - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "Could not find Caja"); - g_signal_connect (dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); - gtk_widget_show (dialog); - g_error_free (error); - } - - g_object_unref (file); -} - -/* copied from mate-volume-manager/src/manager.c maybe there is a better way than - * duplicating this code? */ - -/* - * gvm_run_command - run the given command, replacing %d with the device node - * and %m with the given path - */ -static void -gvm_run_command (const char *device, - const char *command, - const char *path) -{ - char *argv[4]; - gchar *new_command; - GError *error = NULL; - GString *exec = g_string_new (NULL); - char *p, *q; - - /* perform s/%d/device/ and s/%m/path/ */ - new_command = g_strdup (command); - q = new_command; - p = new_command; - while ((p = strchr (p, '%')) != NULL) { - if (*(p + 1) == 'd') { - *p = '\0'; - g_string_append (exec, q); - g_string_append (exec, device); - q = p + 2; - p = p + 2; - } else if (*(p + 1) == 'm') { - *p = '\0'; - g_string_append (exec, q); - g_string_append (exec, path); - q = p + 2; - p = p + 2; - } else { - /* Ignore anything else. */ - p++; - } - } - g_string_append (exec, q); - - argv[0] = "/bin/sh"; - argv[1] = "-c"; - argv[2] = exec->str; - argv[3] = NULL; - - g_spawn_async (g_get_home_dir (), argv, NULL, 0, NULL, NULL, - NULL, &error); - if (error) { - g_warning ("failed to exec %s: %s\n", exec->str, error->message); - g_error_free (error); - } - - g_string_free (exec, TRUE); - g_free (new_command); -} - -/* - * gvm_check_dvd_only - is this a Video DVD? - * - * Returns TRUE if this was a Video DVD and FALSE otherwise. - * (the original in gvm was also running the autoplay action, - * I removed that code, so I renamed from gvm_check_dvd to - * gvm_check_dvd_only) - */ -static gboolean -gvm_check_dvd_only (const char *udi, - const char *device, - const char *mount_point) -{ - char *path; - gboolean retval; - - path = g_build_path (G_DIR_SEPARATOR_S, mount_point, "video_ts", NULL); - retval = g_file_test (path, G_FILE_TEST_IS_DIR); - g_free (path); - - /* try the other name, if needed */ - if (retval == FALSE) { - path = g_build_path (G_DIR_SEPARATOR_S, mount_point, - "VIDEO_TS", NULL); - retval = g_file_test (path, G_FILE_TEST_IS_DIR); - g_free (path); - } - - return retval; -} -/* END copied from mate-volume-manager/src/manager.c */ - -static gboolean -check_dvd_video (DriveButton *self) -{ - GFile *file; - char *udi, *device_path, *mount_path; - gboolean result; - GMount *mount; - - if (!self->volume) - return FALSE; - - mount = g_volume_get_mount (self->volume); - if (!mount) - return FALSE; - - file = g_mount_get_root (mount); - g_object_unref (mount); - - if (!file) - return FALSE; - - mount_path = g_file_get_path (file); - - g_object_unref (file); - - device_path = g_volume_get_identifier (self->volume, - G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); - udi = g_volume_get_identifier (self->volume, - G_VOLUME_IDENTIFIER_KIND_HAL_UDI); - - result = gvm_check_dvd_only (udi, device_path, mount_path); - - g_free (device_path); - g_free (udi); - g_free (mount_path); - - return result; -} - -static gboolean -check_audio_cd (DriveButton *self) -{ - GFile *file; - char *activation_uri; - GMount *mount; - - if (!self->volume) - return FALSE; - - mount = g_volume_get_mount (self->volume); - if (!mount) - return FALSE; - - file = g_mount_get_root (mount); - g_object_unref (mount); - - if (!file) - return FALSE; - - activation_uri = g_file_get_uri (file); - - g_object_unref (file); - - /* we have an audioCD if the activation URI starts by 'cdda://' */ - gboolean result = (strncmp ("cdda://", activation_uri, 7) == 0); - g_free (activation_uri); - return result; -} - -static void -run_command (DriveButton *self, - const char *command) -{ - GFile *file; - char *mount_path, *device_path; - GMount *mount; - - if (!self->volume) - return; - - mount = g_volume_get_mount (self->volume); - if (!mount) - return; - - file = g_mount_get_root (mount); - g_object_unref (mount); - - g_assert (file); - - mount_path = g_file_get_path (file); - - g_object_unref (file); - - device_path = g_volume_get_identifier (self->volume, - G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); - - gvm_run_command (device_path, command, mount_path); - - g_free (mount_path); - g_free (device_path); -} - -static void dummy_async_ready_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - /* do nothing */ -} - -static void -mount_drive (DriveButton *self, - GtkWidget *item) -{ - if (self->volume) { - GMountOperation *mount_op = gtk_mount_operation_new (NULL); - g_volume_mount (self->volume, G_MOUNT_MOUNT_NONE, - mount_op, NULL, dummy_async_ready_callback, NULL); - g_object_unref (mount_op); - } else { - g_return_if_reached (); - } -} - -static void -unmount_drive (DriveButton *self, - GtkWidget *item) -{ - if (self->volume) { - GMount *mount; - - mount = g_volume_get_mount (self->volume); - if (mount) { - g_mount_unmount_with_operation (mount, G_MOUNT_UNMOUNT_NONE, - NULL, NULL, dummy_async_ready_callback, NULL); - g_object_unref (mount); - } - } else if (self->mount) { - g_mount_unmount_with_operation (self->mount, G_MOUNT_UNMOUNT_NONE, - NULL, NULL, dummy_async_ready_callback, NULL); - } else { - g_return_if_reached (); - } -} - -static void eject_finish (DriveButton *self, - GAsyncResult *res, - gpointer user_data) -{ - /* Do nothing. We shouldn't need this according to the GIO - * docs, but the applet crashes without it using glib 2.18.0 */ -} - -static void -eject_drive (DriveButton *self, - GtkWidget *item) -{ - if (self->volume) { - g_volume_eject_with_operation (self->volume, G_MOUNT_UNMOUNT_NONE, - NULL, NULL, - (GAsyncReadyCallback) eject_finish, - NULL); - } else if (self->mount) { - g_mount_eject_with_operation (self->mount, G_MOUNT_UNMOUNT_NONE, - NULL, NULL, - (GAsyncReadyCallback) eject_finish, - NULL); - } else { - g_return_if_reached (); - } -} -static void -play_autoplay_media (DriveButton *self, - const char *dflt) -{ - run_command (self, dflt); -} - -static void -play_dvd (DriveButton *self, - GtkWidget *item) -{ - /* FIXME add an option to set this */ - play_autoplay_media (self, "totem %d"); -} - -static void -play_cda (DriveButton *self, - GtkWidget *item) -{ - /* FIXME add an option to set this */ - play_autoplay_media (self, "sound-juicer -d %d"); -} - -static void -drive_button_ensure_popup (DriveButton *self) -{ - char *display_name, *tmp, *label; - GtkWidget *item; - gboolean mounted, ejectable; - - if (self->popup_menu) return; - - mounted = FALSE; - - if (self->volume) { - GMount *mount = NULL; - - display_name = g_volume_get_name (self->volume); - ejectable = g_volume_can_eject (self->volume); - - mount = g_volume_get_mount (self->volume); - if (mount) { - mounted = TRUE; - g_object_unref (mount); - } - } else { - if (!G_IS_MOUNT (self->volume)) - return; - else { - display_name = g_mount_get_name (self->mount); - ejectable = g_mount_can_eject (self->mount); - mounted = TRUE; - } - } - - self->popup_menu = gtk_menu_new (); - - /* make sure the display name doesn't look like a mnemonic */ - tmp = escape_underscores (display_name ? display_name : "(none)"); - g_free (display_name); - display_name = tmp; - - if (check_dvd_video (self)) { - item = create_menu_item (self, "media-playback-start", - _("_Play DVD"), G_CALLBACK (play_dvd), - TRUE); - } else if (check_audio_cd (self)) { - item = create_menu_item (self, "media-playback-start", - _("_Play CD"), G_CALLBACK (play_cda), - TRUE); - } else { - label = g_strdup_printf (_("_Open %s"), display_name); - item = create_menu_item (self, "document-open", label, - G_CALLBACK (open_drive), mounted); - g_free (label); - } - gtk_container_add (GTK_CONTAINER (self->popup_menu), item); - - if (mounted) { - label = g_strdup_printf (_("Un_mount %s"), display_name); - item = create_menu_item (self, NULL, label, - G_CALLBACK (unmount_drive), TRUE); - g_free (label); - gtk_container_add (GTK_CONTAINER (self->popup_menu), item); - } else { - label = g_strdup_printf (_("_Mount %s"), display_name); - item = create_menu_item (self, NULL, label, - G_CALLBACK (mount_drive), TRUE); - g_free (label); - gtk_container_add (GTK_CONTAINER (self->popup_menu), item); - } - - if (ejectable) { - label = g_strdup_printf (_("_Eject %s"), display_name); - item = create_menu_item (self, "media-eject", label, - G_CALLBACK (eject_drive), TRUE); - g_free (label); - gtk_container_add (GTK_CONTAINER (self->popup_menu), item); - } - - /*Set up custom theme and transparency support */ - GtkWidget *toplevel = gtk_widget_get_toplevel (self->popup_menu); - /* Fix any failures of compiz/other wm's to communicate with gtk for transparency */ - GdkScreen *screen2 = gtk_widget_get_screen (GTK_WIDGET (toplevel)); - GdkVisual *visual = gdk_screen_get_rgba_visual (screen2); - gtk_widget_set_visual (GTK_WIDGET (toplevel), visual); - /*set menu and it's toplevel window to follow panel theme */ - GtkStyleContext *context; - context = gtk_widget_get_style_context (GTK_WIDGET (toplevel)); - gtk_style_context_add_class (context,"gnome-panel-menu-bar"); - gtk_style_context_add_class (context,"mate-panel-menu-bar"); -} diff --git a/drivemount/drive-button.h b/drivemount/drive-button.h deleted file mode 100644 index fdab2f16..00000000 --- a/drivemount/drive-button.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- mode: C; c-basic-offset: 4 -*- - * Drive Mount Applet - * Copyright (c) 2004 Canonical Ltd - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * James Henstridge - */ - -#ifndef DRIVE_BUTTON_H -#define DRIVE_BUTTON_H - -#include - -G_BEGIN_DECLS - -#define DRIVE_TYPE_BUTTON (drive_button_get_type ()) -#define DRIVE_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DRIVE_TYPE_BUTTON, DriveButton)) -#define DRIVE_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DRIVE_TYPE_BUTTON, DriveButtonClass)) -#define DRIVE_IS_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DRIVE_TYPE_BUTTON)) -#define DRIVE_IS_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DRIVE_TYPE_BUTTON)) -#define DRIVE_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DRIVE_TYPE_BUTTON, DriveButtonClass)) - -typedef struct _DriveButton DriveButton; -typedef struct _DriveButtonClass DriveButtonClass; - -struct _DriveButton -{ - GtkButton parent; - - GVolume *volume; - GMount *mount; - int icon_size; - guint update_tag; - - GtkWidget *popup_menu; -}; - -struct _DriveButtonClass -{ - GtkButtonClass parent; -}; - -GType drive_button_get_type (void); -GtkWidget *drive_button_new (GVolume *volume); -GtkWidget *drive_button_new_from_mount (GMount *mount); -void drive_button_queue_update (DriveButton *button); -void drive_button_set_size (DriveButton *button, - int icon_size); - -int drive_button_compare (DriveButton *button, - DriveButton *other_button); - -void drive_button_redraw (gpointer key, gpointer value, gpointer user_data); - -G_END_DECLS - -#endif /* DRIVE_BUTTON_H */ diff --git a/drivemount/drive-list.c b/drivemount/drive-list.c deleted file mode 100644 index b1840051..00000000 --- a/drivemount/drive-list.c +++ /dev/null @@ -1,522 +0,0 @@ -/* -*- mode: C; c-basic-offset: 4 -*- - * Drive Mount Applet - * Copyright (c) 2004 Canonical Ltd - * Copyright 2008 Pierre Ossman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * James Henstridge - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "drive-list.h" -#include "drive-button.h" -#include - -G_DEFINE_TYPE (DriveList, drive_list, GTK_TYPE_GRID); - -static GVolumeMonitor *volume_monitor = NULL; - -static void drive_list_finalize (GObject *object); -static void drive_list_dispose (GObject *object); -static void drive_list_add (GtkContainer *container, GtkWidget *child); -static void drive_list_remove (GtkContainer *container, GtkWidget *child); - -static void mount_added (GVolumeMonitor *monitor, GMount *mount, DriveList *self); -static void mount_changed (GVolumeMonitor *monitor, GMount *mount, DriveList *self); -static void mount_removed (GVolumeMonitor *monitor, GMount *mount, DriveList *self); -static void volume_added (GVolumeMonitor *monitor, GVolume *volume, DriveList *self); -static void volume_changed (GVolumeMonitor *monitor, GVolume *volume, DriveList *self); -static void volume_removed (GVolumeMonitor *monitor, GVolume *volume, DriveList *self); -static void add_volume (DriveList *self, GVolume *volume); -static void remove_volume (DriveList *self, GVolume *volume); -static void add_mount (DriveList *self, GMount *mount); -static void remove_mount (DriveList *self, GMount *mount); -static void queue_relayout (DriveList *self); - -static void -drive_list_class_init (DriveListClass *class) -{ - G_OBJECT_CLASS (class)->finalize = drive_list_finalize; - G_OBJECT_CLASS (class)->dispose = drive_list_dispose; - GTK_CONTAINER_CLASS (class)->add = drive_list_add; - GTK_CONTAINER_CLASS (class)->remove = drive_list_remove; -} - -static void -drive_list_init (DriveList *self) -{ - GList *volumes, *mounts, *tmp; - - gtk_grid_set_column_homogeneous (GTK_GRID (self), TRUE); - gtk_grid_set_row_homogeneous (GTK_GRID (self), TRUE); - - self->volumes = g_hash_table_new (NULL, NULL); - self->mounts = g_hash_table_new (NULL, NULL); - self->orientation = GTK_ORIENTATION_HORIZONTAL; - self->layout_tag = 0; - self->settings = g_settings_new ("org.mate.drivemount"); - self->icon_size = 24; - self->relief = GTK_RELIEF_NORMAL; - - g_signal_connect (self->settings, - "changed::drivemount-checkmark-color", - G_CALLBACK (settings_color_changed), - self); - - /* listen for drive connects/disconnects, and add - * currently connected drives. */ - self->count = 0; - if (!volume_monitor) - volume_monitor = g_volume_monitor_get (); - - g_signal_connect_object (volume_monitor, "mount_added", - G_CALLBACK (mount_added), self, 0); - g_signal_connect_object (volume_monitor, "mount_changed", - G_CALLBACK (mount_changed), self, 0); - g_signal_connect_object (volume_monitor, "mount_removed", - G_CALLBACK (mount_removed), self, 0); - g_signal_connect_object (volume_monitor, "volume_added", - G_CALLBACK (volume_added), self, 0); - g_signal_connect_object (volume_monitor, "volume_changed", - G_CALLBACK (volume_changed), self, 0); - g_signal_connect_object (volume_monitor, "volume_removed", - G_CALLBACK (volume_removed), self, 0); - volumes = g_volume_monitor_get_volumes (volume_monitor); - for (tmp = volumes; tmp != NULL; tmp = tmp->next) { - GVolume *volume = tmp->data; - add_volume (self, volume); - g_object_unref (volume); - self->count++; - } - g_list_free (volumes); - - mounts = g_volume_monitor_get_mounts (volume_monitor); - for (tmp = mounts; tmp != NULL; tmp = tmp->next) { - GMount *mount = tmp->data; - add_mount (self, mount); - g_object_unref (mount); - self->count++; - } - self->dummy = drive_button_new (NULL); - gtk_button_set_relief (GTK_BUTTON (self->dummy), self->relief); - drive_button_set_size (DRIVE_BUTTON (self->dummy), self->icon_size); - - if (self->count == 0) { - gtk_container_add (GTK_CONTAINER (self), self->dummy); - queue_relayout (self); - drive_button_queue_update (DRIVE_BUTTON (self->dummy)); - } - g_list_free (mounts); -} - -GtkWidget * -drive_list_new (void) -{ - return g_object_new (DRIVE_TYPE_LIST, NULL); -} - -static void -drive_list_finalize (GObject *object) -{ - DriveList *self = DRIVE_LIST (object); - - g_hash_table_destroy (self->volumes); - g_hash_table_destroy (self->mounts); - g_object_unref (self->settings); - - if (G_OBJECT_CLASS (drive_list_parent_class)->finalize) - (* G_OBJECT_CLASS (drive_list_parent_class)->finalize) (object); -} - -static void -drive_list_dispose (GObject *object) -{ - DriveList *self = DRIVE_LIST (object); - - g_signal_handlers_disconnect_by_func (volume_monitor, - G_CALLBACK (mount_added), self); - g_signal_handlers_disconnect_by_func (volume_monitor, - G_CALLBACK (mount_changed), self); - g_signal_handlers_disconnect_by_func (volume_monitor, - G_CALLBACK (mount_removed), self); - g_signal_handlers_disconnect_by_func (volume_monitor, - G_CALLBACK (volume_added), self); - g_signal_handlers_disconnect_by_func (volume_monitor, - G_CALLBACK (volume_changed), self); - g_signal_handlers_disconnect_by_func (volume_monitor, - G_CALLBACK (volume_removed), self); - - if (self->layout_tag) - g_source_remove (self->layout_tag); - self->layout_tag = 0; - - if (G_OBJECT_CLASS (drive_list_parent_class)->dispose) - (* G_OBJECT_CLASS (drive_list_parent_class)->dispose) (object); -} - -static void -drive_list_add (GtkContainer *container, - GtkWidget *child) -{ - DriveList *self; - DriveButton *button; - - g_return_if_fail (DRIVE_IS_LIST (container)); - g_return_if_fail (DRIVE_IS_BUTTON (child)); - - if (GTK_CONTAINER_CLASS (drive_list_parent_class)->add) - (* GTK_CONTAINER_CLASS (drive_list_parent_class)->add) (container, child); - - self = DRIVE_LIST (container); - button = DRIVE_BUTTON (child); - if (button->volume) - g_hash_table_insert (self->volumes, button->volume, button); - else - g_hash_table_insert (self->mounts, button->mount, button); -} - -static void -drive_list_remove (GtkContainer *container, - GtkWidget *child) -{ - DriveList *self; - DriveButton *button; - - g_return_if_fail (DRIVE_IS_LIST (container)); - g_return_if_fail (DRIVE_IS_BUTTON (child)); - - self = DRIVE_LIST (container); - button = DRIVE_BUTTON (child); - if (button->volume) - g_hash_table_remove (self->volumes, button->volume); - else - g_hash_table_remove (self->mounts, button->mount); - - if (GTK_CONTAINER_CLASS (drive_list_parent_class)->remove) - (* GTK_CONTAINER_CLASS (drive_list_parent_class)->remove) (container, child); -} - -static void -list_buttons (gpointer key, - gpointer value, - gpointer user_data) -{ - GtkWidget *button = value; - GList **sorted_buttons = user_data; - - *sorted_buttons = g_list_insert_sorted (*sorted_buttons, button, - (GCompareFunc)drive_button_compare); -} - -static gboolean -relayout_buttons (gpointer data) -{ - DriveList *self = DRIVE_LIST (data); - GList *sorted_buttons = NULL, *tmp; - int i = 0; - - self->layout_tag = 0; - if ( self->count > 0 ) { - g_hash_table_foreach (self->volumes, list_buttons, &sorted_buttons); - g_hash_table_foreach (self->mounts, list_buttons, &sorted_buttons); - - /* position buttons in the table according to their sorted order */ - for (tmp = sorted_buttons, i = 0; tmp != NULL; tmp = tmp->next, i++) { - GtkWidget *button = tmp->data; - - if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { - gtk_container_child_set (GTK_CONTAINER (self), button, - "left-attach", i + 1, "top-attach", 0, - "width", 1, "height", 1, - NULL); - } - else { - gtk_container_child_set (GTK_CONTAINER (self), button, - "left-attach", 0, "top-attach", i + 1, - "width", 1, "height", 1, - NULL); - } - } - } - else { - gtk_widget_show (self->dummy); - if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { - gtk_container_child_set (GTK_CONTAINER (self), self->dummy, - "left-attach", i + 1, "top-attach", 0, - "width", 1, "height", 1, - NULL); - } - else { - gtk_container_child_set (GTK_CONTAINER (self), self->dummy, - "left-attach", 0, "top-attach", i + 1, - "width", 1, "height", 1, - NULL); - } - } - return FALSE; -} - -static void -queue_relayout (DriveList *self) -{ - if (!self->layout_tag) { - self->layout_tag = g_idle_add (relayout_buttons, self); - } -} - -static void -mount_added (GVolumeMonitor *monitor, - GMount *mount, - DriveList *self) -{ - add_mount (self, mount); - self->count++; - if (self->count == 1) - gtk_container_remove (GTK_CONTAINER (self), g_object_ref (self->dummy)); - - mount_changed (monitor, mount, self); -} - -static void -mount_changed (GVolumeMonitor *monitor, - GMount *mount, - DriveList *self) -{ - GVolume *volume; - DriveButton *button = NULL;; - - volume = g_mount_get_volume (mount); - if (volume) { - button = g_hash_table_lookup (self->volumes, volume); - g_object_unref (volume); - } else { - button = g_hash_table_lookup (self->mounts, mount); - } - if (button) - drive_button_queue_update (button); -} - -static void -mount_removed (GVolumeMonitor *monitor, - GMount *mount, - DriveList *self) -{ - remove_mount (self, mount); - mount_changed (monitor, mount, self); - self->count--; - if (self->count == 0) { - gtk_container_add (GTK_CONTAINER (self), self->dummy); - queue_relayout (self); - } -} - -static void -volume_added (GVolumeMonitor *monitor, - GVolume *volume, - DriveList *self) -{ - add_volume (self, volume); - self->count++; - if (self->count == 1) - gtk_container_remove (GTK_CONTAINER (self), g_object_ref (self->dummy)); -} - -static void -volume_changed (GVolumeMonitor *monitor, - GVolume *volume, - DriveList *self) -{ - DriveButton *button = NULL;; - - button = g_hash_table_lookup (self->volumes, volume); - if (button) - drive_button_queue_update (button); -} - -static void -volume_removed (GVolumeMonitor *monitor, - GVolume *volume, - DriveList *self) -{ - remove_volume (self, volume); - self->count--; - if (self->count == 0) { - gtk_container_add (GTK_CONTAINER (self), self->dummy); - queue_relayout (self); - } -} - -static void -add_volume (DriveList *self, - GVolume *volume) -{ - GtkWidget *button; - - /* if the volume has already been added, return */ - if (g_hash_table_lookup (self->volumes, volume) != NULL) - return; - - button = drive_button_new (volume); - gtk_button_set_relief (GTK_BUTTON (button), self->relief); - drive_button_set_size (DRIVE_BUTTON (button), self->icon_size); - gtk_container_add (GTK_CONTAINER (self), button); - gtk_widget_show (button); - queue_relayout (self); -} - -static void -remove_volume (DriveList *self, - GVolume *volume) -{ - GtkWidget *button; - - /* if the volume has already been added, return */ - button = g_hash_table_lookup (self->volumes, volume); - if (button) { - gtk_container_remove (GTK_CONTAINER (self), button); - queue_relayout (self); - } -} - -static void -add_mount (DriveList *self, - GMount *mount) -{ - GtkWidget *button; - GVolume *volume; - - /* ignore mounts reported as shadowed */ - if (g_mount_is_shadowed (mount)) { - return; - } - - /* ignore mounts attached to a volume */ - volume = g_mount_get_volume (mount); - if (volume) { - g_object_unref (volume); - return; - } - - /* if the mount has already been added, return */ - if (g_hash_table_lookup (self->mounts, mount) != NULL) - return; - - button = drive_button_new_from_mount (mount); - gtk_button_set_relief (GTK_BUTTON (button), self->relief); - drive_button_set_size (DRIVE_BUTTON (button), self->icon_size); - gtk_container_add (GTK_CONTAINER (self), button); - gtk_widget_show (button); - queue_relayout (self); -} - -static void -remove_mount (DriveList *self, - GMount *mount) -{ - GtkWidget *button; - - /* if the mount has already been added, return */ - button = g_hash_table_lookup (self->mounts, mount); - if (button) { - gtk_container_remove (GTK_CONTAINER (self), button); - queue_relayout (self); - } -} - -void -drive_list_set_orientation (DriveList *self, - GtkOrientation orientation) -{ - g_return_if_fail (DRIVE_IS_LIST (self)); - - if (orientation != self->orientation) { - self->orientation = orientation; - queue_relayout (self); - } -} - -static void -set_icon_size (gpointer key, - gpointer value, - gpointer user_data) -{ - DriveButton *button = value; - DriveList *self = user_data; - - drive_button_set_size (button, self->icon_size); -} - - -void -drive_list_set_panel_size (DriveList *self, - int panel_size) -{ - g_return_if_fail (DRIVE_IS_LIST (self)); - - if (self->icon_size != panel_size) { - self->icon_size = panel_size; - g_hash_table_foreach (self->volumes, set_icon_size, self); - g_hash_table_foreach (self->mounts, set_icon_size, self); - } -} - -void -drive_list_redraw (DriveList *self) -{ - g_hash_table_foreach (self->volumes, drive_button_redraw, self); - g_hash_table_foreach (self->mounts, drive_button_redraw, self); -} - -void -settings_color_changed (GSettings *settings, - gchar *key, - DriveList *drive_list) -{ - g_return_if_fail (DRIVE_IS_LIST (drive_list)); - drive_list_redraw (drive_list); -} - -static void -set_button_relief (gpointer key, - gpointer value, - gpointer user_data) -{ - GtkButton *button = value; - DriveList *self = user_data; - - gtk_button_set_relief (button, self->relief); -} - -void -drive_list_set_transparent (DriveList *self, - gboolean transparent) -{ - GtkReliefStyle relief; - - relief = transparent ? GTK_RELIEF_NONE : GTK_RELIEF_NORMAL; - - if (relief == self->relief) - return; - - self->relief = relief; - g_hash_table_foreach (self->volumes, set_button_relief, self); - g_hash_table_foreach (self->mounts, set_button_relief, self); -} diff --git a/drivemount/drive-list.h b/drivemount/drive-list.h deleted file mode 100644 index e2da7333..00000000 --- a/drivemount/drive-list.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- mode: C; c-basic-offset: 4 -*- - * Drive Mount Applet - * Copyright (c) 2004 Canonical Ltd - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * James Henstridge - */ - -#ifndef DRIVE_LIST_H -#define DRIVE_LIST_H - -#include - -G_BEGIN_DECLS - -#define DRIVE_TYPE_LIST (drive_list_get_type ()) -#define DRIVE_LIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DRIVE_TYPE_LIST, DriveList)) -#define DRIVE_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DRIVE_TYPE_LIST, DriveListClass)) -#define DRIVE_IS_LIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DRIVE_TYPE_LIST)) -#define DRIVE_IS_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DRIVE_TYPE_LIST)) -#define DRIVE_LIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DRIVE_TYPE_LIST, DriveListClass)) - -typedef struct _DriveList DriveList; -typedef struct _DriveListClass DriveListClass; - -struct _DriveList -{ - GtkGrid parent; - - GHashTable *volumes; - GHashTable *mounts; - GtkOrientation orientation; - guint layout_tag; - GtkReliefStyle relief; - GtkWidget *dummy; - gint count; - - GSettings *settings; - - int icon_size; -}; - -struct _DriveListClass -{ - GtkGridClass parent_class; -}; - -GType drive_list_get_type (void); -GtkWidget *drive_list_new (void); -void drive_list_set_orientation (DriveList *list, - GtkOrientation orientation); -void drive_list_set_panel_size (DriveList *list, - int panel_size); -void drive_list_set_transparent (DriveList *self, - gboolean transparent); -void drive_list_redraw (DriveList *self); -void settings_color_changed (GSettings *settings, gchar *key, DriveList *drive_list); - -#endif /* DRIVE_LIST_H */ diff --git a/drivemount/drivemount-applet-menu.xml b/drivemount/drivemount-applet-menu.xml deleted file mode 100644 index efc26591..00000000 --- a/drivemount/drivemount-applet-menu.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/drivemount/drivemount-resources.gresource.xml b/drivemount/drivemount-resources.gresource.xml deleted file mode 100644 index 3a8c57a8..00000000 --- a/drivemount/drivemount-resources.gresource.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - drivemount-applet-menu.xml - - diff --git a/drivemount/drivemount.c b/drivemount/drivemount.c deleted file mode 100644 index d6a77f20..00000000 --- a/drivemount/drivemount.c +++ /dev/null @@ -1,230 +0,0 @@ -/* -*- mode: C; c-basic-offset: 4 -*- - * Drive Mount Applet - * Copyright (c) 2004 Canonical Ltd - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * James Henstridge - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include -#include -#include - -#include "drive-list.h" - -static const char drivemount_iid[] = "DriveMountApplet"; -static const char factory_iid[] = "DriveMountAppletFactory"; - -static void -change_orient (MatePanelApplet *applet, - MatePanelAppletOrient o, - DriveList *drive_list) -{ - GtkOrientation orientation; - - switch (o) { - case MATE_PANEL_APPLET_ORIENT_LEFT: - case MATE_PANEL_APPLET_ORIENT_RIGHT: - orientation = GTK_ORIENTATION_VERTICAL; - break; - case MATE_PANEL_APPLET_ORIENT_UP: - case MATE_PANEL_APPLET_ORIENT_DOWN: - default: - orientation = GTK_ORIENTATION_HORIZONTAL; - } - drive_list_set_orientation (drive_list, orientation); -} - -static void -size_allocate (MatePanelApplet *applet, - GdkRectangle *allocation, - DriveList *drive_list) -{ - int size; - - switch (mate_panel_applet_get_orient (applet)) { - case MATE_PANEL_APPLET_ORIENT_LEFT: - case MATE_PANEL_APPLET_ORIENT_RIGHT: - size = allocation->width; - break; - case MATE_PANEL_APPLET_ORIENT_UP: - case MATE_PANEL_APPLET_ORIENT_DOWN: - default: - size = allocation->height; - } - drive_list_set_panel_size (drive_list, size); -} - -static void -change_background (MatePanelApplet *applet, - MatePanelAppletBackgroundType type, - GdkColor *colour, - cairo_pattern_t *pattern, - DriveList *drivelist) -{ - switch (type) { - case PANEL_NO_BACKGROUND: - drive_list_set_transparent (drivelist, FALSE); - break; - case PANEL_COLOR_BACKGROUND: - case PANEL_PIXMAP_BACKGROUND: - drive_list_set_transparent (drivelist, TRUE); - } -} - -static void -display_about_dialog (GtkAction *action, - DriveList *drive_list) -{ - const gchar *authors[] = { - "James Henstridge ", - NULL - }; - - const gchar *documenters[] = { - "Dan Mueth ", - "John Fleck ", - N_("MATE Documentation Team"), - NULL - }; - -#ifdef ENABLE_NLS - const char **p; - for (p = documenters; *p; ++p) - *p = _(*p); -#endif - - gtk_show_about_dialog (NULL, - "title", _("About Disk Mounter"), - "version", VERSION, - "copyright", _("Copyright \xC2\xA9 2004 Canonical Ltd\n" - "Copyright \xc2\xa9 2012-2020 MATE developers"), - "comments", _("Applet for mounting and unmounting block volumes."), - "authors", authors, - "documenters", documenters, - "translator-credits", _("translator-credits"), - "logo_icon_name", "media-floppy", - NULL); -} - -static void -display_help (GtkAction *action, - DriveList *drive_list) -{ - GdkScreen *screen; - GError *error = NULL; - - screen = gtk_widget_get_screen (GTK_WIDGET (drive_list)); - - gtk_show_uri_on_window (NULL, - "help:mate-drivemount", - gtk_get_current_event_time (), - &error); - - if (error) { - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("There was an error displaying help: %s"), - error->message); - g_signal_connect (dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); - gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); - gtk_window_set_screen (GTK_WINDOW (dialog), screen); - gtk_widget_show (dialog); - g_error_free (error); - } -} - -static const GtkActionEntry applet_menu_actions[] = { - { "Help", "help-browser", N_("_Help"), - NULL, NULL, - G_CALLBACK (display_help) }, - { "About", "help-about", N_("_About"), - NULL, NULL, - G_CALLBACK (display_about_dialog) } -}; - -static gboolean -applet_factory (MatePanelApplet *applet, - const char *iid, - gpointer user_data) -{ - gboolean ret = FALSE; - GtkWidget *drive_list; - AtkObject *ao; - GtkActionGroup *action_group; - - if (!strcmp (iid, drivemount_iid)) { - g_set_application_name (_("Disk Mounter")); - - gtk_window_set_default_icon_name ("media-floppy"); - - mate_panel_applet_set_flags (applet, MATE_PANEL_APPLET_EXPAND_MINOR); - - drive_list = drive_list_new (); - - gtk_container_add (GTK_CONTAINER (applet), drive_list); - - g_signal_connect_object (applet, "change_orient", - G_CALLBACK (change_orient), drive_list, 0); - g_signal_connect_object (applet, "size_allocate", - G_CALLBACK (size_allocate), drive_list, 0); - g_signal_connect (applet, "change_background", - G_CALLBACK (change_background), drive_list); - - /* set initial state */ - change_orient (applet, - mate_panel_applet_get_orient (applet), - DRIVE_LIST (drive_list)); - - action_group = gtk_action_group_new ("DriveMount Applet Actions"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (action_group, - applet_menu_actions, - G_N_ELEMENTS (applet_menu_actions), - drive_list); - mate_panel_applet_setup_menu_from_resource (applet, - DRIVEMOUNT_RESOURCE_PATH "drivemount-applet-menu.xml", - action_group); - g_object_unref (action_group); - - ao = gtk_widget_get_accessible (GTK_WIDGET (applet)); - atk_object_set_name (ao, _("Disk Mounter")); - - gtk_widget_show_all (GTK_WIDGET (applet)); - - ret = TRUE; - } - - return ret; -} - -MATE_PANEL_APPLET_OUT_PROCESS_FACTORY (factory_iid, - PANEL_TYPE_APPLET, - "Drive-Mount-Applet", - applet_factory, NULL) - diff --git a/drivemount/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in b/drivemount/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in deleted file mode 100644 index 637628d2..00000000 --- a/drivemount/org.mate.applets.DriveMountApplet.mate-panel-applet.desktop.in.in +++ /dev/null @@ -1,17 +0,0 @@ -[Applet Factory] -Id=DriveMountAppletFactory -Location=@LIBEXECDIR@/mate-drivemount-applet -Name=Drive Mount Applet Factory -Description=Factory for drive mount applet - -[DriveMountApplet] -Name=Disk Mounter -Description=Mount local disks and devices -# Translators: Do NOT translate or transliterate this text (this is an icon file name)! -Icon=media-floppy -MateComponentId=OAFIID:MATE_DriveMountApplet -X-MATE-Bugzilla-Bugzilla=MATE -X-MATE-Bugzilla-Product=mate-applets -X-MATE-Bugzilla-Component=Disk Mounter (drivemount) -X-MATE-Bugzilla-Version=@VERSION@ -X-MATE-Bugzilla-OtherBinaries=drivemount_applet2 diff --git a/drivemount/org.mate.drivemount.gschema.xml.in b/drivemount/org.mate.drivemount.gschema.xml.in deleted file mode 100644 index 24ffe871..00000000 --- a/drivemount/org.mate.drivemount.gschema.xml.in +++ /dev/null @@ -1,9 +0,0 @@ - - - - '#00e300' - Checkmark color for mounted drive or share - Default color in a hex value. - - - diff --git a/drivemount/org.mate.panel.applet.DriveMountAppletFactory.service.in b/drivemount/org.mate.panel.applet.DriveMountAppletFactory.service.in deleted file mode 100644 index 90d44b42..00000000 --- a/drivemount/org.mate.panel.applet.DriveMountAppletFactory.service.in +++ /dev/null @@ -1,3 +0,0 @@ -[D-BUS Service] -Name=org.mate.panel.applet.DriveMountAppletFactory -Exec=@LIBEXECDIR@/mate-drivemount-applet diff --git a/drivemount/src/Makefile.am b/drivemount/src/Makefile.am new file mode 100644 index 00000000..28b273c0 --- /dev/null +++ b/drivemount/src/Makefile.am @@ -0,0 +1,43 @@ +NULL = + +AM_CPPFLAGS = \ + -I. \ + -I$(srcdir) \ + -DDRIVEMOUNT_RESOURCE_PATH=\""/org/mate/mate-applets/drivemount/"\" \ + ${WARN_CFLAGS} \ + $(MATE_APPLETS4_CFLAGS) \ + $(NULL) + +libexec_PROGRAMS = mate-drivemount-applet + +BUILT_SOURCES = \ + drivemount-resources.c \ + drivemount-resources.h \ + $(NULL) + +nodist_mate_drivemount_applet_SOURCES = \ + $(BUILT_SOURCES) \ + $(NULL) + +mate_drivemount_applet_SOURCES = \ + drivemount.c \ + drive-list.c \ + drive-list.h \ + drive-button.c \ + drive-button.h \ + $(NULL) + +mate_drivemount_applet_LDADD = \ + $(MATE_APPLETS4_LIBS) + +drivemount-resources.c: ../data/drivemount-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/../data/ --generate-dependencies $(srcdir)/../data/drivemount-resources.gresource.xml) + $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/../data/ --generate --c-name drivemount $< + +drivemount-resources.h: ../data/drivemount-resources.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/../data/ --generate-dependencies $(srcdir)/../data/drivemount-resources.gresource.xml) + $(AM_V_GEN)$(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/../data/ --generate --c-name drivemount $< + +CLEANFILES = \ + $(BUILT_SOURCES) \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/drivemount/src/drive-button.c b/drivemount/src/drive-button.c new file mode 100644 index 00000000..f64f38c4 --- /dev/null +++ b/drivemount/src/drive-button.c @@ -0,0 +1,982 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * Drive Mount Applet + * Copyright (c) 2004 Canonical Ltd + * Copyright 2008 Pierre Ossman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * James Henstridge + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "drive-button.h" +#include +#include +#include + +#include + +enum { + CMD_NONE, + CMD_MOUNT_OR_PLAY, + CMD_UNMOUNT, + CMD_EJECT +}; + +/* type registration boilerplate code */ +G_DEFINE_TYPE (DriveButton, drive_button, GTK_TYPE_BUTTON) + +static void drive_button_set_volume (DriveButton *self, + GVolume *volume); +static void drive_button_set_mount (DriveButton *self, + GMount *mount); +static void drive_button_reset_popup (DriveButton *self); +static void drive_button_ensure_popup (DriveButton *self); + +static void drive_button_dispose (GObject *object); +#if 0 +static void drive_button_unrealize (GtkWidget *widget); +#endif /* 0 */ +static gboolean drive_button_button_press (GtkWidget *widget, + GdkEventButton *event); +static gboolean drive_button_key_press (GtkWidget *widget, + GdkEventKey *event); +static void drive_button_theme_change (GtkIconTheme *icon_theme, + gpointer data); + +static void +drive_button_class_init (DriveButtonClass *class) +{ + G_OBJECT_CLASS (class)->dispose = drive_button_dispose; + GTK_WIDGET_CLASS (class)->button_press_event = drive_button_button_press; + GTK_WIDGET_CLASS (class)->key_press_event = drive_button_key_press; + + GtkCssProvider *provider; + + provider = gtk_css_provider_new (); + + gtk_css_provider_load_from_data (provider, + "#drive-button {\n" + " border-width: 0px;\n" + " padding: 0px;\n" + " margin: 0px;\n" + "}", + -1, NULL); + + gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + g_object_unref (provider); +} + +static void +drive_button_init (DriveButton *self) +{ + GtkWidget *image; + + image = gtk_image_new (); + gtk_container_add (GTK_CONTAINER (self), image); + gtk_widget_show (image); + + self->volume = NULL; + self->mount = NULL; + self->icon_size = 24; + self->update_tag = 0; + + self->popup_menu = NULL; + + gtk_widget_set_name (GTK_WIDGET (self), "drive-button"); +} + +GtkWidget * +drive_button_new (GVolume *volume) +{ + DriveButton *self; + + self = g_object_new (DRIVE_TYPE_BUTTON, NULL); + if (volume != NULL) { + drive_button_set_volume (self, volume); + g_signal_connect (gtk_icon_theme_get_default (), + "changed", G_CALLBACK (drive_button_theme_change), + self); + } + + return (GtkWidget *)self; +} + +GtkWidget * +drive_button_new_from_mount (GMount *mount) +{ + DriveButton *self; + + self = g_object_new (DRIVE_TYPE_BUTTON, NULL); + drive_button_set_mount (self, mount); + + g_signal_connect (gtk_icon_theme_get_default (), + "changed", G_CALLBACK (drive_button_theme_change), + self); + + return (GtkWidget *)self; +} + +static void +drive_button_dispose (GObject *object) +{ + DriveButton *self = DRIVE_BUTTON (object); + + drive_button_set_volume (self, NULL); + + if (self->update_tag) + g_source_remove (self->update_tag); + self->update_tag = 0; + + drive_button_reset_popup (self); + + if (G_OBJECT_CLASS (drive_button_parent_class)->dispose) + (* G_OBJECT_CLASS (drive_button_parent_class)->dispose) (object); +} + +static gboolean +drive_button_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + DriveButton *self = DRIVE_BUTTON (widget); + + /* don't consume non-button1 presses */ + if (event->button == 1) { + drive_button_ensure_popup (self); + if (self->popup_menu) { + gtk_menu_popup_at_widget (GTK_MENU (self->popup_menu), + widget, + GDK_GRAVITY_SOUTH_WEST, + GDK_GRAVITY_NORTH_WEST, + (const GdkEvent*) event); + } + return TRUE; + } + return FALSE; +} + +static gboolean +drive_button_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + DriveButton *self = DRIVE_BUTTON (widget); + + switch (event->keyval) { + case GDK_KEY_KP_Space: + case GDK_KEY_space: + case GDK_KEY_KP_Enter: + case GDK_KEY_Return: + drive_button_ensure_popup (self); + if (self->popup_menu) { + gtk_menu_popup_at_widget (GTK_MENU (self->popup_menu), + widget, + GDK_GRAVITY_SOUTH_WEST, + GDK_GRAVITY_NORTH_WEST, + (const GdkEvent*) event); + } + return TRUE; + } + return FALSE; +} + +static void +drive_button_theme_change (GtkIconTheme *icon_theme, + gpointer data) +{ + drive_button_queue_update (data); +} + +static void +drive_button_set_volume (DriveButton *self, + GVolume *volume) +{ + g_return_if_fail (DRIVE_IS_BUTTON (self)); + + if (self->volume) { + g_object_unref (self->volume); + } + self->volume = NULL; + if (self->mount) { + g_object_unref (self->mount); + } + self->mount = NULL; + + if (volume) { + self->volume = g_object_ref (volume); + } + drive_button_queue_update (self); +} + +static void +drive_button_set_mount (DriveButton *self, + GMount *mount) +{ + g_return_if_fail (DRIVE_IS_BUTTON (self)); + + if (self->volume) { + g_object_unref (self->volume); + } + self->volume = NULL; + if (self->mount) { + g_object_unref (self->mount); + } + self->mount = NULL; + + if (mount) { + self->mount = g_object_ref (mount); + } + drive_button_queue_update (self); +} + +static gboolean +drive_button_update (gpointer user_data) +{ + DriveButton *self; + GdkScreen *screen; + GtkIconTheme *icon_theme; + GtkIconInfo *icon_info; + GIcon *icon; + int width, height, scale; + cairo_t *cr; + cairo_surface_t *surface = NULL; + cairo_surface_t *tmp_surface = NULL; + GtkRequisition button_req, image_req; + char *display_name, *tip; + + g_return_val_if_fail (DRIVE_IS_BUTTON (user_data), FALSE); + self = DRIVE_BUTTON (user_data); + self->update_tag = 0; + + /* base the icon size on the desired button size */ + drive_button_reset_popup (self); + scale = gtk_widget_get_scale_factor (GTK_WIDGET (self)); + gtk_widget_get_preferred_size (GTK_WIDGET (self), NULL, &button_req); + gtk_widget_get_preferred_size (gtk_bin_get_child (GTK_BIN (self)), NULL, &image_req); + width = (self->icon_size - (button_req.width - image_req.width)) / scale; + height = (self->icon_size - (button_req.height - image_req.height)) / scale; + + /* if no volume or mount, display general image */ + if (!self->volume && !self->mount) + { + gtk_widget_set_tooltip_text (GTK_WIDGET (self), _("nothing to mount")); + screen = gtk_widget_get_screen (GTK_WIDGET (self)); + icon_theme = gtk_icon_theme_get_for_screen (screen); //m + // note - other good icon would be emblem-unreadable + icon_info = gtk_icon_theme_lookup_icon_for_scale (icon_theme, "media-floppy", + MIN (width, height), scale, + GTK_ICON_LOOKUP_USE_BUILTIN); + if (icon_info) { + surface = gtk_icon_info_load_surface (icon_info, NULL, NULL); + g_object_unref (icon_info); + } + + if (!surface) + return FALSE; + + if (gtk_bin_get_child (GTK_BIN (self)) != NULL) + gtk_image_set_from_surface (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (self))), surface); + + return FALSE; + } + + gboolean is_mounted = FALSE; + + if (self->volume) + { + GMount *mount; + + display_name = g_volume_get_name (self->volume); + mount = g_volume_get_mount (self->volume); + + if (mount) + { + is_mounted = TRUE; + tip = g_strdup_printf ("%s\n%s", display_name, _("(mounted)")); + icon = g_mount_get_icon (mount); + g_object_unref (mount); + } + else + { + is_mounted = FALSE; + tip = g_strdup_printf ("%s\n%s", display_name, _("(not mounted)")); + icon = g_volume_get_icon (self->volume); + } + } else + { + is_mounted = TRUE; + display_name = g_mount_get_name (self->mount); + tip = g_strdup_printf ("%s\n%s", display_name, _("(mounted)")); + icon = g_mount_get_icon (self->mount); + } + + gtk_widget_set_tooltip_text (GTK_WIDGET (self), tip); + g_free (tip); + g_free (display_name); + + screen = gtk_widget_get_screen (GTK_WIDGET (self)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (icon_theme, icon, + MIN (width, height), scale, + GTK_ICON_LOOKUP_USE_BUILTIN); + if (icon_info) + { + surface = gtk_icon_info_load_surface (icon_info, NULL, NULL); + g_object_unref (icon_info); + } + + g_object_unref (icon); + + if (!surface) + return FALSE; + + // create a new surface because icon image can be shared by system + tmp_surface = cairo_surface_create_similar (surface, + cairo_surface_get_content (surface), + cairo_image_surface_get_width (surface) / scale, + cairo_image_surface_get_height (surface) / scale); + + // if mounted, change icon + if (is_mounted) + { + int icon_width, icon_height, rowstride, n_channels, x, y; + guchar *pixels, *p; + gboolean has_alpha; + + has_alpha = cairo_surface_get_content (tmp_surface) != CAIRO_CONTENT_COLOR; + n_channels = 3; + if (has_alpha) + n_channels++; + + icon_width = cairo_image_surface_get_width (tmp_surface); + icon_height = cairo_image_surface_get_height (tmp_surface); + + rowstride = cairo_image_surface_get_stride (tmp_surface); + pixels = cairo_image_surface_get_data (tmp_surface); + + GdkRGBA color; + GSettings *settings; + settings = g_settings_new ("org.mate.drivemount"); + gchar *color_string = g_settings_get_string (settings, "drivemount-checkmark-color"); + if (!color_string) + color_string = g_strdup ("#00ff00"); + gdk_rgba_parse (&color, color_string); + g_free (color_string); + g_object_unref (settings); + + guchar red = color.red*255; + guchar green = color.green*255; + guchar blue = color.blue*255; + + const gdouble ratio = 0.65; + gdouble y_start = icon_height * ratio; + gdouble x_start = icon_height * (1 + ratio); + + for (y = y_start; y < icon_height; y++) + for (x = x_start - y; x < icon_width; x++) + { + p = pixels + y * rowstride + x * n_channels; + p[0] = red; + p[1] = green; + p[2] = blue; + if (has_alpha) + p[3] = 255; + } + } + + cr = cairo_create (tmp_surface); + cairo_set_operator (cr, CAIRO_OPERATOR_OVERLAY); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + + gtk_image_set_from_surface (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (self))), tmp_surface); + + cairo_surface_destroy (surface); + cairo_surface_destroy (tmp_surface); + + gtk_widget_get_preferred_size (GTK_WIDGET (self), NULL, &button_req); + + return FALSE; +} + +void +drive_button_queue_update (DriveButton *self) +{ + if (!self->update_tag) { + self->update_tag = g_idle_add (drive_button_update, self); + } +} + +void +drive_button_set_size (DriveButton *self, + int icon_size) +{ + g_return_if_fail (DRIVE_IS_BUTTON (self)); + + if (self->icon_size != icon_size) { + self->icon_size = icon_size; + drive_button_queue_update (self); + } +} + +void +drive_button_redraw (gpointer key, + gpointer value, + gpointer user_data) +{ + DriveButton *button = value; + drive_button_queue_update (button); +} + +int +drive_button_compare (DriveButton *button, + DriveButton *other_button) +{ + /* sort drives before driveless volumes volumes */ + if (button->volume) { + if (other_button->volume) { + int cmp; + gchar *str1, *str2; + + str1 = g_volume_get_name (button->volume); + str2 = g_volume_get_name (other_button->volume); + cmp = g_utf8_collate (str1, str2); + g_free (str2); + g_free (str1); + + return cmp; + } else { + return -1; + } + } else { + if (other_button->volume) { + return 1; + } else { + int cmp; + gchar *str1, *str2; + + str1 = g_mount_get_name (button->mount); + str2 = g_mount_get_name (other_button->mount); + cmp = g_utf8_collate (str1, str2); + g_free (str2); + g_free (str1); + + return cmp; + } + } +} + +static void +drive_button_reset_popup (DriveButton *self) +{ + if (self->popup_menu) + gtk_widget_destroy (GTK_WIDGET (self->popup_menu)); + self->popup_menu = NULL; +} + +#if 0 +static void +popup_menu_detach (GtkWidget *attach_widget, GtkMenu *menu) +{ + DRIVE_BUTTON (attach_widget)->popup_menu = NULL; +} +#endif /* 0 */ + +static char * +escape_underscores (const char *str) +{ + char *new_str; + int i, j, count; + + /* count up how many underscores are in the string */ + count = 0; + for (i = 0; str[i] != '\0'; i++) { + if (str[i] == '_') + count++; + } + /* copy to new string, doubling up underscores */ + new_str = g_new (char, i + count + 1); + for (i = j = 0; str[i] != '\0'; i++, j++) { + new_str[j] = str[i]; + if (str[i] == '_') + new_str[++j] = '_'; + } + new_str[j] = '\0'; + return new_str; +} +static GtkWidget * +create_menu_item (DriveButton *self, + const gchar *icon_name, + const gchar *label, + GCallback callback, + gboolean sensitive) +{ + GtkWidget *item, *image; + + item = gtk_image_menu_item_new_with_mnemonic (label); + if (icon_name) { + image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + gtk_widget_show (image); + } + if (callback) + g_signal_connect_object (item, "activate", callback, self, + G_CONNECT_SWAPPED); + gtk_widget_set_sensitive (item, sensitive); + gtk_widget_show (item); + return item; +} + +static void +open_drive (DriveButton *self, + GtkWidget *item) +{ + GdkScreen *screen; + GtkWidget *dialog; + GError *error = NULL; + GFile *file = NULL; + GList *files = NULL; + GdkAppLaunchContext *launch_context; + GAppInfo *app_info; + + if (self->volume) { + GMount *mount; + + mount = g_volume_get_mount (self->volume); + if (mount) { + file = g_mount_get_root (mount); + g_object_unref (mount); + } + } else if (self->mount) { + file = g_mount_get_root (self->mount); + } else + g_return_if_reached (); + + app_info = g_app_info_get_default_for_type ("inode/directory", FALSE); + if (!app_info) + app_info = G_APP_INFO (g_desktop_app_info_new ("caja.desktop")); + + if (app_info) { + GdkDisplay *display = gtk_widget_get_display (item); + launch_context = gdk_display_get_app_launch_context (display); + screen = gtk_widget_get_screen (GTK_WIDGET (self)); + gdk_app_launch_context_set_screen (launch_context, screen); + files = g_list_prepend (files, file); + g_app_info_launch (app_info, + files, + G_APP_LAUNCH_CONTEXT (launch_context), + &error); + + g_object_unref (launch_context); + g_list_free (files); + } + + if (!app_info || error) { + dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Cannot execute Caja")); + if (error) + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message); + else + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "Could not find Caja"); + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + g_error_free (error); + } + + g_object_unref (file); +} + +/* copied from mate-volume-manager/src/manager.c maybe there is a better way than + * duplicating this code? */ + +/* + * gvm_run_command - run the given command, replacing %d with the device node + * and %m with the given path + */ +static void +gvm_run_command (const char *device, + const char *command, + const char *path) +{ + char *argv[4]; + gchar *new_command; + GError *error = NULL; + GString *exec = g_string_new (NULL); + char *p, *q; + + /* perform s/%d/device/ and s/%m/path/ */ + new_command = g_strdup (command); + q = new_command; + p = new_command; + while ((p = strchr (p, '%')) != NULL) { + if (*(p + 1) == 'd') { + *p = '\0'; + g_string_append (exec, q); + g_string_append (exec, device); + q = p + 2; + p = p + 2; + } else if (*(p + 1) == 'm') { + *p = '\0'; + g_string_append (exec, q); + g_string_append (exec, path); + q = p + 2; + p = p + 2; + } else { + /* Ignore anything else. */ + p++; + } + } + g_string_append (exec, q); + + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = exec->str; + argv[3] = NULL; + + g_spawn_async (g_get_home_dir (), argv, NULL, 0, NULL, NULL, + NULL, &error); + if (error) { + g_warning ("failed to exec %s: %s\n", exec->str, error->message); + g_error_free (error); + } + + g_string_free (exec, TRUE); + g_free (new_command); +} + +/* + * gvm_check_dvd_only - is this a Video DVD? + * + * Returns TRUE if this was a Video DVD and FALSE otherwise. + * (the original in gvm was also running the autoplay action, + * I removed that code, so I renamed from gvm_check_dvd to + * gvm_check_dvd_only) + */ +static gboolean +gvm_check_dvd_only (const char *udi, + const char *device, + const char *mount_point) +{ + char *path; + gboolean retval; + + path = g_build_path (G_DIR_SEPARATOR_S, mount_point, "video_ts", NULL); + retval = g_file_test (path, G_FILE_TEST_IS_DIR); + g_free (path); + + /* try the other name, if needed */ + if (retval == FALSE) { + path = g_build_path (G_DIR_SEPARATOR_S, mount_point, + "VIDEO_TS", NULL); + retval = g_file_test (path, G_FILE_TEST_IS_DIR); + g_free (path); + } + + return retval; +} +/* END copied from mate-volume-manager/src/manager.c */ + +static gboolean +check_dvd_video (DriveButton *self) +{ + GFile *file; + char *udi, *device_path, *mount_path; + gboolean result; + GMount *mount; + + if (!self->volume) + return FALSE; + + mount = g_volume_get_mount (self->volume); + if (!mount) + return FALSE; + + file = g_mount_get_root (mount); + g_object_unref (mount); + + if (!file) + return FALSE; + + mount_path = g_file_get_path (file); + + g_object_unref (file); + + device_path = g_volume_get_identifier (self->volume, + G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + udi = g_volume_get_identifier (self->volume, + G_VOLUME_IDENTIFIER_KIND_HAL_UDI); + + result = gvm_check_dvd_only (udi, device_path, mount_path); + + g_free (device_path); + g_free (udi); + g_free (mount_path); + + return result; +} + +static gboolean +check_audio_cd (DriveButton *self) +{ + GFile *file; + char *activation_uri; + GMount *mount; + + if (!self->volume) + return FALSE; + + mount = g_volume_get_mount (self->volume); + if (!mount) + return FALSE; + + file = g_mount_get_root (mount); + g_object_unref (mount); + + if (!file) + return FALSE; + + activation_uri = g_file_get_uri (file); + + g_object_unref (file); + + /* we have an audioCD if the activation URI starts by 'cdda://' */ + gboolean result = (strncmp ("cdda://", activation_uri, 7) == 0); + g_free (activation_uri); + return result; +} + +static void +run_command (DriveButton *self, + const char *command) +{ + GFile *file; + char *mount_path, *device_path; + GMount *mount; + + if (!self->volume) + return; + + mount = g_volume_get_mount (self->volume); + if (!mount) + return; + + file = g_mount_get_root (mount); + g_object_unref (mount); + + g_assert (file); + + mount_path = g_file_get_path (file); + + g_object_unref (file); + + device_path = g_volume_get_identifier (self->volume, + G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); + + gvm_run_command (device_path, command, mount_path); + + g_free (mount_path); + g_free (device_path); +} + +static void dummy_async_ready_callback (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + /* do nothing */ +} + +static void +mount_drive (DriveButton *self, + GtkWidget *item) +{ + if (self->volume) { + GMountOperation *mount_op = gtk_mount_operation_new (NULL); + g_volume_mount (self->volume, G_MOUNT_MOUNT_NONE, + mount_op, NULL, dummy_async_ready_callback, NULL); + g_object_unref (mount_op); + } else { + g_return_if_reached (); + } +} + +static void +unmount_drive (DriveButton *self, + GtkWidget *item) +{ + if (self->volume) { + GMount *mount; + + mount = g_volume_get_mount (self->volume); + if (mount) { + g_mount_unmount_with_operation (mount, G_MOUNT_UNMOUNT_NONE, + NULL, NULL, dummy_async_ready_callback, NULL); + g_object_unref (mount); + } + } else if (self->mount) { + g_mount_unmount_with_operation (self->mount, G_MOUNT_UNMOUNT_NONE, + NULL, NULL, dummy_async_ready_callback, NULL); + } else { + g_return_if_reached (); + } +} + +static void eject_finish (DriveButton *self, + GAsyncResult *res, + gpointer user_data) +{ + /* Do nothing. We shouldn't need this according to the GIO + * docs, but the applet crashes without it using glib 2.18.0 */ +} + +static void +eject_drive (DriveButton *self, + GtkWidget *item) +{ + if (self->volume) { + g_volume_eject_with_operation (self->volume, G_MOUNT_UNMOUNT_NONE, + NULL, NULL, + (GAsyncReadyCallback) eject_finish, + NULL); + } else if (self->mount) { + g_mount_eject_with_operation (self->mount, G_MOUNT_UNMOUNT_NONE, + NULL, NULL, + (GAsyncReadyCallback) eject_finish, + NULL); + } else { + g_return_if_reached (); + } +} +static void +play_autoplay_media (DriveButton *self, + const char *dflt) +{ + run_command (self, dflt); +} + +static void +play_dvd (DriveButton *self, + GtkWidget *item) +{ + /* FIXME add an option to set this */ + play_autoplay_media (self, "totem %d"); +} + +static void +play_cda (DriveButton *self, + GtkWidget *item) +{ + /* FIXME add an option to set this */ + play_autoplay_media (self, "sound-juicer -d %d"); +} + +static void +drive_button_ensure_popup (DriveButton *self) +{ + char *display_name, *tmp, *label; + GtkWidget *item; + gboolean mounted, ejectable; + + if (self->popup_menu) return; + + mounted = FALSE; + + if (self->volume) { + GMount *mount = NULL; + + display_name = g_volume_get_name (self->volume); + ejectable = g_volume_can_eject (self->volume); + + mount = g_volume_get_mount (self->volume); + if (mount) { + mounted = TRUE; + g_object_unref (mount); + } + } else { + if (!G_IS_MOUNT (self->volume)) + return; + else { + display_name = g_mount_get_name (self->mount); + ejectable = g_mount_can_eject (self->mount); + mounted = TRUE; + } + } + + self->popup_menu = gtk_menu_new (); + + /* make sure the display name doesn't look like a mnemonic */ + tmp = escape_underscores (display_name ? display_name : "(none)"); + g_free (display_name); + display_name = tmp; + + if (check_dvd_video (self)) { + item = create_menu_item (self, "media-playback-start", + _("_Play DVD"), G_CALLBACK (play_dvd), + TRUE); + } else if (check_audio_cd (self)) { + item = create_menu_item (self, "media-playback-start", + _("_Play CD"), G_CALLBACK (play_cda), + TRUE); + } else { + label = g_strdup_printf (_("_Open %s"), display_name); + item = create_menu_item (self, "document-open", label, + G_CALLBACK (open_drive), mounted); + g_free (label); + } + gtk_container_add (GTK_CONTAINER (self->popup_menu), item); + + if (mounted) { + label = g_strdup_printf (_("Un_mount %s"), display_name); + item = create_menu_item (self, NULL, label, + G_CALLBACK (unmount_drive), TRUE); + g_free (label); + gtk_container_add (GTK_CONTAINER (self->popup_menu), item); + } else { + label = g_strdup_printf (_("_Mount %s"), display_name); + item = create_menu_item (self, NULL, label, + G_CALLBACK (mount_drive), TRUE); + g_free (label); + gtk_container_add (GTK_CONTAINER (self->popup_menu), item); + } + + if (ejectable) { + label = g_strdup_printf (_("_Eject %s"), display_name); + item = create_menu_item (self, "media-eject", label, + G_CALLBACK (eject_drive), TRUE); + g_free (label); + gtk_container_add (GTK_CONTAINER (self->popup_menu), item); + } + + /*Set up custom theme and transparency support */ + GtkWidget *toplevel = gtk_widget_get_toplevel (self->popup_menu); + /* Fix any failures of compiz/other wm's to communicate with gtk for transparency */ + GdkScreen *screen2 = gtk_widget_get_screen (GTK_WIDGET (toplevel)); + GdkVisual *visual = gdk_screen_get_rgba_visual (screen2); + gtk_widget_set_visual (GTK_WIDGET (toplevel), visual); + /*set menu and it's toplevel window to follow panel theme */ + GtkStyleContext *context; + context = gtk_widget_get_style_context (GTK_WIDGET (toplevel)); + gtk_style_context_add_class (context,"gnome-panel-menu-bar"); + gtk_style_context_add_class (context,"mate-panel-menu-bar"); +} diff --git a/drivemount/src/drive-button.h b/drivemount/src/drive-button.h new file mode 100644 index 00000000..fdab2f16 --- /dev/null +++ b/drivemount/src/drive-button.h @@ -0,0 +1,71 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * Drive Mount Applet + * Copyright (c) 2004 Canonical Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * James Henstridge + */ + +#ifndef DRIVE_BUTTON_H +#define DRIVE_BUTTON_H + +#include + +G_BEGIN_DECLS + +#define DRIVE_TYPE_BUTTON (drive_button_get_type ()) +#define DRIVE_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DRIVE_TYPE_BUTTON, DriveButton)) +#define DRIVE_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DRIVE_TYPE_BUTTON, DriveButtonClass)) +#define DRIVE_IS_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DRIVE_TYPE_BUTTON)) +#define DRIVE_IS_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DRIVE_TYPE_BUTTON)) +#define DRIVE_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DRIVE_TYPE_BUTTON, DriveButtonClass)) + +typedef struct _DriveButton DriveButton; +typedef struct _DriveButtonClass DriveButtonClass; + +struct _DriveButton +{ + GtkButton parent; + + GVolume *volume; + GMount *mount; + int icon_size; + guint update_tag; + + GtkWidget *popup_menu; +}; + +struct _DriveButtonClass +{ + GtkButtonClass parent; +}; + +GType drive_button_get_type (void); +GtkWidget *drive_button_new (GVolume *volume); +GtkWidget *drive_button_new_from_mount (GMount *mount); +void drive_button_queue_update (DriveButton *button); +void drive_button_set_size (DriveButton *button, + int icon_size); + +int drive_button_compare (DriveButton *button, + DriveButton *other_button); + +void drive_button_redraw (gpointer key, gpointer value, gpointer user_data); + +G_END_DECLS + +#endif /* DRIVE_BUTTON_H */ diff --git a/drivemount/src/drive-list.c b/drivemount/src/drive-list.c new file mode 100644 index 00000000..b1840051 --- /dev/null +++ b/drivemount/src/drive-list.c @@ -0,0 +1,522 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * Drive Mount Applet + * Copyright (c) 2004 Canonical Ltd + * Copyright 2008 Pierre Ossman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * James Henstridge + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "drive-list.h" +#include "drive-button.h" +#include + +G_DEFINE_TYPE (DriveList, drive_list, GTK_TYPE_GRID); + +static GVolumeMonitor *volume_monitor = NULL; + +static void drive_list_finalize (GObject *object); +static void drive_list_dispose (GObject *object); +static void drive_list_add (GtkContainer *container, GtkWidget *child); +static void drive_list_remove (GtkContainer *container, GtkWidget *child); + +static void mount_added (GVolumeMonitor *monitor, GMount *mount, DriveList *self); +static void mount_changed (GVolumeMonitor *monitor, GMount *mount, DriveList *self); +static void mount_removed (GVolumeMonitor *monitor, GMount *mount, DriveList *self); +static void volume_added (GVolumeMonitor *monitor, GVolume *volume, DriveList *self); +static void volume_changed (GVolumeMonitor *monitor, GVolume *volume, DriveList *self); +static void volume_removed (GVolumeMonitor *monitor, GVolume *volume, DriveList *self); +static void add_volume (DriveList *self, GVolume *volume); +static void remove_volume (DriveList *self, GVolume *volume); +static void add_mount (DriveList *self, GMount *mount); +static void remove_mount (DriveList *self, GMount *mount); +static void queue_relayout (DriveList *self); + +static void +drive_list_class_init (DriveListClass *class) +{ + G_OBJECT_CLASS (class)->finalize = drive_list_finalize; + G_OBJECT_CLASS (class)->dispose = drive_list_dispose; + GTK_CONTAINER_CLASS (class)->add = drive_list_add; + GTK_CONTAINER_CLASS (class)->remove = drive_list_remove; +} + +static void +drive_list_init (DriveList *self) +{ + GList *volumes, *mounts, *tmp; + + gtk_grid_set_column_homogeneous (GTK_GRID (self), TRUE); + gtk_grid_set_row_homogeneous (GTK_GRID (self), TRUE); + + self->volumes = g_hash_table_new (NULL, NULL); + self->mounts = g_hash_table_new (NULL, NULL); + self->orientation = GTK_ORIENTATION_HORIZONTAL; + self->layout_tag = 0; + self->settings = g_settings_new ("org.mate.drivemount"); + self->icon_size = 24; + self->relief = GTK_RELIEF_NORMAL; + + g_signal_connect (self->settings, + "changed::drivemount-checkmark-color", + G_CALLBACK (settings_color_changed), + self); + + /* listen for drive connects/disconnects, and add + * currently connected drives. */ + self->count = 0; + if (!volume_monitor) + volume_monitor = g_volume_monitor_get (); + + g_signal_connect_object (volume_monitor, "mount_added", + G_CALLBACK (mount_added), self, 0); + g_signal_connect_object (volume_monitor, "mount_changed", + G_CALLBACK (mount_changed), self, 0); + g_signal_connect_object (volume_monitor, "mount_removed", + G_CALLBACK (mount_removed), self, 0); + g_signal_connect_object (volume_monitor, "volume_added", + G_CALLBACK (volume_added), self, 0); + g_signal_connect_object (volume_monitor, "volume_changed", + G_CALLBACK (volume_changed), self, 0); + g_signal_connect_object (volume_monitor, "volume_removed", + G_CALLBACK (volume_removed), self, 0); + volumes = g_volume_monitor_get_volumes (volume_monitor); + for (tmp = volumes; tmp != NULL; tmp = tmp->next) { + GVolume *volume = tmp->data; + add_volume (self, volume); + g_object_unref (volume); + self->count++; + } + g_list_free (volumes); + + mounts = g_volume_monitor_get_mounts (volume_monitor); + for (tmp = mounts; tmp != NULL; tmp = tmp->next) { + GMount *mount = tmp->data; + add_mount (self, mount); + g_object_unref (mount); + self->count++; + } + self->dummy = drive_button_new (NULL); + gtk_button_set_relief (GTK_BUTTON (self->dummy), self->relief); + drive_button_set_size (DRIVE_BUTTON (self->dummy), self->icon_size); + + if (self->count == 0) { + gtk_container_add (GTK_CONTAINER (self), self->dummy); + queue_relayout (self); + drive_button_queue_update (DRIVE_BUTTON (self->dummy)); + } + g_list_free (mounts); +} + +GtkWidget * +drive_list_new (void) +{ + return g_object_new (DRIVE_TYPE_LIST, NULL); +} + +static void +drive_list_finalize (GObject *object) +{ + DriveList *self = DRIVE_LIST (object); + + g_hash_table_destroy (self->volumes); + g_hash_table_destroy (self->mounts); + g_object_unref (self->settings); + + if (G_OBJECT_CLASS (drive_list_parent_class)->finalize) + (* G_OBJECT_CLASS (drive_list_parent_class)->finalize) (object); +} + +static void +drive_list_dispose (GObject *object) +{ + DriveList *self = DRIVE_LIST (object); + + g_signal_handlers_disconnect_by_func (volume_monitor, + G_CALLBACK (mount_added), self); + g_signal_handlers_disconnect_by_func (volume_monitor, + G_CALLBACK (mount_changed), self); + g_signal_handlers_disconnect_by_func (volume_monitor, + G_CALLBACK (mount_removed), self); + g_signal_handlers_disconnect_by_func (volume_monitor, + G_CALLBACK (volume_added), self); + g_signal_handlers_disconnect_by_func (volume_monitor, + G_CALLBACK (volume_changed), self); + g_signal_handlers_disconnect_by_func (volume_monitor, + G_CALLBACK (volume_removed), self); + + if (self->layout_tag) + g_source_remove (self->layout_tag); + self->layout_tag = 0; + + if (G_OBJECT_CLASS (drive_list_parent_class)->dispose) + (* G_OBJECT_CLASS (drive_list_parent_class)->dispose) (object); +} + +static void +drive_list_add (GtkContainer *container, + GtkWidget *child) +{ + DriveList *self; + DriveButton *button; + + g_return_if_fail (DRIVE_IS_LIST (container)); + g_return_if_fail (DRIVE_IS_BUTTON (child)); + + if (GTK_CONTAINER_CLASS (drive_list_parent_class)->add) + (* GTK_CONTAINER_CLASS (drive_list_parent_class)->add) (container, child); + + self = DRIVE_LIST (container); + button = DRIVE_BUTTON (child); + if (button->volume) + g_hash_table_insert (self->volumes, button->volume, button); + else + g_hash_table_insert (self->mounts, button->mount, button); +} + +static void +drive_list_remove (GtkContainer *container, + GtkWidget *child) +{ + DriveList *self; + DriveButton *button; + + g_return_if_fail (DRIVE_IS_LIST (container)); + g_return_if_fail (DRIVE_IS_BUTTON (child)); + + self = DRIVE_LIST (container); + button = DRIVE_BUTTON (child); + if (button->volume) + g_hash_table_remove (self->volumes, button->volume); + else + g_hash_table_remove (self->mounts, button->mount); + + if (GTK_CONTAINER_CLASS (drive_list_parent_class)->remove) + (* GTK_CONTAINER_CLASS (drive_list_parent_class)->remove) (container, child); +} + +static void +list_buttons (gpointer key, + gpointer value, + gpointer user_data) +{ + GtkWidget *button = value; + GList **sorted_buttons = user_data; + + *sorted_buttons = g_list_insert_sorted (*sorted_buttons, button, + (GCompareFunc)drive_button_compare); +} + +static gboolean +relayout_buttons (gpointer data) +{ + DriveList *self = DRIVE_LIST (data); + GList *sorted_buttons = NULL, *tmp; + int i = 0; + + self->layout_tag = 0; + if ( self->count > 0 ) { + g_hash_table_foreach (self->volumes, list_buttons, &sorted_buttons); + g_hash_table_foreach (self->mounts, list_buttons, &sorted_buttons); + + /* position buttons in the table according to their sorted order */ + for (tmp = sorted_buttons, i = 0; tmp != NULL; tmp = tmp->next, i++) { + GtkWidget *button = tmp->data; + + if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { + gtk_container_child_set (GTK_CONTAINER (self), button, + "left-attach", i + 1, "top-attach", 0, + "width", 1, "height", 1, + NULL); + } + else { + gtk_container_child_set (GTK_CONTAINER (self), button, + "left-attach", 0, "top-attach", i + 1, + "width", 1, "height", 1, + NULL); + } + } + } + else { + gtk_widget_show (self->dummy); + if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { + gtk_container_child_set (GTK_CONTAINER (self), self->dummy, + "left-attach", i + 1, "top-attach", 0, + "width", 1, "height", 1, + NULL); + } + else { + gtk_container_child_set (GTK_CONTAINER (self), self->dummy, + "left-attach", 0, "top-attach", i + 1, + "width", 1, "height", 1, + NULL); + } + } + return FALSE; +} + +static void +queue_relayout (DriveList *self) +{ + if (!self->layout_tag) { + self->layout_tag = g_idle_add (relayout_buttons, self); + } +} + +static void +mount_added (GVolumeMonitor *monitor, + GMount *mount, + DriveList *self) +{ + add_mount (self, mount); + self->count++; + if (self->count == 1) + gtk_container_remove (GTK_CONTAINER (self), g_object_ref (self->dummy)); + + mount_changed (monitor, mount, self); +} + +static void +mount_changed (GVolumeMonitor *monitor, + GMount *mount, + DriveList *self) +{ + GVolume *volume; + DriveButton *button = NULL;; + + volume = g_mount_get_volume (mount); + if (volume) { + button = g_hash_table_lookup (self->volumes, volume); + g_object_unref (volume); + } else { + button = g_hash_table_lookup (self->mounts, mount); + } + if (button) + drive_button_queue_update (button); +} + +static void +mount_removed (GVolumeMonitor *monitor, + GMount *mount, + DriveList *self) +{ + remove_mount (self, mount); + mount_changed (monitor, mount, self); + self->count--; + if (self->count == 0) { + gtk_container_add (GTK_CONTAINER (self), self->dummy); + queue_relayout (self); + } +} + +static void +volume_added (GVolumeMonitor *monitor, + GVolume *volume, + DriveList *self) +{ + add_volume (self, volume); + self->count++; + if (self->count == 1) + gtk_container_remove (GTK_CONTAINER (self), g_object_ref (self->dummy)); +} + +static void +volume_changed (GVolumeMonitor *monitor, + GVolume *volume, + DriveList *self) +{ + DriveButton *button = NULL;; + + button = g_hash_table_lookup (self->volumes, volume); + if (button) + drive_button_queue_update (button); +} + +static void +volume_removed (GVolumeMonitor *monitor, + GVolume *volume, + DriveList *self) +{ + remove_volume (self, volume); + self->count--; + if (self->count == 0) { + gtk_container_add (GTK_CONTAINER (self), self->dummy); + queue_relayout (self); + } +} + +static void +add_volume (DriveList *self, + GVolume *volume) +{ + GtkWidget *button; + + /* if the volume has already been added, return */ + if (g_hash_table_lookup (self->volumes, volume) != NULL) + return; + + button = drive_button_new (volume); + gtk_button_set_relief (GTK_BUTTON (button), self->relief); + drive_button_set_size (DRIVE_BUTTON (button), self->icon_size); + gtk_container_add (GTK_CONTAINER (self), button); + gtk_widget_show (button); + queue_relayout (self); +} + +static void +remove_volume (DriveList *self, + GVolume *volume) +{ + GtkWidget *button; + + /* if the volume has already been added, return */ + button = g_hash_table_lookup (self->volumes, volume); + if (button) { + gtk_container_remove (GTK_CONTAINER (self), button); + queue_relayout (self); + } +} + +static void +add_mount (DriveList *self, + GMount *mount) +{ + GtkWidget *button; + GVolume *volume; + + /* ignore mounts reported as shadowed */ + if (g_mount_is_shadowed (mount)) { + return; + } + + /* ignore mounts attached to a volume */ + volume = g_mount_get_volume (mount); + if (volume) { + g_object_unref (volume); + return; + } + + /* if the mount has already been added, return */ + if (g_hash_table_lookup (self->mounts, mount) != NULL) + return; + + button = drive_button_new_from_mount (mount); + gtk_button_set_relief (GTK_BUTTON (button), self->relief); + drive_button_set_size (DRIVE_BUTTON (button), self->icon_size); + gtk_container_add (GTK_CONTAINER (self), button); + gtk_widget_show (button); + queue_relayout (self); +} + +static void +remove_mount (DriveList *self, + GMount *mount) +{ + GtkWidget *button; + + /* if the mount has already been added, return */ + button = g_hash_table_lookup (self->mounts, mount); + if (button) { + gtk_container_remove (GTK_CONTAINER (self), button); + queue_relayout (self); + } +} + +void +drive_list_set_orientation (DriveList *self, + GtkOrientation orientation) +{ + g_return_if_fail (DRIVE_IS_LIST (self)); + + if (orientation != self->orientation) { + self->orientation = orientation; + queue_relayout (self); + } +} + +static void +set_icon_size (gpointer key, + gpointer value, + gpointer user_data) +{ + DriveButton *button = value; + DriveList *self = user_data; + + drive_button_set_size (button, self->icon_size); +} + + +void +drive_list_set_panel_size (DriveList *self, + int panel_size) +{ + g_return_if_fail (DRIVE_IS_LIST (self)); + + if (self->icon_size != panel_size) { + self->icon_size = panel_size; + g_hash_table_foreach (self->volumes, set_icon_size, self); + g_hash_table_foreach (self->mounts, set_icon_size, self); + } +} + +void +drive_list_redraw (DriveList *self) +{ + g_hash_table_foreach (self->volumes, drive_button_redraw, self); + g_hash_table_foreach (self->mounts, drive_button_redraw, self); +} + +void +settings_color_changed (GSettings *settings, + gchar *key, + DriveList *drive_list) +{ + g_return_if_fail (DRIVE_IS_LIST (drive_list)); + drive_list_redraw (drive_list); +} + +static void +set_button_relief (gpointer key, + gpointer value, + gpointer user_data) +{ + GtkButton *button = value; + DriveList *self = user_data; + + gtk_button_set_relief (button, self->relief); +} + +void +drive_list_set_transparent (DriveList *self, + gboolean transparent) +{ + GtkReliefStyle relief; + + relief = transparent ? GTK_RELIEF_NONE : GTK_RELIEF_NORMAL; + + if (relief == self->relief) + return; + + self->relief = relief; + g_hash_table_foreach (self->volumes, set_button_relief, self); + g_hash_table_foreach (self->mounts, set_button_relief, self); +} diff --git a/drivemount/src/drive-list.h b/drivemount/src/drive-list.h new file mode 100644 index 00000000..e2da7333 --- /dev/null +++ b/drivemount/src/drive-list.h @@ -0,0 +1,73 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * Drive Mount Applet + * Copyright (c) 2004 Canonical Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * James Henstridge + */ + +#ifndef DRIVE_LIST_H +#define DRIVE_LIST_H + +#include + +G_BEGIN_DECLS + +#define DRIVE_TYPE_LIST (drive_list_get_type ()) +#define DRIVE_LIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DRIVE_TYPE_LIST, DriveList)) +#define DRIVE_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DRIVE_TYPE_LIST, DriveListClass)) +#define DRIVE_IS_LIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DRIVE_TYPE_LIST)) +#define DRIVE_IS_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DRIVE_TYPE_LIST)) +#define DRIVE_LIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DRIVE_TYPE_LIST, DriveListClass)) + +typedef struct _DriveList DriveList; +typedef struct _DriveListClass DriveListClass; + +struct _DriveList +{ + GtkGrid parent; + + GHashTable *volumes; + GHashTable *mounts; + GtkOrientation orientation; + guint layout_tag; + GtkReliefStyle relief; + GtkWidget *dummy; + gint count; + + GSettings *settings; + + int icon_size; +}; + +struct _DriveListClass +{ + GtkGridClass parent_class; +}; + +GType drive_list_get_type (void); +GtkWidget *drive_list_new (void); +void drive_list_set_orientation (DriveList *list, + GtkOrientation orientation); +void drive_list_set_panel_size (DriveList *list, + int panel_size); +void drive_list_set_transparent (DriveList *self, + gboolean transparent); +void drive_list_redraw (DriveList *self); +void settings_color_changed (GSettings *settings, gchar *key, DriveList *drive_list); + +#endif /* DRIVE_LIST_H */ diff --git a/drivemount/src/drivemount.c b/drivemount/src/drivemount.c new file mode 100644 index 00000000..d6a77f20 --- /dev/null +++ b/drivemount/src/drivemount.c @@ -0,0 +1,230 @@ +/* -*- mode: C; c-basic-offset: 4 -*- + * Drive Mount Applet + * Copyright (c) 2004 Canonical Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * James Henstridge + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include + +#include "drive-list.h" + +static const char drivemount_iid[] = "DriveMountApplet"; +static const char factory_iid[] = "DriveMountAppletFactory"; + +static void +change_orient (MatePanelApplet *applet, + MatePanelAppletOrient o, + DriveList *drive_list) +{ + GtkOrientation orientation; + + switch (o) { + case MATE_PANEL_APPLET_ORIENT_LEFT: + case MATE_PANEL_APPLET_ORIENT_RIGHT: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + case MATE_PANEL_APPLET_ORIENT_DOWN: + default: + orientation = GTK_ORIENTATION_HORIZONTAL; + } + drive_list_set_orientation (drive_list, orientation); +} + +static void +size_allocate (MatePanelApplet *applet, + GdkRectangle *allocation, + DriveList *drive_list) +{ + int size; + + switch (mate_panel_applet_get_orient (applet)) { + case MATE_PANEL_APPLET_ORIENT_LEFT: + case MATE_PANEL_APPLET_ORIENT_RIGHT: + size = allocation->width; + break; + case MATE_PANEL_APPLET_ORIENT_UP: + case MATE_PANEL_APPLET_ORIENT_DOWN: + default: + size = allocation->height; + } + drive_list_set_panel_size (drive_list, size); +} + +static void +change_background (MatePanelApplet *applet, + MatePanelAppletBackgroundType type, + GdkColor *colour, + cairo_pattern_t *pattern, + DriveList *drivelist) +{ + switch (type) { + case PANEL_NO_BACKGROUND: + drive_list_set_transparent (drivelist, FALSE); + break; + case PANEL_COLOR_BACKGROUND: + case PANEL_PIXMAP_BACKGROUND: + drive_list_set_transparent (drivelist, TRUE); + } +} + +static void +display_about_dialog (GtkAction *action, + DriveList *drive_list) +{ + const gchar *authors[] = { + "James Henstridge ", + NULL + }; + + const gchar *documenters[] = { + "Dan Mueth ", + "John Fleck ", + N_("MATE Documentation Team"), + NULL + }; + +#ifdef ENABLE_NLS + const char **p; + for (p = documenters; *p; ++p) + *p = _(*p); +#endif + + gtk_show_about_dialog (NULL, + "title", _("About Disk Mounter"), + "version", VERSION, + "copyright", _("Copyright \xC2\xA9 2004 Canonical Ltd\n" + "Copyright \xc2\xa9 2012-2020 MATE developers"), + "comments", _("Applet for mounting and unmounting block volumes."), + "authors", authors, + "documenters", documenters, + "translator-credits", _("translator-credits"), + "logo_icon_name", "media-floppy", + NULL); +} + +static void +display_help (GtkAction *action, + DriveList *drive_list) +{ + GdkScreen *screen; + GError *error = NULL; + + screen = gtk_widget_get_screen (GTK_WIDGET (drive_list)); + + gtk_show_uri_on_window (NULL, + "help:mate-drivemount", + gtk_get_current_event_time (), + &error); + + if (error) { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("There was an error displaying help: %s"), + error->message); + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + gtk_window_set_screen (GTK_WINDOW (dialog), screen); + gtk_widget_show (dialog); + g_error_free (error); + } +} + +static const GtkActionEntry applet_menu_actions[] = { + { "Help", "help-browser", N_("_Help"), + NULL, NULL, + G_CALLBACK (display_help) }, + { "About", "help-about", N_("_About"), + NULL, NULL, + G_CALLBACK (display_about_dialog) } +}; + +static gboolean +applet_factory (MatePanelApplet *applet, + const char *iid, + gpointer user_data) +{ + gboolean ret = FALSE; + GtkWidget *drive_list; + AtkObject *ao; + GtkActionGroup *action_group; + + if (!strcmp (iid, drivemount_iid)) { + g_set_application_name (_("Disk Mounter")); + + gtk_window_set_default_icon_name ("media-floppy"); + + mate_panel_applet_set_flags (applet, MATE_PANEL_APPLET_EXPAND_MINOR); + + drive_list = drive_list_new (); + + gtk_container_add (GTK_CONTAINER (applet), drive_list); + + g_signal_connect_object (applet, "change_orient", + G_CALLBACK (change_orient), drive_list, 0); + g_signal_connect_object (applet, "size_allocate", + G_CALLBACK (size_allocate), drive_list, 0); + g_signal_connect (applet, "change_background", + G_CALLBACK (change_background), drive_list); + + /* set initial state */ + change_orient (applet, + mate_panel_applet_get_orient (applet), + DRIVE_LIST (drive_list)); + + action_group = gtk_action_group_new ("DriveMount Applet Actions"); + gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions (action_group, + applet_menu_actions, + G_N_ELEMENTS (applet_menu_actions), + drive_list); + mate_panel_applet_setup_menu_from_resource (applet, + DRIVEMOUNT_RESOURCE_PATH "drivemount-applet-menu.xml", + action_group); + g_object_unref (action_group); + + ao = gtk_widget_get_accessible (GTK_WIDGET (applet)); + atk_object_set_name (ao, _("Disk Mounter")); + + gtk_widget_show_all (GTK_WIDGET (applet)); + + ret = TRUE; + } + + return ret; +} + +MATE_PANEL_APPLET_OUT_PROCESS_FACTORY (factory_iid, + PANEL_TYPE_APPLET, + "Drive-Mount-Applet", + applet_factory, NULL) + -- cgit v1.2.1