1 /* Reload Image -- Allows to reload an image from disk
2  *
3  * Copyright (C) 2007-2012 The Free Software Foundation
4  *
5  * Author: Lucas Rocha <lucasr@gnome.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include "eog-reload-plugin.h"
27 
28 #include <gmodule.h>
29 #include <glib/gi18n-lib.h>
30 
31 #include <libpeas/peas.h>
32 
33 #include <eog-application.h>
34 #include <eog-debug.h>
35 #include <eog-thumb-view.h>
36 #include <eog-window.h>
37 #include <eog-window-activatable.h>
38 
39 enum {
40   PROP_0,
41   PROP_WINDOW
42 };
43 
44 #define EOG_RELOAD_PLUGIN_MENU_ID "EogPluginRunReload"
45 #define EOG_RELOAD_PLUGIN_ACTION "reload"
46 
47 static void eog_window_activatable_iface_init (EogWindowActivatableInterface *iface);
48 
49 G_DEFINE_DYNAMIC_TYPE_EXTENDED (EogReloadPlugin,
50                                 eog_reload_plugin,
51                                 PEAS_TYPE_EXTENSION_BASE,
52                                 0,
53                                 G_IMPLEMENT_INTERFACE_DYNAMIC (EOG_TYPE_WINDOW_ACTIVATABLE,
54                                                                eog_window_activatable_iface_init))
55 
56 static void
reload_cb(GSimpleAction * simple,GVariant * parameter,gpointer user_data)57 reload_cb (GSimpleAction *simple,
58 	   GVariant      *parameter,
59 	   gpointer       user_data)
60 {
61 	eog_window_reload_image (EOG_WINDOW (user_data));
62 }
63 
64 static void
eog_reload_plugin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)65 eog_reload_plugin_set_property (GObject      *object,
66 				guint         prop_id,
67 				const GValue *value,
68 				GParamSpec   *pspec)
69 {
70 	EogReloadPlugin *plugin = EOG_RELOAD_PLUGIN (object);
71 
72 	switch (prop_id)
73 	{
74 	case PROP_WINDOW:
75 		plugin->window = EOG_WINDOW (g_value_dup_object (value));
76 		break;
77 
78 	default:
79 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
80 		break;
81 	}
82 }
83 
84 static void
eog_reload_plugin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)85 eog_reload_plugin_get_property (GObject    *object,
86 				guint       prop_id,
87 				GValue     *value,
88 				GParamSpec *pspec)
89 {
90 	EogReloadPlugin *plugin = EOG_RELOAD_PLUGIN (object);
91 
92 	switch (prop_id)
93 	{
94 	case PROP_WINDOW:
95 		g_value_set_object (value, plugin->window);
96 		break;
97 
98 	default:
99 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100 		break;
101 	}
102 }
103 
104 static void
eog_reload_plugin_init(EogReloadPlugin * plugin)105 eog_reload_plugin_init (EogReloadPlugin *plugin)
106 {
107 	eog_debug_message (DEBUG_PLUGINS, "EogReloadPlugin initializing");
108 }
109 
110 static void
eog_reload_plugin_dispose(GObject * object)111 eog_reload_plugin_dispose (GObject *object)
112 {
113 	EogReloadPlugin *plugin = EOG_RELOAD_PLUGIN (object);
114 
115 	eog_debug_message (DEBUG_PLUGINS, "EogReloadPlugin disposing");
116 
117 	if (plugin->window != NULL) {
118 		g_object_unref (plugin->window);
119 		plugin->window = NULL;
120 	}
121 
122 	G_OBJECT_CLASS (eog_reload_plugin_parent_class)->dispose (object);
123 }
124 
125 static void
eog_reload_plugin_update_action_state(EogReloadPlugin * plugin)126 eog_reload_plugin_update_action_state (EogReloadPlugin *plugin)
127 {
128 	GAction *action;
129 	EogThumbView *thumbview;
130 	gboolean enable = FALSE;
131 
132 	thumbview = EOG_THUMB_VIEW (eog_window_get_thumb_view (plugin->window));
133 
134 	if (G_LIKELY (thumbview))
135 	{
136 		enable = (eog_thumb_view_get_n_selected (thumbview) != 0);
137 	}
138 
139 	action = g_action_map_lookup_action (G_ACTION_MAP (plugin->window),
140 					     EOG_RELOAD_PLUGIN_ACTION);
141 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enable);
142 }
143 
144 static void
_selection_changed_cb(EogThumbView * thumbview,gpointer user_data)145 _selection_changed_cb (EogThumbView *thumbview, gpointer user_data)
146 {
147 	EogReloadPlugin *plugin = EOG_RELOAD_PLUGIN (user_data);
148 
149 	if (G_LIKELY (plugin))
150 		eog_reload_plugin_update_action_state (plugin);
151 }
152 
153 static void
eog_reload_plugin_activate(EogWindowActivatable * activatable)154 eog_reload_plugin_activate (EogWindowActivatable *activatable)
155 {
156 	const gchar * const accel_keys[] = { "R", NULL };
157 	EogReloadPlugin *plugin = EOG_RELOAD_PLUGIN (activatable);
158 	GMenu *model, *menu;
159 	GMenuItem *item;
160 	GSimpleAction *action;
161 
162 	eog_debug (DEBUG_PLUGINS);
163 
164 	model= eog_window_get_gear_menu_section (plugin->window,
165 						 "plugins-section");
166 
167 	g_return_if_fail (G_IS_MENU (model));
168 
169 	/* Setup and inject action */
170 	action = g_simple_action_new (EOG_RELOAD_PLUGIN_ACTION, NULL);
171 	g_signal_connect(action, "activate",
172 			 G_CALLBACK (reload_cb), plugin->window);
173 	g_action_map_add_action (G_ACTION_MAP (plugin->window),
174 				 G_ACTION (action));
175 	g_object_unref (action);
176 
177 	g_signal_connect (G_OBJECT (eog_window_get_thumb_view (plugin->window)),
178 			  "selection-changed",
179 			  G_CALLBACK (_selection_changed_cb),
180 			  plugin);
181 	eog_reload_plugin_update_action_state (plugin);
182 
183 	/* Append entry to the window's gear menu */
184 	menu = g_menu_new ();
185 	g_menu_append (menu, _("Reload Image"),
186 		       "win." EOG_RELOAD_PLUGIN_ACTION);
187 
188 	item = g_menu_item_new_section (NULL, G_MENU_MODEL (menu));
189 	g_menu_item_set_attribute (item, "id",
190 				   "s", EOG_RELOAD_PLUGIN_MENU_ID);
191 	g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_ICON,
192 				   "s", "view-refresh-symbolic");
193 	g_menu_append_item (model, item);
194 	g_object_unref (item);
195 
196 	g_object_unref (menu);
197 
198 	/* Define accelerator keys */
199 	gtk_application_set_accels_for_action (GTK_APPLICATION (EOG_APP),
200 					       "win." EOG_RELOAD_PLUGIN_ACTION,
201 					       accel_keys);
202 }
203 
204 static void
eog_reload_plugin_deactivate(EogWindowActivatable * activatable)205 eog_reload_plugin_deactivate (EogWindowActivatable *activatable)
206 {
207 	const gchar * const empty_accels[1] = { NULL };
208 	EogReloadPlugin *plugin = EOG_RELOAD_PLUGIN (activatable);
209 	GMenu *menu;
210 	GMenuModel *model;
211 	gint i;
212 
213 	eog_debug (DEBUG_PLUGINS);
214 
215 	menu = eog_window_get_gear_menu_section (plugin->window,
216 						 "plugins-section");
217 
218 	g_return_if_fail (G_IS_MENU (menu));
219 
220 	/* Remove menu entry */
221 	model = G_MENU_MODEL (menu);
222 	for (i = 0; i < g_menu_model_get_n_items (model); i++) {
223 		gchar *id;
224 		if (g_menu_model_get_item_attribute (model, i, "id", "s", &id)) {
225 			const gboolean found =
226 				(g_strcmp0 (id, EOG_RELOAD_PLUGIN_MENU_ID) == 0);
227 			g_free (id);
228 
229 			if (found) {
230 				g_menu_remove (menu, i);
231 				break;
232 			}
233 		}
234 	}
235 
236 	/* Unset accelerator */
237 	gtk_application_set_accels_for_action(GTK_APPLICATION (EOG_APP),
238 					      "win." EOG_RELOAD_PLUGIN_ACTION,
239 					      empty_accels);
240 
241 	/* Disconnect selection-changed handler as the thumbview would
242 	 * otherwise still cause callbacks during its own disposal */
243 	g_signal_handlers_disconnect_by_func (eog_window_get_thumb_view (plugin->window),
244 					      _selection_changed_cb, plugin);
245 
246 	/* Finally remove action */
247 	g_action_map_remove_action (G_ACTION_MAP (plugin->window),
248 				    EOG_RELOAD_PLUGIN_ACTION);
249 }
250 
251 static void
eog_reload_plugin_class_init(EogReloadPluginClass * klass)252 eog_reload_plugin_class_init (EogReloadPluginClass *klass)
253 {
254 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
255 
256 	object_class->dispose= eog_reload_plugin_dispose;
257 	object_class->set_property = eog_reload_plugin_set_property;
258 	object_class->get_property = eog_reload_plugin_get_property;
259 
260 	g_object_class_override_property (object_class, PROP_WINDOW, "window");
261 }
262 
263 static void
eog_reload_plugin_class_finalize(EogReloadPluginClass * klass)264 eog_reload_plugin_class_finalize (EogReloadPluginClass *klass)
265 {
266 }
267 
268 static void
eog_window_activatable_iface_init(EogWindowActivatableInterface * iface)269 eog_window_activatable_iface_init (EogWindowActivatableInterface *iface)
270 {
271 	iface->activate = eog_reload_plugin_activate;
272 	iface->deactivate = eog_reload_plugin_deactivate;
273 }
274 
275 G_MODULE_EXPORT void
peas_register_types(PeasObjectModule * module)276 peas_register_types (PeasObjectModule *module)
277 {
278 	eog_reload_plugin_register_type (G_TYPE_MODULE (module));
279 	peas_object_module_register_extension_type (module,
280 						    EOG_TYPE_WINDOW_ACTIVATABLE,
281 						    EOG_TYPE_RELOAD_PLUGIN);
282 }
283