1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #include "eog-postr-plugin.h"
6 
7 #include <gmodule.h>
8 #include <glib/gi18n-lib.h>
9 
10 #include <eog/eog-debug.h>
11 #include <eog/eog-thumb-view.h>
12 #include <eog/eog-image.h>
13 #include <eog/eog-window-activatable.h>
14 
15 #define EOG_POSTR_PLUGIN_MENU_ID "EogPluginPostr"
16 #define EOG_POSTR_PLUGIN_ACTION "upload-with-postr"
17 
18 enum {
19 	PROP_O,
20 	PROP_WINDOW
21 };
22 
23 static void
24 eog_window_activatable_iface_init (EogWindowActivatableInterface *iface);
25 
26 G_DEFINE_DYNAMIC_TYPE_EXTENDED (EogPostrPlugin, eog_postr_plugin,
27 		PEAS_TYPE_EXTENSION_BASE, 0,
28 		G_IMPLEMENT_INTERFACE_DYNAMIC(EOG_TYPE_WINDOW_ACTIVATABLE,
29 					eog_window_activatable_iface_init))
30 
31 static void
postr_cb(GSimpleAction * simple,GVariant * parameter,gpointer user_data)32 postr_cb (GSimpleAction *simple,
33 	  GVariant      *parameter,
34 	  gpointer       user_data)
35 {
36 	EogWindow *window;
37 	GtkWidget *thumbview;
38 	GList *images, *i;
39 	gchar *cmd = g_strdup ("postr ");
40 
41 	eog_debug(DEBUG_PLUGINS);
42 
43 	g_return_if_fail (EOG_IS_WINDOW (user_data));
44 
45 	window = EOG_WINDOW (user_data);
46 	thumbview = eog_window_get_thumb_view (window);
47 	images = eog_thumb_view_get_selected_images (EOG_THUMB_VIEW (thumbview));
48 
49 	for (i = g_list_first (images); i; i = i->next) {
50 		EogImage *image = (EogImage *) i->data;
51 		GFile *imgfile;
52 		gchar *imgpath;
53 		gchar *oldcmd = cmd;
54 
55 		imgfile = eog_image_get_file (image);
56 		imgpath = g_file_get_path (imgfile);
57 
58 		if (G_LIKELY (imgpath != NULL)) {
59 			cmd = g_strconcat (oldcmd, "\"", imgpath, "\"", " ", NULL);
60 			g_free (oldcmd);
61 		}
62 
63 		g_free (imgpath);
64 		g_object_unref (imgfile);
65 	}
66 
67 	g_spawn_command_line_async (cmd, NULL);
68 
69 	g_list_free_full (images, g_object_unref);
70 	g_free (cmd);
71 }
72 
73 static void
eog_postr_plugin_update_action_state(EogPostrPlugin * plugin)74 eog_postr_plugin_update_action_state (EogPostrPlugin *plugin)
75 {
76 	GAction *action;
77 	EogThumbView *thumbview;
78 	gboolean enable = FALSE;
79 
80 	thumbview = EOG_THUMB_VIEW (eog_window_get_thumb_view (plugin->window));
81 
82 	if (G_LIKELY (thumbview))
83 	{
84 		enable = (eog_thumb_view_get_n_selected (thumbview) != 0);
85 	}
86 
87 	action = g_action_map_lookup_action (G_ACTION_MAP (plugin->window),
88 					     EOG_POSTR_PLUGIN_ACTION);
89 	g_simple_action_set_enabled (G_SIMPLE_ACTION (action), enable);
90 }
91 
92 static void
_selection_changed_cb(EogThumbView * thumbview,gpointer user_data)93 _selection_changed_cb (EogThumbView *thumbview, gpointer user_data)
94 {
95 	EogPostrPlugin *plugin = EOG_POSTR_PLUGIN (user_data);
96 
97 	if (G_LIKELY (plugin))
98 		eog_postr_plugin_update_action_state (plugin);
99 }
100 
101 static void
eog_postr_plugin_init(EogPostrPlugin * plugin)102 eog_postr_plugin_init (EogPostrPlugin *plugin)
103 {
104 	eog_debug_message (DEBUG_PLUGINS, "EogPostrPlugin initializing");
105 }
106 
107 
108 static void
eog_postr_plugin_dispose(GObject * object)109 eog_postr_plugin_dispose (GObject *object)
110 {
111 	EogPostrPlugin *plugin = EOG_POSTR_PLUGIN (object);
112 
113 	eog_debug_message (DEBUG_PLUGINS, "EogPostrPlugin disposing");
114 
115 	if (plugin->window != NULL) {
116 		g_object_unref (plugin->window);
117 		plugin->window = NULL;
118 	}
119 
120 	G_OBJECT_CLASS (eog_postr_plugin_parent_class)->dispose (object);
121 }
122 
123 static void
impl_activate(EogWindowActivatable * activatable)124 impl_activate (EogWindowActivatable *activatable)
125 {
126 	EogPostrPlugin *plugin = EOG_POSTR_PLUGIN (activatable);
127 	GMenu *model, *menu;
128 	GMenuItem *item;
129 	GSimpleAction *action;
130 
131 	eog_debug (DEBUG_PLUGINS);
132 
133 	g_return_if_fail (plugin->window != NULL);
134 
135 	model= eog_window_get_gear_menu_section (plugin->window,
136 						 "plugins-section");
137 
138 	g_return_if_fail (G_IS_MENU (model));
139 
140 	/* Setup and inject action */
141 	action = g_simple_action_new (EOG_POSTR_PLUGIN_ACTION, NULL);
142 	g_signal_connect(action, "activate",
143 			 G_CALLBACK (postr_cb), plugin->window);
144 	g_action_map_add_action (G_ACTION_MAP (plugin->window),
145 				 G_ACTION (action));
146 	g_object_unref (action);
147 
148 	g_signal_connect (G_OBJECT (eog_window_get_thumb_view (plugin->window)),
149 			  "selection-changed",
150 			  G_CALLBACK (_selection_changed_cb),
151 			  plugin);
152 	eog_postr_plugin_update_action_state (plugin);
153 
154 	/* Append entry to the window's gear menu */
155 	menu = g_menu_new ();
156 	g_menu_append (menu, _("Upload to Flickr"),
157 		       "win." EOG_POSTR_PLUGIN_ACTION);
158 
159 	item = g_menu_item_new_section (NULL, G_MENU_MODEL (menu));
160 	g_menu_item_set_attribute (item, "id",
161 				   "s", EOG_POSTR_PLUGIN_MENU_ID);
162 	g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_ICON,
163 				   "s", "postr");
164 	g_menu_append_item (model, item);
165 	g_object_unref (item);
166 
167 	g_object_unref (menu);
168 
169 }
170 
171 static void
impl_deactivate(EogWindowActivatable * activatable)172 impl_deactivate	(EogWindowActivatable *activatable)
173 {
174 	EogPostrPlugin *plugin = EOG_POSTR_PLUGIN (activatable);
175 	GMenu *menu;
176 	GMenuModel *model;
177 	gint i;
178 
179 	eog_debug (DEBUG_PLUGINS);
180 
181 	menu = eog_window_get_gear_menu_section (plugin->window,
182 						 "plugins-section");
183 
184 	g_return_if_fail (G_IS_MENU (menu));
185 
186 	/* Remove menu entry */
187 	model = G_MENU_MODEL (menu);
188 	for (i = 0; i < g_menu_model_get_n_items (model); i++) {
189 		gchar *id;
190 		if (g_menu_model_get_item_attribute (model, i, "id", "s", &id)) {
191 			const gboolean found =
192 				(g_strcmp0 (id, EOG_POSTR_PLUGIN_MENU_ID) == 0);
193 			g_free (id);
194 
195 			if (found) {
196 				g_menu_remove (menu, i);
197 				break;
198 			}
199 		}
200 	}
201 
202 	g_signal_handlers_disconnect_by_func (eog_window_get_thumb_view (plugin->window),
203 					      _selection_changed_cb, plugin);
204 
205 
206 	/* Finally remove action */
207 	g_action_map_remove_action (G_ACTION_MAP (plugin->window),
208 				    EOG_POSTR_PLUGIN_ACTION);
209 }
210 
211 static void
eog_postr_plugin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)212 eog_postr_plugin_get_property (GObject    *object,
213 			       guint       prop_id,
214 			       GValue     *value,
215 			       GParamSpec *pspec)
216 {
217 	EogPostrPlugin *plugin = EOG_POSTR_PLUGIN (object);
218 
219 	switch (prop_id)
220 	{
221 	case PROP_WINDOW:
222 		g_value_set_object (value, plugin->window);
223 		break;
224 
225 	default:
226 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
227 		break;
228 	}
229 }
230 
231 static void
eog_postr_plugin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)232 eog_postr_plugin_set_property (GObject      *object,
233 			       guint         prop_id,
234 			       const GValue *value,
235 			       GParamSpec   *pspec)
236 {
237 	EogPostrPlugin *plugin = EOG_POSTR_PLUGIN (object);
238 
239 	switch (prop_id)
240 	{
241 	case PROP_WINDOW:
242 		plugin->window = EOG_WINDOW (g_value_dup_object (value));
243 		break;
244 
245 	default:
246 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
247 		break;
248 	}
249 }
250 
251 static void
eog_postr_plugin_class_init(EogPostrPluginClass * klass)252 eog_postr_plugin_class_init (EogPostrPluginClass *klass)
253 {
254 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
255 
256 	object_class->finalize = eog_postr_plugin_dispose;
257 	object_class->set_property = eog_postr_plugin_set_property;
258 	object_class->get_property = eog_postr_plugin_get_property;
259 
260 	g_object_class_override_property (object_class, PROP_WINDOW, "window");
261 }
262 
263 static void
eog_postr_plugin_class_finalize(EogPostrPluginClass * klass)264 eog_postr_plugin_class_finalize (EogPostrPluginClass *klass)
265 {
266 	/* Dummy needed for G_DEFINE_DYNAMIC_TYPE_EXTENDED */
267 }
268 
269 static void
eog_window_activatable_iface_init(EogWindowActivatableInterface * iface)270 eog_window_activatable_iface_init (EogWindowActivatableInterface *iface)
271 {
272 	iface->activate = impl_activate;
273 	iface->deactivate = impl_deactivate;
274 }
275 
276 G_MODULE_EXPORT void
peas_register_types(PeasObjectModule * module)277 peas_register_types (PeasObjectModule *module)
278 {
279 	eog_postr_plugin_register_type (G_TYPE_MODULE (module));
280 	peas_object_module_register_extension_type (module,
281 						    EOG_TYPE_WINDOW_ACTIVATABLE,
282 						    EOG_TYPE_POSTR_PLUGIN);
283 }
284