1 #include "pluma-file-browser-messages.h"
2 #include "pluma-file-browser-store.h"
3 #include <pluma/pluma-message.h>
4 
5 #define MESSAGE_OBJECT_PATH 	"/plugins/filebrowser"
6 #define WINDOW_DATA_KEY	       	"PlumaFileBrowserMessagesWindowData"
7 
8 #define BUS_CONNECT(bus, name, data) pluma_message_bus_connect(bus, MESSAGE_OBJECT_PATH, #name, (PlumaMessageCallback)  message_##name##_cb, data, NULL)
9 
10 typedef struct
11 {
12 	PlumaWindow *window;
13 	PlumaMessage *message;
14 } MessageCacheData;
15 
16 typedef struct
17 {
18 	guint row_inserted_id;
19 	guint row_deleted_id;
20 	guint root_changed_id;
21 	guint begin_loading_id;
22 	guint end_loading_id;
23 
24 	GList *merge_ids;
25 	GtkActionGroup *merged_actions;
26 
27 	PlumaMessageBus *bus;
28 	PlumaFileBrowserWidget *widget;
29 	GHashTable *row_tracking;
30 
31 	GHashTable *filters;
32 } WindowData;
33 
34 typedef struct
35 {
36 	gulong id;
37 
38 	PlumaWindow *window;
39 	PlumaMessage *message;
40 } FilterData;
41 
42 static WindowData *
window_data_new(PlumaWindow * window,PlumaFileBrowserWidget * widget)43 window_data_new (PlumaWindow            *window,
44 		 PlumaFileBrowserWidget *widget)
45 {
46 	WindowData *data = g_slice_new (WindowData);
47 	GtkUIManager *manager;
48 	GList *groups;
49 
50 	data->bus = pluma_window_get_message_bus (window);
51 	data->widget = widget;
52 	data->row_tracking = g_hash_table_new_full (g_str_hash,
53 						    g_str_equal,
54 						    (GDestroyNotify)g_free,
55 						    (GDestroyNotify)gtk_tree_row_reference_free);
56 
57 	data->filters = g_hash_table_new_full (g_str_hash,
58 					       g_str_equal,
59 					       (GDestroyNotify)g_free,
60 					       NULL);
61 
62 	manager = pluma_file_browser_widget_get_ui_manager (widget);
63 
64 	data->merge_ids = NULL;
65 	data->merged_actions = gtk_action_group_new ("MessageMergedActions");
66 
67 	groups = gtk_ui_manager_get_action_groups (manager);
68 	gtk_ui_manager_insert_action_group (manager, data->merged_actions, g_list_length (groups));
69 
70 	g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, data);
71 
72 	return data;
73 }
74 
75 static WindowData *
get_window_data(PlumaWindow * window)76 get_window_data (PlumaWindow * window)
77 {
78 	return (WindowData *) (g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY));
79 }
80 
81 static void
window_data_free(PlumaWindow * window)82 window_data_free (PlumaWindow *window)
83 {
84 	WindowData *data = get_window_data (window);
85 	GtkUIManager *manager;
86 	GList *item;
87 
88 	g_hash_table_destroy (data->row_tracking);
89 	g_hash_table_destroy (data->filters);
90 
91 	manager = pluma_file_browser_widget_get_ui_manager (data->widget);
92 	gtk_ui_manager_remove_action_group (manager, data->merged_actions);
93 
94 	for (item = data->merge_ids; item; item = item->next)
95 		gtk_ui_manager_remove_ui (manager, GPOINTER_TO_INT (item->data));
96 
97 	g_list_free (data->merge_ids);
98 	g_object_unref (data->merged_actions);
99 
100 	g_slice_free (WindowData, data);
101 
102 	g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL);
103 }
104 
105 static FilterData *
filter_data_new(PlumaWindow * window,PlumaMessage * message)106 filter_data_new (PlumaWindow  *window,
107 		 PlumaMessage *message)
108 {
109 	FilterData *data = g_slice_new (FilterData);
110 	WindowData *wdata;
111 
112 	data->window = window;
113 	data->id = 0;
114 	data->message = message;
115 
116 	wdata = get_window_data (window);
117 
118 	g_hash_table_insert (wdata->filters,
119 			     pluma_message_type_identifier (pluma_message_get_object_path (message),
120 			                                    pluma_message_get_method (message)),
121 			     data);
122 
123 	return data;
124 }
125 
126 static void
filter_data_free(FilterData * data)127 filter_data_free (FilterData *data)
128 {
129 	WindowData *wdata = get_window_data (data->window);
130 	gchar *identifier;
131 
132 	identifier = pluma_message_type_identifier (pluma_message_get_object_path (data->message),
133 			                            pluma_message_get_method (data->message));
134 
135 	g_hash_table_remove (wdata->filters, identifier);
136 	g_free (identifier);
137 
138 	g_object_unref (data->message);
139 	g_slice_free (FilterData, data);
140 }
141 
142 static GtkTreePath *
track_row_lookup(WindowData * data,const gchar * id)143 track_row_lookup (WindowData  *data,
144 		  const gchar *id)
145 {
146 	GtkTreeRowReference *ref;
147 
148 	ref = (GtkTreeRowReference *)g_hash_table_lookup (data->row_tracking, id);
149 
150 	if (!ref)
151 		return NULL;
152 
153 	return gtk_tree_row_reference_get_path (ref);
154 }
155 
156 static void
message_cache_data_free(MessageCacheData * data,GClosure * closure)157 message_cache_data_free (MessageCacheData *data,
158                          GClosure         *closure)
159 {
160 	g_object_unref (data->message);
161 	g_slice_free (MessageCacheData, data);
162 }
163 
164 static MessageCacheData *
message_cache_data_new(PlumaWindow * window,PlumaMessage * message)165 message_cache_data_new (PlumaWindow            *window,
166 			PlumaMessage           *message)
167 {
168 	MessageCacheData *data = g_slice_new (MessageCacheData);
169 
170 	data->window = window;
171 	data->message = message;
172 
173 	return data;
174 }
175 
176 static void
message_get_root_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)177 message_get_root_cb (PlumaMessageBus *bus,
178 		     PlumaMessage    *message,
179 		     WindowData      *data)
180 {
181 	PlumaFileBrowserStore *store;
182 	gchar *uri;
183 
184 	store = pluma_file_browser_widget_get_browser_store (data->widget);
185 	uri = pluma_file_browser_store_get_virtual_root (store);
186 
187 	pluma_message_set (message, "uri", uri, NULL);
188 	g_free (uri);
189 }
190 
191 static void
message_set_root_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)192 message_set_root_cb (PlumaMessageBus *bus,
193 		     PlumaMessage    *message,
194 		     WindowData      *data)
195 {
196 	gchar *root = NULL;
197 	gchar *virtual = NULL;
198 
199 	pluma_message_get (message, "uri", &root, NULL);
200 
201 	if (!root)
202 		return;
203 
204 	if (pluma_message_has_key (message, "virtual"))
205 		pluma_message_get (message, "virtual", &virtual, NULL);
206 
207 	if (virtual)
208 		pluma_file_browser_widget_set_root_and_virtual_root (data->widget, root, virtual);
209 	else
210 		pluma_file_browser_widget_set_root (data->widget, root, TRUE);
211 
212 	g_free (root);
213 	g_free (virtual);
214 }
215 
216 static void
message_set_emblem_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)217 message_set_emblem_cb (PlumaMessageBus *bus,
218 		       PlumaMessage    *message,
219 		       WindowData      *data)
220 {
221 	gchar *id = NULL;
222 	gchar *emblem = NULL;
223 	GtkTreePath *path;
224 	PlumaFileBrowserStore *store;
225 
226 	pluma_message_get (message, "id", &id, "emblem", &emblem, NULL);
227 
228 	if (!id || !emblem)
229 	{
230 		g_free (id);
231 		g_free (emblem);
232 
233 		return;
234 	}
235 
236 	path = track_row_lookup (data, id);
237 
238 	if (path != NULL)
239 	{
240 		GError *error = NULL;
241 		GdkPixbuf *pixbuf;
242 
243 		pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
244 						   emblem,
245 						   10,
246 						   0,
247 						   &error);
248 
249 		if (pixbuf)
250 		{
251 			GValue value = { 0, };
252 			GtkTreeIter iter;
253 
254 			store = pluma_file_browser_widget_get_browser_store (data->widget);
255 
256 			if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
257 			{
258 				g_value_init (&value, GDK_TYPE_PIXBUF);
259 				g_value_set_object (&value, pixbuf);
260 
261 				pluma_file_browser_store_set_value (store,
262 								    &iter,
263 								    PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM,
264 								    &value);
265 
266 				g_value_unset (&value);
267 			}
268 
269 			g_object_unref (pixbuf);
270 		}
271 
272 		if (error)
273 			g_error_free (error);
274 	}
275 
276 	g_free (id);
277 	g_free (emblem);
278 }
279 
280 static gchar *
item_id(const gchar * path,const gchar * uri)281 item_id (const gchar *path,
282 	 const gchar *uri)
283 {
284 	return g_strconcat (path, "::", uri, NULL);
285 }
286 
287 static gchar *
track_row(WindowData * data,PlumaFileBrowserStore * store,GtkTreePath * path,const gchar * uri)288 track_row (WindowData            *data,
289 	   PlumaFileBrowserStore *store,
290 	   GtkTreePath           *path,
291 	   const gchar		 *uri)
292 {
293 	GtkTreeRowReference *ref;
294 	gchar *id;
295 	gchar *pathstr;
296 
297 	pathstr = gtk_tree_path_to_string (path);
298 	id = item_id (pathstr, uri);
299 
300 	ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
301 	g_hash_table_insert (data->row_tracking, g_strdup (id), ref);
302 
303 	g_free (pathstr);
304 
305 	return id;
306 }
307 
308 static void
set_item_message(WindowData * data,GtkTreeIter * iter,GtkTreePath * path,PlumaMessage * message)309 set_item_message (WindowData   *data,
310 		  GtkTreeIter  *iter,
311 		  GtkTreePath  *path,
312 		  PlumaMessage *message)
313 {
314 	PlumaFileBrowserStore *store;
315 	gchar *uri = NULL;
316 	guint flags = 0;
317 	gchar *track_id;
318 
319 	store = pluma_file_browser_widget_get_browser_store (data->widget);
320 
321 	gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
322 			    PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
323 			    PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
324 			    -1);
325 
326 	if (!uri)
327 		return;
328 
329 	if (path && gtk_tree_path_get_depth (path) != 0)
330 		track_id = track_row (data, store, path, uri);
331 	else
332 		track_id = NULL;
333 
334 	pluma_message_set (message,
335 			   "id", track_id,
336 			   "uri", uri,
337 			   NULL);
338 
339 	if (pluma_message_has_key (message, "is_directory"))
340 	{
341 		pluma_message_set (message,
342 				   "is_directory", FILE_IS_DIR (flags),
343 				   NULL);
344 	}
345 
346 	g_free (uri);
347 	g_free (track_id);
348 }
349 
350 static gboolean
custom_message_filter_func(PlumaFileBrowserWidget * widget,PlumaFileBrowserStore * store,GtkTreeIter * iter,FilterData * data)351 custom_message_filter_func (PlumaFileBrowserWidget *widget,
352 			    PlumaFileBrowserStore  *store,
353 			    GtkTreeIter            *iter,
354 			    FilterData             *data)
355 {
356 	WindowData *wdata = get_window_data (data->window);
357 	gchar *uri = NULL;
358 	guint flags = 0;
359 	gboolean filter = FALSE;
360 	GtkTreePath *path;
361 
362 	gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
363 			    PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
364 			    PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
365 			    -1);
366 
367 	if (!uri || FILE_IS_DUMMY (flags))
368 	{
369 		g_free (uri);
370 		return FALSE;
371 	}
372 
373 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
374 	set_item_message (wdata, iter, path, data->message);
375 	gtk_tree_path_free (path);
376 
377 	pluma_message_set (data->message, "filter", filter, NULL);
378 
379 	pluma_message_bus_send_message_sync (wdata->bus, data->message);
380 	pluma_message_get (data->message, "filter", &filter, NULL);
381 
382 	return !filter;
383 }
384 
385 static void
message_add_filter_cb(PlumaMessageBus * bus,PlumaMessage * message,PlumaWindow * window)386 message_add_filter_cb (PlumaMessageBus *bus,
387 		       PlumaMessage    *message,
388 		       PlumaWindow     *window)
389 {
390 	gchar *object_path = NULL;
391 	gchar *method = NULL;
392 	gulong id;
393 	PlumaMessageType *message_type;
394 	PlumaMessage *cbmessage;
395 	FilterData *filter_data;
396 	WindowData *data = get_window_data (window);
397 
398 	pluma_message_get (message,
399 			   "object_path", &object_path,
400 			   "method", &method,
401 			   NULL);
402 
403 	// Check if there exists such a 'callback' message
404 	if (!object_path || !method)
405 	{
406 		g_free (object_path);
407 		g_free (method);
408 
409 		return;
410 	}
411 
412 	message_type = pluma_message_bus_lookup (bus, object_path, method);
413 
414 	if (!message_type)
415 	{
416 		g_free (object_path);
417 		g_free (method);
418 
419 		return;
420 	}
421 
422 	// Check if the message type has the correct arguments
423 	if (pluma_message_type_lookup (message_type, "id") != G_TYPE_STRING ||
424 	    pluma_message_type_lookup (message_type, "uri") != G_TYPE_STRING ||
425 	    pluma_message_type_lookup (message_type, "is_directory") != G_TYPE_BOOLEAN ||
426 	    pluma_message_type_lookup (message_type, "filter") != G_TYPE_BOOLEAN)
427 	{
428 		return;
429 	}
430 
431 	cbmessage = pluma_message_type_instantiate (message_type,
432 						    "id", NULL,
433 						    "uri", NULL,
434 						    "is_directory", FALSE,
435 						    "filter", FALSE,
436 						    NULL);
437 
438 	// Register the custom filter on the widget
439 	filter_data = filter_data_new (window, cbmessage);
440 	id = pluma_file_browser_widget_add_filter (data->widget,
441 						   (PlumaFileBrowserWidgetFilterFunc)custom_message_filter_func,
442 						   filter_data,
443 						   (GDestroyNotify)filter_data_free);
444 
445 	filter_data->id = id;
446 }
447 
448 static void
message_remove_filter_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)449 message_remove_filter_cb (PlumaMessageBus *bus,
450 		          PlumaMessage    *message,
451 		          WindowData      *data)
452 {
453 	gulong id = 0;
454 
455 	pluma_message_get (message, "id", &id, NULL);
456 
457 	if (!id)
458 		return;
459 
460 	pluma_file_browser_widget_remove_filter (data->widget, id);
461 }
462 
463 static void
message_up_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)464 message_up_cb (PlumaMessageBus *bus,
465 	       PlumaMessage    *message,
466 	       WindowData      *data)
467 {
468 	PlumaFileBrowserStore *store = pluma_file_browser_widget_get_browser_store (data->widget);
469 
470 	pluma_file_browser_store_set_virtual_root_up (store);
471 }
472 
473 static void
message_history_back_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)474 message_history_back_cb (PlumaMessageBus *bus,
475 		         PlumaMessage    *message,
476 		         WindowData      *data)
477 {
478 	pluma_file_browser_widget_history_back (data->widget);
479 }
480 
481 static void
message_history_forward_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)482 message_history_forward_cb (PlumaMessageBus *bus,
483 		            PlumaMessage    *message,
484 		            WindowData      *data)
485 {
486 	pluma_file_browser_widget_history_forward (data->widget);
487 }
488 
489 static void
message_refresh_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)490 message_refresh_cb (PlumaMessageBus *bus,
491 		    PlumaMessage    *message,
492 		    WindowData      *data)
493 {
494 	pluma_file_browser_widget_refresh (data->widget);
495 }
496 
497 static void
message_set_show_hidden_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)498 message_set_show_hidden_cb (PlumaMessageBus *bus,
499 		            PlumaMessage    *message,
500 		            WindowData      *data)
501 {
502 	gboolean active = FALSE;
503 	PlumaFileBrowserStore *store;
504 	PlumaFileBrowserStoreFilterMode mode;
505 
506 	pluma_message_get (message, "active", &active, NULL);
507 
508 	store = pluma_file_browser_widget_get_browser_store (data->widget);
509 	mode = pluma_file_browser_store_get_filter_mode (store);
510 
511 	if (active)
512 		mode &= ~PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN;
513 	else
514 		mode |= PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN;
515 
516 	pluma_file_browser_store_set_filter_mode (store, mode);
517 }
518 
519 static void
message_set_show_binary_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)520 message_set_show_binary_cb (PlumaMessageBus *bus,
521 		            PlumaMessage    *message,
522 		            WindowData      *data)
523 {
524 	gboolean active = FALSE;
525 	PlumaFileBrowserStore *store;
526 	PlumaFileBrowserStoreFilterMode mode;
527 
528 	pluma_message_get (message, "active", &active, NULL);
529 
530 	store = pluma_file_browser_widget_get_browser_store (data->widget);
531 	mode = pluma_file_browser_store_get_filter_mode (store);
532 
533 	if (active)
534 		mode &= ~PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY;
535 	else
536 		mode |= PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY;
537 
538 	pluma_file_browser_store_set_filter_mode (store, mode);
539 }
540 
541 static void
message_show_bookmarks_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)542 message_show_bookmarks_cb (PlumaMessageBus *bus,
543 		           PlumaMessage    *message,
544 		           WindowData      *data)
545 {
546 	pluma_file_browser_widget_show_bookmarks (data->widget);
547 }
548 
549 static void
message_show_files_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)550 message_show_files_cb (PlumaMessageBus *bus,
551 		       PlumaMessage    *message,
552 		       WindowData      *data)
553 {
554 	pluma_file_browser_widget_show_files (data->widget);
555 }
556 
557 static void
message_add_context_item_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)558 message_add_context_item_cb (PlumaMessageBus *bus,
559 			     PlumaMessage    *message,
560 			     WindowData      *data)
561 {
562 	GtkAction *action = NULL;
563 	gchar *path = NULL;
564 	gchar *name;
565 	GtkUIManager *manager;
566 	guint merge_id;
567 
568 	pluma_message_get (message,
569 			   "action", &action,
570 			   "path", &path,
571 			   NULL);
572 
573 	if (!action || !path)
574 	{
575 		if (action)
576 			g_object_unref (action);
577 
578 		g_free (path);
579 		return;
580 	}
581 
582 	gtk_action_group_add_action (data->merged_actions, action);
583 	manager = pluma_file_browser_widget_get_ui_manager (data->widget);
584 	name = g_strconcat (gtk_action_get_name (action), "MenuItem", NULL);
585 	merge_id = gtk_ui_manager_new_merge_id (manager);
586 
587 	gtk_ui_manager_add_ui (manager,
588 			       merge_id,
589 			       path,
590 			       name,
591 			       gtk_action_get_name (action),
592 			       GTK_UI_MANAGER_AUTO,
593 			       FALSE);
594 
595 	if (gtk_ui_manager_get_widget (manager, path))
596 	{
597 		data->merge_ids = g_list_prepend (data->merge_ids, GINT_TO_POINTER (merge_id));
598 		pluma_message_set (message, "id", merge_id, NULL);
599 	}
600 	else
601 	{
602 		pluma_message_set (message, "id", 0, NULL);
603 	}
604 
605 	g_object_unref (action);
606 	g_free (path);
607 	g_free (name);
608 }
609 
610 static void
message_remove_context_item_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)611 message_remove_context_item_cb (PlumaMessageBus *bus,
612 				PlumaMessage    *message,
613 				WindowData      *data)
614 {
615 	guint merge_id = 0;
616 	GtkUIManager *manager;
617 
618 	pluma_message_get (message, "id", &merge_id, NULL);
619 
620 	if (merge_id == 0)
621 		return;
622 
623 	manager = pluma_file_browser_widget_get_ui_manager (data->widget);
624 
625 	data->merge_ids = g_list_remove (data->merge_ids, GINT_TO_POINTER (merge_id));
626 	gtk_ui_manager_remove_ui (manager, merge_id);
627 }
628 
629 static void
message_get_view_cb(PlumaMessageBus * bus,PlumaMessage * message,WindowData * data)630 message_get_view_cb (PlumaMessageBus *bus,
631 		     PlumaMessage    *message,
632 		     WindowData      *data)
633 {
634 	PlumaFileBrowserView *view;
635 	view = pluma_file_browser_widget_get_browser_view (data->widget);
636 
637 	pluma_message_set (message, "view", view, NULL);
638 }
639 
640 static void
register_methods(PlumaWindow * window,PlumaFileBrowserWidget * widget)641 register_methods (PlumaWindow            *window,
642 		  PlumaFileBrowserWidget *widget)
643 {
644 	PlumaMessageBus *bus = pluma_window_get_message_bus (window);
645 	WindowData *data = get_window_data (window);
646 
647 	/* Register method calls */
648 	pluma_message_bus_register (bus,
649 				    MESSAGE_OBJECT_PATH, "get_root",
650 				    1,
651 				    "uri", G_TYPE_STRING,
652 				    NULL);
653 
654 	pluma_message_bus_register (bus,
655 				    MESSAGE_OBJECT_PATH, "set_root",
656 				    1,
657 				    "uri", G_TYPE_STRING,
658 				    "virtual", G_TYPE_STRING,
659 				    NULL);
660 
661 	pluma_message_bus_register (bus,
662 				    MESSAGE_OBJECT_PATH, "set_emblem",
663 				    0,
664 				    "id", G_TYPE_STRING,
665 				    "emblem", G_TYPE_STRING,
666 				    NULL);
667 
668 	pluma_message_bus_register (bus,
669 				    MESSAGE_OBJECT_PATH, "add_filter",
670 				    1,
671 				    "object_path", G_TYPE_STRING,
672 				    "method", G_TYPE_STRING,
673 				    "id", G_TYPE_ULONG,
674 				    NULL);
675 
676 	pluma_message_bus_register (bus,
677 				    MESSAGE_OBJECT_PATH, "remove_filter",
678 				    0,
679 				    "id", G_TYPE_ULONG,
680 				    NULL);
681 
682 	pluma_message_bus_register (bus,
683 				    MESSAGE_OBJECT_PATH, "add_context_item",
684 				    1,
685 				    "action", GTK_TYPE_ACTION,
686 				    "path", G_TYPE_STRING,
687 				    "id", G_TYPE_UINT,
688 				    NULL);
689 
690 	pluma_message_bus_register (bus,
691 				    MESSAGE_OBJECT_PATH, "remove_context_item",
692 				    0,
693 				    "id", G_TYPE_UINT,
694 				    NULL);
695 
696 	pluma_message_bus_register (bus, MESSAGE_OBJECT_PATH, "up", 0, NULL);
697 
698 	pluma_message_bus_register (bus, MESSAGE_OBJECT_PATH, "history_back", 0, NULL);
699 	pluma_message_bus_register (bus, MESSAGE_OBJECT_PATH, "history_forward", 0, NULL);
700 
701 	pluma_message_bus_register (bus, MESSAGE_OBJECT_PATH, "refresh", 0, NULL);
702 
703 	pluma_message_bus_register (bus,
704 				    MESSAGE_OBJECT_PATH, "set_show_hidden",
705 				    0,
706 				    "active", G_TYPE_BOOLEAN,
707 				    NULL);
708 	pluma_message_bus_register (bus,
709 				    MESSAGE_OBJECT_PATH, "set_show_binary",
710 				    0,
711 				    "active", G_TYPE_BOOLEAN,
712 				    NULL);
713 
714 	pluma_message_bus_register (bus, MESSAGE_OBJECT_PATH, "show_bookmarks", 0, NULL);
715 	pluma_message_bus_register (bus, MESSAGE_OBJECT_PATH, "show_files", 0, NULL);
716 
717 	pluma_message_bus_register (bus,
718 				    MESSAGE_OBJECT_PATH, "get_view",
719 				    1,
720 				    "view", PLUMA_TYPE_FILE_BROWSER_VIEW,
721 				    NULL);
722 
723 	BUS_CONNECT (bus, get_root, data);
724 	BUS_CONNECT (bus, set_root, data);
725 	BUS_CONNECT (bus, set_emblem, data);
726 	BUS_CONNECT (bus, add_filter, window);
727 	BUS_CONNECT (bus, remove_filter, data);
728 
729 	BUS_CONNECT (bus, add_context_item, data);
730 	BUS_CONNECT (bus, remove_context_item, data);
731 
732 	BUS_CONNECT (bus, up, data);
733 	BUS_CONNECT (bus, history_back, data);
734 	BUS_CONNECT (bus, history_forward, data);
735 
736 	BUS_CONNECT (bus, refresh, data);
737 
738 	BUS_CONNECT (bus, set_show_hidden, data);
739 	BUS_CONNECT (bus, set_show_binary, data);
740 
741 	BUS_CONNECT (bus, show_bookmarks, data);
742 	BUS_CONNECT (bus, show_files, data);
743 
744 	BUS_CONNECT (bus, get_view, data);
745 }
746 
747 static void
store_row_inserted(PlumaFileBrowserStore * store,GtkTreePath * path,GtkTreeIter * iter,MessageCacheData * data)748 store_row_inserted (PlumaFileBrowserStore *store,
749 		    GtkTreePath		  *path,
750 		    GtkTreeIter           *iter,
751 		    MessageCacheData      *data)
752 {
753 	gchar *uri = NULL;
754 	guint flags = 0;
755 
756 	gtk_tree_model_get (GTK_TREE_MODEL (store), iter,
757 			    PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
758 			    PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
759 			    -1);
760 
761 	if (!FILE_IS_DUMMY (flags) && !FILE_IS_FILTERED (flags))
762 	{
763 		WindowData *wdata = get_window_data (data->window);
764 
765 		set_item_message (wdata, iter, path, data->message);
766 		pluma_message_bus_send_message_sync (wdata->bus, data->message);
767 	}
768 
769 	g_free (uri);
770 }
771 
772 static void
store_row_deleted(PlumaFileBrowserStore * store,GtkTreePath * path,MessageCacheData * data)773 store_row_deleted (PlumaFileBrowserStore *store,
774 		   GtkTreePath		 *path,
775 		   MessageCacheData      *data)
776 {
777 	GtkTreeIter iter;
778 	gchar *uri = NULL;
779 	guint flags = 0;
780 
781 	if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
782 		return;
783 
784 	gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
785 			    PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
786 			    PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
787 			    -1);
788 
789 	if (!FILE_IS_DUMMY (flags) && !FILE_IS_FILTERED (flags))
790 	{
791 		WindowData *wdata = get_window_data (data->window);
792 
793 		set_item_message (wdata, &iter, path, data->message);
794 		pluma_message_bus_send_message_sync (wdata->bus, data->message);
795 	}
796 
797 	g_free (uri);
798 }
799 
800 static void
store_virtual_root_changed(PlumaFileBrowserStore * store,GParamSpec * spec,MessageCacheData * data)801 store_virtual_root_changed (PlumaFileBrowserStore *store,
802 			    GParamSpec            *spec,
803 			    MessageCacheData      *data)
804 {
805 	WindowData *wdata = get_window_data (data->window);
806 	gchar *uri;
807 
808 	uri = pluma_file_browser_store_get_virtual_root (store);
809 
810 	if (!uri)
811 		return;
812 
813 	pluma_message_set (data->message,
814 			   "uri", uri,
815 			   NULL);
816 
817 	pluma_message_bus_send_message_sync (wdata->bus, data->message);
818 
819 	g_free (uri);
820 }
821 
822 static void
store_begin_loading(PlumaFileBrowserStore * store,GtkTreeIter * iter,MessageCacheData * data)823 store_begin_loading (PlumaFileBrowserStore *store,
824 		     GtkTreeIter           *iter,
825 		     MessageCacheData      *data)
826 {
827 	GtkTreePath *path;
828 	WindowData *wdata = get_window_data (data->window);
829 
830 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
831 
832 	set_item_message (wdata, iter, path, data->message);
833 
834 	pluma_message_bus_send_message_sync (wdata->bus, data->message);
835 	gtk_tree_path_free (path);
836 }
837 
838 static void
store_end_loading(PlumaFileBrowserStore * store,GtkTreeIter * iter,MessageCacheData * data)839 store_end_loading (PlumaFileBrowserStore *store,
840 		   GtkTreeIter           *iter,
841 		   MessageCacheData      *data)
842 {
843 	GtkTreePath *path;
844 	WindowData *wdata = get_window_data (data->window);
845 
846 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
847 
848 	set_item_message (wdata, iter, path, data->message);
849 
850 	pluma_message_bus_send_message_sync (wdata->bus, data->message);
851 	gtk_tree_path_free (path);
852 }
853 
854 static void
register_signals(PlumaWindow * window,PlumaFileBrowserWidget * widget)855 register_signals (PlumaWindow            *window,
856 		  PlumaFileBrowserWidget *widget)
857 {
858 	PlumaMessageBus *bus = pluma_window_get_message_bus (window);
859 	PlumaFileBrowserStore *store;
860 	PlumaMessageType *inserted_type;
861 	PlumaMessageType *deleted_type;
862 	PlumaMessageType *begin_loading_type;
863 	PlumaMessageType *end_loading_type;
864 	PlumaMessageType *root_changed_type;
865 
866 	PlumaMessage *message;
867 	WindowData *data;
868 
869 	/* Register signals */
870 	root_changed_type = pluma_message_bus_register (bus,
871 				    MESSAGE_OBJECT_PATH, "root_changed",
872 				    0,
873 				    "id", G_TYPE_STRING,
874 				    "uri", G_TYPE_STRING,
875 				    NULL);
876 
877 	begin_loading_type = pluma_message_bus_register (bus,
878 				    MESSAGE_OBJECT_PATH, "begin_loading",
879 				    0,
880 				    "id", G_TYPE_STRING,
881 				    "uri", G_TYPE_STRING,
882 				    NULL);
883 
884 	end_loading_type = pluma_message_bus_register (bus,
885 				    MESSAGE_OBJECT_PATH, "end_loading",
886 				    0,
887 				    "id", G_TYPE_STRING,
888 				    "uri", G_TYPE_STRING,
889 				    NULL);
890 
891 	inserted_type = pluma_message_bus_register (bus,
892 						    MESSAGE_OBJECT_PATH, "inserted",
893 						    0,
894 						    "id", G_TYPE_STRING,
895 						    "uri", G_TYPE_STRING,
896 						    "is_directory", G_TYPE_BOOLEAN,
897 						    NULL);
898 
899 	deleted_type = pluma_message_bus_register (bus,
900 						   MESSAGE_OBJECT_PATH, "deleted",
901 						   0,
902 						   "id", G_TYPE_STRING,
903 						   "uri", G_TYPE_STRING,
904 						   "is_directory", G_TYPE_BOOLEAN,
905 						   NULL);
906 
907 	store = pluma_file_browser_widget_get_browser_store (widget);
908 
909 	message = pluma_message_type_instantiate (inserted_type,
910 						  "id", NULL,
911 						  "uri", NULL,
912 						  "is_directory", FALSE,
913 						  NULL);
914 
915 	data = get_window_data (window);
916 
917 	data->row_inserted_id =
918 		g_signal_connect_data (store,
919 				       "row-inserted",
920 				       G_CALLBACK (store_row_inserted),
921 				       message_cache_data_new (window, message),
922 				       (GClosureNotify)message_cache_data_free,
923 				       0);
924 
925 	message = pluma_message_type_instantiate (deleted_type,
926 						  "id", NULL,
927 						  "uri", NULL,
928 						  "is_directory", FALSE,
929 						  NULL);
930 	data->row_deleted_id =
931 		g_signal_connect_data (store,
932 				       "row-deleted",
933 				       G_CALLBACK (store_row_deleted),
934 				       message_cache_data_new (window, message),
935 				       (GClosureNotify)message_cache_data_free,
936 				       0);
937 
938 	message = pluma_message_type_instantiate (root_changed_type,
939 						  "id", NULL,
940 						  "uri", NULL,
941 						  NULL);
942 	data->root_changed_id =
943 		g_signal_connect_data (store,
944 				       "notify::virtual-root",
945 				       G_CALLBACK (store_virtual_root_changed),
946 				       message_cache_data_new (window, message),
947 				       (GClosureNotify)message_cache_data_free,
948 				       0);
949 
950 	message = pluma_message_type_instantiate (begin_loading_type,
951 						  "id", NULL,
952 						  "uri", NULL,
953 						  NULL);
954 	data->begin_loading_id =
955 		g_signal_connect_data (store,
956 				      "begin_loading",
957 				       G_CALLBACK (store_begin_loading),
958 				       message_cache_data_new (window, message),
959 				       (GClosureNotify)message_cache_data_free,
960 				       0);
961 
962 	message = pluma_message_type_instantiate (end_loading_type,
963 						  "id", NULL,
964 						  "uri", NULL,
965 						  NULL);
966 	data->end_loading_id =
967 		g_signal_connect_data (store,
968 				       "end_loading",
969 				       G_CALLBACK (store_end_loading),
970 				       message_cache_data_new (window, message),
971 				       (GClosureNotify)message_cache_data_free,
972 				       0);
973 }
974 
975 static void
message_unregistered(PlumaMessageBus * bus,PlumaMessageType * message_type,PlumaWindow * window)976 message_unregistered (PlumaMessageBus  *bus,
977 		      PlumaMessageType *message_type,
978 		      PlumaWindow      *window)
979 {
980 	gchar *identifier = pluma_message_type_identifier (pluma_message_type_get_object_path (message_type),
981 							   pluma_message_type_get_method (message_type));
982 	FilterData *data;
983 	WindowData *wdata = get_window_data (window);
984 
985 	data = g_hash_table_lookup (wdata->filters, identifier);
986 
987 	if (data)
988 		pluma_file_browser_widget_remove_filter (wdata->widget, data->id);
989 
990 	g_free (identifier);
991 }
992 
993 void
pluma_file_browser_messages_register(PlumaWindow * window,PlumaFileBrowserWidget * widget)994 pluma_file_browser_messages_register (PlumaWindow            *window,
995 				      PlumaFileBrowserWidget *widget)
996 {
997 	window_data_new (window, widget);
998 
999 	register_methods (window, widget);
1000 	register_signals (window, widget);
1001 
1002 	g_signal_connect (pluma_window_get_message_bus (window),
1003 			  "unregistered",
1004 			  G_CALLBACK (message_unregistered),
1005 			  window);
1006 }
1007 
1008 static void
cleanup_signals(PlumaWindow * window)1009 cleanup_signals (PlumaWindow *window)
1010 {
1011 	WindowData *data = get_window_data (window);
1012 	PlumaFileBrowserStore *store;
1013 
1014 	store = pluma_file_browser_widget_get_browser_store (data->widget);
1015 
1016 	g_signal_handler_disconnect (store, data->row_inserted_id);
1017 	g_signal_handler_disconnect (store, data->row_deleted_id);
1018 	g_signal_handler_disconnect (store, data->root_changed_id);
1019 	g_signal_handler_disconnect (store, data->begin_loading_id);
1020 	g_signal_handler_disconnect (store, data->end_loading_id);
1021 
1022 	g_signal_handlers_disconnect_by_func (data->bus, message_unregistered, window);
1023 }
1024 
1025 void
pluma_file_browser_messages_unregister(PlumaWindow * window)1026 pluma_file_browser_messages_unregister (PlumaWindow *window)
1027 {
1028 	PlumaMessageBus *bus = pluma_window_get_message_bus (window);
1029 
1030 	cleanup_signals (window);
1031 	pluma_message_bus_unregister_all (bus, MESSAGE_OBJECT_PATH);
1032 
1033 	window_data_free (window);
1034 }
1035