1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ |
---|
2 | /** |
---|
3 | * eog-collection-view.c |
---|
4 | * |
---|
5 | * Authors: |
---|
6 | * Martin Baulig (baulig@suse.de) |
---|
7 | * Jens Finke (jens@gnome.org) |
---|
8 | * |
---|
9 | * Copyright 2000 SuSE GmbH. |
---|
10 | * Copyright 2001 The Free Software Foundation |
---|
11 | */ |
---|
12 | #include <config.h> |
---|
13 | #include <stdio.h> |
---|
14 | #include <gtk/gtksignal.h> |
---|
15 | #include <gtk/gtkmarshal.h> |
---|
16 | #include <gtk/gtktypeutils.h> |
---|
17 | #include <gtk/gtklabel.h> |
---|
18 | #include <gtk/gtkwindow.h> |
---|
19 | #include <libgnomevfs/gnome-vfs-types.h> |
---|
20 | #include <libgnomevfs/gnome-vfs-uri.h> |
---|
21 | #include <libgnomevfs/gnome-vfs-ops.h> |
---|
22 | #include <libgnomevfs/gnome-vfs-result.h> |
---|
23 | #include <libgnomevfs/gnome-vfs-find-directory.h> |
---|
24 | #include <libgnomeui/gnome-dialog-util.h> |
---|
25 | #include <gconf/gconf-client.h> |
---|
26 | #include <bonobo/bonobo-macros.h> |
---|
27 | #include <bonobo/bonobo-persist-file.h> |
---|
28 | |
---|
29 | #ifdef ENABLE_EVOLUTION |
---|
30 | # include "Evolution-Composer.h" |
---|
31 | #endif |
---|
32 | |
---|
33 | #if HAVE_LIBPREVIEW |
---|
34 | #include "eog-image-loader-preview.h" |
---|
35 | #else |
---|
36 | #include "eog-image-loader-simple.h" |
---|
37 | #endif |
---|
38 | |
---|
39 | #include "eog-item-factory-clean.h" |
---|
40 | #include "eog-wrap-list.h" |
---|
41 | #include "eog-collection-view.h" |
---|
42 | #include "eog-collection-model.h" |
---|
43 | #include "eog-collection-preferences.h" |
---|
44 | #include "eog-collection-marshal.h" |
---|
45 | #include "eog-slide-show.h" |
---|
46 | |
---|
47 | enum { |
---|
48 | PROP_WINDOW_TITLE, |
---|
49 | PROP_WINDOW_STATUS, |
---|
50 | PROP_LAST |
---|
51 | }; |
---|
52 | |
---|
53 | static const gchar *property_name[] = { |
---|
54 | "window/title", |
---|
55 | "window/status" |
---|
56 | }; |
---|
57 | |
---|
58 | enum { |
---|
59 | PREF_LAYOUT, |
---|
60 | PREF_COLOR, |
---|
61 | PREF_LAST |
---|
62 | }; |
---|
63 | |
---|
64 | #define PREF_PREFIX "/apps/eog/collection" |
---|
65 | static const gchar *pref_key[] = { |
---|
66 | PREF_PREFIX"/layout", |
---|
67 | PREF_PREFIX"/color" |
---|
68 | }; |
---|
69 | |
---|
70 | struct _EogCollectionViewPrivate { |
---|
71 | EogCollectionModel *model; |
---|
72 | |
---|
73 | GtkWidget *wraplist; |
---|
74 | GtkWidget *root; |
---|
75 | |
---|
76 | BonoboPropertyBag *property_bag; |
---|
77 | |
---|
78 | BonoboUIComponent *uic; |
---|
79 | |
---|
80 | GConfClient *client; |
---|
81 | guint notify_id[PREF_LAST]; |
---|
82 | |
---|
83 | gint idle_id; |
---|
84 | gboolean need_update_prop[PROP_LAST]; |
---|
85 | }; |
---|
86 | |
---|
87 | |
---|
88 | enum { |
---|
89 | OPEN_URI, |
---|
90 | LAST_SIGNAL |
---|
91 | }; |
---|
92 | |
---|
93 | static guint eog_collection_view_signals [LAST_SIGNAL]; |
---|
94 | |
---|
95 | static void eog_collection_view_dispose (GObject *object); |
---|
96 | |
---|
97 | BONOBO_CLASS_BOILERPLATE_FULL (EogCollectionView, eog_collection_view, |
---|
98 | GNOME_EOG_ImageCollection, |
---|
99 | BonoboObject, BONOBO_TYPE_OBJECT); |
---|
100 | |
---|
101 | |
---|
102 | static void |
---|
103 | impl_GNOME_EOG_ImageCollection_openURI (PortableServer_Servant servant, |
---|
104 | const CORBA_char * uri, |
---|
105 | CORBA_Environment * ev) |
---|
106 | { |
---|
107 | EogCollectionView *cview; |
---|
108 | EogCollectionViewPrivate *priv; |
---|
109 | |
---|
110 | cview = EOG_COLLECTION_VIEW (bonobo_object_from_servant (servant)); |
---|
111 | priv = cview->priv; |
---|
112 | |
---|
113 | if (uri == CORBA_OBJECT_NIL) return; |
---|
114 | |
---|
115 | eog_collection_model_set_uri (priv->model, (gchar*)uri); |
---|
116 | } |
---|
117 | |
---|
118 | |
---|
119 | static void |
---|
120 | impl_GNOME_EOG_ImageCollection_openURIList (PortableServer_Servant servant, |
---|
121 | const GNOME_EOG_URIList *uri_list, |
---|
122 | CORBA_Environment * ev) |
---|
123 | { |
---|
124 | EogCollectionView *cview; |
---|
125 | EogCollectionViewPrivate *priv; |
---|
126 | GList *list; |
---|
127 | guint i; |
---|
128 | |
---|
129 | cview = EOG_COLLECTION_VIEW (bonobo_object_from_servant (servant)); |
---|
130 | priv = cview->priv; |
---|
131 | |
---|
132 | list = NULL; |
---|
133 | #ifdef COLLECTION_DEBUG |
---|
134 | g_print ("uri_list->_length: %i\n", uri_list->_length); |
---|
135 | #endif |
---|
136 | for (i = 0; i < uri_list->_length; i++) { |
---|
137 | list = g_list_append |
---|
138 | (list, g_strdup (uri_list->_buffer[i])); |
---|
139 | } |
---|
140 | |
---|
141 | eog_collection_model_set_uri_list (priv->model, list); |
---|
142 | |
---|
143 | g_list_foreach (list, (GFunc) g_free, NULL); |
---|
144 | g_list_free (list); |
---|
145 | } |
---|
146 | |
---|
147 | static void |
---|
148 | verb_SlideShow_cb (BonoboUIComponent *uic, |
---|
149 | gpointer user_data, |
---|
150 | const char *cname) |
---|
151 | { |
---|
152 | EogCollectionView *view; |
---|
153 | GtkWidget *show; |
---|
154 | |
---|
155 | view = EOG_COLLECTION_VIEW (user_data); |
---|
156 | |
---|
157 | show = eog_slide_show_new (view->priv->model); |
---|
158 | gtk_widget_show (show); |
---|
159 | } |
---|
160 | |
---|
161 | |
---|
162 | static BonoboUIVerb collection_verbs[] = { |
---|
163 | BONOBO_UI_VERB ("SlideShow", verb_SlideShow_cb), |
---|
164 | BONOBO_UI_VERB_END |
---|
165 | }; |
---|
166 | |
---|
167 | static void |
---|
168 | eog_collection_view_create_ui (EogCollectionView *view) |
---|
169 | { |
---|
170 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (view)); |
---|
171 | |
---|
172 | /* Set up the UI from an XML file. */ |
---|
173 | bonobo_ui_util_set_ui (view->priv->uic, DATADIR, |
---|
174 | "eog-collection-view-ui.xml", "EogCollectionView", NULL); |
---|
175 | |
---|
176 | bonobo_ui_component_add_verb_list_with_data (view->priv->uic, |
---|
177 | collection_verbs, |
---|
178 | view); |
---|
179 | } |
---|
180 | |
---|
181 | void |
---|
182 | eog_collection_view_set_ui_container (EogCollectionView *list_view, |
---|
183 | Bonobo_UIContainer ui_container) |
---|
184 | { |
---|
185 | g_return_if_fail (list_view != NULL); |
---|
186 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (list_view)); |
---|
187 | g_return_if_fail (ui_container != CORBA_OBJECT_NIL); |
---|
188 | |
---|
189 | bonobo_ui_component_set_container (list_view->priv->uic, ui_container, NULL); |
---|
190 | |
---|
191 | eog_collection_view_create_ui (list_view); |
---|
192 | } |
---|
193 | |
---|
194 | void |
---|
195 | eog_collection_view_unset_ui_container (EogCollectionView *list_view) |
---|
196 | { |
---|
197 | g_return_if_fail (list_view != NULL); |
---|
198 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (list_view)); |
---|
199 | |
---|
200 | bonobo_ui_component_unset_container (list_view->priv->uic, NULL); |
---|
201 | } |
---|
202 | |
---|
203 | GtkWidget * |
---|
204 | eog_collection_view_get_widget (EogCollectionView *list_view) |
---|
205 | { |
---|
206 | g_return_val_if_fail (list_view != NULL, NULL); |
---|
207 | g_return_val_if_fail (EOG_IS_COLLECTION_VIEW (list_view), NULL); |
---|
208 | |
---|
209 | gtk_widget_ref (list_view->priv->root); |
---|
210 | |
---|
211 | return list_view->priv->root; |
---|
212 | } |
---|
213 | |
---|
214 | static void |
---|
215 | eog_collection_view_dispose (GObject *object) |
---|
216 | { |
---|
217 | EogCollectionView *list_view; |
---|
218 | |
---|
219 | g_return_if_fail (object != NULL); |
---|
220 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (object)); |
---|
221 | |
---|
222 | list_view = EOG_COLLECTION_VIEW (object); |
---|
223 | |
---|
224 | if (list_view->priv->model) |
---|
225 | g_object_unref (G_OBJECT (list_view->priv->model)); |
---|
226 | list_view->priv->model = NULL; |
---|
227 | |
---|
228 | if (list_view->priv->property_bag) |
---|
229 | bonobo_object_unref (BONOBO_OBJECT (list_view->priv->property_bag)); |
---|
230 | list_view->priv->property_bag = NULL; |
---|
231 | |
---|
232 | if (list_view->priv->client) |
---|
233 | g_object_unref (G_OBJECT (list_view->priv->client)); |
---|
234 | list_view->priv->client = NULL; |
---|
235 | |
---|
236 | if (list_view->priv->uic) |
---|
237 | bonobo_object_unref (BONOBO_OBJECT (list_view->priv->uic)); |
---|
238 | list_view->priv->uic = NULL; |
---|
239 | |
---|
240 | list_view->priv->wraplist = NULL; |
---|
241 | list_view->priv->root = NULL; |
---|
242 | |
---|
243 | BONOBO_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); |
---|
244 | } |
---|
245 | |
---|
246 | static void |
---|
247 | eog_collection_view_finalize (GObject *object) |
---|
248 | { |
---|
249 | EogCollectionView *list_view; |
---|
250 | |
---|
251 | g_return_if_fail (object != NULL); |
---|
252 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (object)); |
---|
253 | |
---|
254 | list_view = EOG_COLLECTION_VIEW (object); |
---|
255 | |
---|
256 | g_free (list_view->priv); |
---|
257 | |
---|
258 | BONOBO_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); |
---|
259 | } |
---|
260 | |
---|
261 | static void |
---|
262 | eog_collection_view_class_init (EogCollectionViewClass *klass) |
---|
263 | { |
---|
264 | GObjectClass *object_class = (GObjectClass *)klass; |
---|
265 | POA_GNOME_EOG_ImageCollection__epv *epv; |
---|
266 | |
---|
267 | object_class->dispose = eog_collection_view_dispose; |
---|
268 | object_class->finalize = eog_collection_view_finalize; |
---|
269 | |
---|
270 | epv = &klass->epv; |
---|
271 | epv->openURI = impl_GNOME_EOG_ImageCollection_openURI; |
---|
272 | epv->openURIList = impl_GNOME_EOG_ImageCollection_openURIList; |
---|
273 | |
---|
274 | eog_collection_view_signals [OPEN_URI] = |
---|
275 | g_signal_new ("open_uri", |
---|
276 | G_TYPE_FROM_CLASS(object_class), |
---|
277 | G_SIGNAL_RUN_FIRST, |
---|
278 | G_STRUCT_OFFSET (EogCollectionViewClass, open_uri), |
---|
279 | NULL, |
---|
280 | NULL, |
---|
281 | eog_collection_marshal_VOID__POINTER, |
---|
282 | G_TYPE_NONE, 1, |
---|
283 | G_TYPE_POINTER); |
---|
284 | } |
---|
285 | |
---|
286 | static void |
---|
287 | eog_collection_view_instance_init (EogCollectionView *view) |
---|
288 | { |
---|
289 | view->priv = g_new0 (EogCollectionViewPrivate, 1); |
---|
290 | view->priv->idle_id = -1; |
---|
291 | } |
---|
292 | |
---|
293 | static void |
---|
294 | handle_double_click (EogWrapList *wlist, gint n, EogCollectionView *view) |
---|
295 | { |
---|
296 | gchar *uri; |
---|
297 | |
---|
298 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (view)); |
---|
299 | |
---|
300 | uri = eog_collection_model_get_uri (view->priv->model, n); |
---|
301 | if (uri == NULL) return; |
---|
302 | |
---|
303 | g_signal_emit (G_OBJECT (view), eog_collection_view_signals [OPEN_URI], 0, uri); |
---|
304 | |
---|
305 | g_free (uri); |
---|
306 | } |
---|
307 | |
---|
308 | static gboolean |
---|
309 | delete_item (EogCollectionModel *model, CImage *image, gpointer user_data) |
---|
310 | { |
---|
311 | GnomeVFSURI *uri, *trash = NULL, *path; |
---|
312 | GnomeVFSResult result = GNOME_VFS_OK; |
---|
313 | const gchar *msg; |
---|
314 | EogCollectionView *view; |
---|
315 | GtkWidget *dialog; |
---|
316 | |
---|
317 | g_return_val_if_fail (EOG_IS_COLLECTION_VIEW (user_data), FALSE); |
---|
318 | view = EOG_COLLECTION_VIEW (user_data); |
---|
319 | |
---|
320 | /* If the image isn't selected, do nothing */ |
---|
321 | if (!cimage_is_selected (image)) |
---|
322 | return (TRUE); |
---|
323 | |
---|
324 | uri = cimage_get_uri (image); |
---|
325 | result = gnome_vfs_find_directory (uri, |
---|
326 | GNOME_VFS_DIRECTORY_KIND_TRASH, |
---|
327 | &trash, FALSE, FALSE, 0777); |
---|
328 | if (result == GNOME_VFS_OK) { |
---|
329 | path = gnome_vfs_uri_append_file_name (trash, |
---|
330 | gnome_vfs_uri_get_path (uri)); |
---|
331 | gnome_vfs_uri_unref (trash); |
---|
332 | result = gnome_vfs_move_uri (uri, path, TRUE); |
---|
333 | gnome_vfs_uri_unref (path); |
---|
334 | if (result == GNOME_VFS_OK) |
---|
335 | eog_collection_model_remove_item (model, cimage_get_unique_id (image)); |
---|
336 | } |
---|
337 | gnome_vfs_uri_unref (uri); |
---|
338 | |
---|
339 | if (result != GNOME_VFS_OK) { |
---|
340 | msg = gnome_vfs_result_to_string (result); |
---|
341 | |
---|
342 | dialog = gtk_message_dialog_new ( |
---|
343 | NULL, GTK_DIALOG_MODAL, |
---|
344 | GTK_MESSAGE_ERROR, |
---|
345 | GTK_BUTTONS_CLOSE, |
---|
346 | msg); |
---|
347 | gtk_dialog_run (GTK_DIALOG (dialog)); |
---|
348 | gtk_widget_destroy (dialog); |
---|
349 | |
---|
350 | return (FALSE); |
---|
351 | } |
---|
352 | |
---|
353 | return (TRUE); |
---|
354 | } |
---|
355 | |
---|
356 | static void |
---|
357 | handle_delete_activate (GtkMenuItem *item, EogCollectionView *view) |
---|
358 | { |
---|
359 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (view)); |
---|
360 | |
---|
361 | eog_collection_model_foreach (view->priv->model, delete_item, view); |
---|
362 | } |
---|
363 | |
---|
364 | #ifdef ENABLE_EVOLUTION |
---|
365 | static gboolean |
---|
366 | send_item (EogCollectionModel *model, guint n, gpointer user_data) |
---|
367 | { |
---|
368 | Bonobo_StorageInfo *info; |
---|
369 | Bonobo_Stream stream; |
---|
370 | Bonobo_Stream_iobuf *buffer; |
---|
371 | CORBA_Object composer; |
---|
372 | GNOME_Evolution_Composer_AttachmentData *attachment_data; |
---|
373 | CORBA_Environment ev; |
---|
374 | gchar *uri; |
---|
375 | CImage *image; |
---|
376 | |
---|
377 | g_return_val_if_fail (EOG_IS_COLLECTION_MODEL (model), FALSE); |
---|
378 | composer = user_data; |
---|
379 | |
---|
380 | image = eog_collection_model_get_image (model, n); |
---|
381 | |
---|
382 | /* If the image isn't selected, do nothing */ |
---|
383 | if (!cimage_is_selected (image)) |
---|
384 | return (TRUE); |
---|
385 | |
---|
386 | CORBA_exception_init (&ev); |
---|
387 | |
---|
388 | uri = eog_collection_model_get_uri (model, n); |
---|
389 | stream = bonobo_get_object (uri, "IDL:Bonobo/Stream:1.0", &ev); |
---|
390 | g_free (uri); |
---|
391 | if (BONOBO_EX (&ev)) { |
---|
392 | g_warning ("Could not load file: %s", |
---|
393 | bonobo_exception_get_text (&ev)); |
---|
394 | return (FALSE); |
---|
395 | } |
---|
396 | |
---|
397 | info = Bonobo_Stream_getInfo (stream, Bonobo_FIELD_CONTENT_TYPE | |
---|
398 | Bonobo_FIELD_SIZE, &ev); |
---|
399 | if (BONOBO_EX (&ev)) { |
---|
400 | bonobo_object_release_unref (stream, NULL); |
---|
401 | g_warning ("Could not get info about stream: %s", |
---|
402 | bonobo_exception_get_text (&ev)); |
---|
403 | return (FALSE); |
---|
404 | } |
---|
405 | |
---|
406 | Bonobo_Stream_read (stream, info->size, &buffer, &ev); |
---|
407 | bonobo_object_release_unref (stream, NULL); |
---|
408 | if (BONOBO_EX (&ev)) { |
---|
409 | CORBA_free (info); |
---|
410 | g_warning ("Could not read stream: %s", |
---|
411 | bonobo_exception_get_text (&ev)); |
---|
412 | return (FALSE); |
---|
413 | } |
---|
414 | |
---|
415 | attachment_data = GNOME_Evolution_Composer_AttachmentData__alloc (); |
---|
416 | attachment_data->_buffer = buffer->_buffer; |
---|
417 | attachment_data->_length = buffer->_length; |
---|
418 | GNOME_Evolution_Composer_attachData (composer, info->content_type, |
---|
419 | info->name, info->name, FALSE, |
---|
420 | attachment_data, &ev); |
---|
421 | CORBA_free (info); |
---|
422 | CORBA_free (attachment_data); |
---|
423 | if (BONOBO_EX (&ev)) { |
---|
424 | g_warning ("Unable to attach image: %s", |
---|
425 | bonobo_exception_get_text (&ev)); |
---|
426 | CORBA_exception_free (&ev); |
---|
427 | return (FALSE); |
---|
428 | } |
---|
429 | |
---|
430 | CORBA_exception_free (&ev); |
---|
431 | |
---|
432 | return (TRUE); |
---|
433 | } |
---|
434 | |
---|
435 | static void |
---|
436 | handle_send_activate (GtkMenuItem *item, EogCollectionView *view) |
---|
437 | { |
---|
438 | CORBA_Object composer; |
---|
439 | CORBA_Environment ev; |
---|
440 | |
---|
441 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (view)); |
---|
442 | |
---|
443 | CORBA_exception_init (&ev); |
---|
444 | composer = oaf_activate_from_id ("OAFIID:GNOME_Evolution_Mail_Composer", |
---|
445 | 0, NULL, &ev); |
---|
446 | if (BONOBO_EX (&ev)) { |
---|
447 | g_warning ("Unable to start composer: %s", |
---|
448 | bonobo_exception_get_text (&ev)); |
---|
449 | CORBA_exception_free (&ev); |
---|
450 | return; |
---|
451 | } |
---|
452 | |
---|
453 | eog_collection_model_foreach (view->priv->model, send_item, composer); |
---|
454 | |
---|
455 | GNOME_Evolution_Composer_show (composer, &ev); |
---|
456 | if (BONOBO_EX (&ev)) { |
---|
457 | g_warning ("Unable to show composer: %s", |
---|
458 | bonobo_exception_get_text (&ev)); |
---|
459 | CORBA_exception_free (&ev); |
---|
460 | bonobo_object_release_unref (composer, NULL); |
---|
461 | return; |
---|
462 | } |
---|
463 | |
---|
464 | CORBA_exception_free (&ev); |
---|
465 | } |
---|
466 | #endif |
---|
467 | |
---|
468 | static void |
---|
469 | kill_popup_menu (GtkWidget *widget, GtkMenu *menu) |
---|
470 | { |
---|
471 | g_return_if_fail (GTK_IS_MENU (menu)); |
---|
472 | |
---|
473 | g_object_unref (G_OBJECT (menu)); |
---|
474 | } |
---|
475 | |
---|
476 | static gboolean |
---|
477 | handle_right_click (EogWrapList *wlist, gint n, GdkEvent *event, |
---|
478 | EogCollectionView *view) |
---|
479 | { |
---|
480 | GtkWidget *menu, *item, *label; |
---|
481 | |
---|
482 | g_return_val_if_fail (EOG_IS_COLLECTION_VIEW (view), FALSE); |
---|
483 | |
---|
484 | menu = gtk_menu_new (); |
---|
485 | g_signal_connect (G_OBJECT (menu), "hide", |
---|
486 | G_CALLBACK (kill_popup_menu), menu); |
---|
487 | |
---|
488 | #ifdef ENABLE_EVOLUTION |
---|
489 | label = gtk_label_new (_("Send")); |
---|
490 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
---|
491 | gtk_widget_show (label); |
---|
492 | |
---|
493 | item = gtk_menu_item_new (); |
---|
494 | gtk_widget_show (item); |
---|
495 | g_signal_connect (G_OBJECT (item), "activate", |
---|
496 | G_CALLBACK (handle_send_activate), view); |
---|
497 | gtk_container_add (GTK_CONTAINER (item), label); |
---|
498 | gtk_menu_append (GTK_MENU (menu), item); |
---|
499 | #endif |
---|
500 | |
---|
501 | label = gtk_label_new (_("Move to Trash")); |
---|
502 | gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
---|
503 | gtk_widget_show (label); |
---|
504 | |
---|
505 | item = gtk_menu_item_new (); |
---|
506 | gtk_widget_show (item); |
---|
507 | g_signal_connect (G_OBJECT (item), "activate", |
---|
508 | G_CALLBACK (handle_delete_activate), view); |
---|
509 | gtk_container_add (GTK_CONTAINER (item), label); |
---|
510 | gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); |
---|
511 | |
---|
512 | gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, |
---|
513 | event->button.button, event->button.time); |
---|
514 | |
---|
515 | return (TRUE); |
---|
516 | } |
---|
517 | |
---|
518 | static void |
---|
519 | eog_collection_view_get_prop (BonoboPropertyBag *bag, |
---|
520 | BonoboArg *arg, |
---|
521 | guint arg_id, |
---|
522 | CORBA_Environment *ev, |
---|
523 | gpointer user_data) |
---|
524 | { |
---|
525 | EogCollectionView *view; |
---|
526 | EogCollectionViewPrivate *priv; |
---|
527 | |
---|
528 | g_return_if_fail (user_data != NULL); |
---|
529 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (user_data)); |
---|
530 | |
---|
531 | view = EOG_COLLECTION_VIEW (user_data); |
---|
532 | priv = view->priv; |
---|
533 | |
---|
534 | switch (arg_id) { |
---|
535 | case PROP_WINDOW_TITLE: { |
---|
536 | gchar *base_uri; |
---|
537 | gchar *title; |
---|
538 | |
---|
539 | base_uri = eog_collection_model_get_base_uri (priv->model); |
---|
540 | |
---|
541 | if (base_uri == NULL) |
---|
542 | title = g_strdup (_("Collection View")); |
---|
543 | else { |
---|
544 | if (g_ascii_strncasecmp ("file:", base_uri, 5) == 0) |
---|
545 | title = g_strdup ((base_uri+5*sizeof(guchar))); |
---|
546 | else |
---|
547 | title = g_strdup (base_uri); |
---|
548 | } |
---|
549 | |
---|
550 | BONOBO_ARG_SET_STRING (arg, title); |
---|
551 | g_free (title); |
---|
552 | break; |
---|
553 | } |
---|
554 | case PROP_WINDOW_STATUS: { |
---|
555 | gchar *str; |
---|
556 | gint nimg, nsel; |
---|
557 | |
---|
558 | nimg = eog_collection_model_get_length (priv->model); |
---|
559 | nsel = eog_collection_model_get_selected_length (priv->model); |
---|
560 | |
---|
561 | str = g_new0 (guchar, 70); |
---|
562 | |
---|
563 | if (nsel == 0) |
---|
564 | g_snprintf (str, 70, "Images: %i", nimg); |
---|
565 | else if (nsel == 1) { |
---|
566 | CImage *img; |
---|
567 | GnomeVFSURI *uri; |
---|
568 | gchar *basename; |
---|
569 | |
---|
570 | img = eog_collection_model_get_selected_image (priv->model); |
---|
571 | uri = cimage_get_uri (img); |
---|
572 | g_assert (uri != NULL); |
---|
573 | |
---|
574 | basename = g_path_get_basename (gnome_vfs_uri_get_path (uri)); |
---|
575 | g_snprintf (str, 70, "Images: %i %s (%i x %i)", nimg, |
---|
576 | basename, |
---|
577 | cimage_get_width (img), |
---|
578 | cimage_get_height (img)); |
---|
579 | |
---|
580 | gnome_vfs_uri_unref (uri); |
---|
581 | g_free (basename); |
---|
582 | } else |
---|
583 | g_snprintf (str, 70, "Images: %i Selected: %i", nimg, nsel); |
---|
584 | |
---|
585 | BONOBO_ARG_SET_STRING (arg, str); |
---|
586 | g_free (str); |
---|
587 | break; |
---|
588 | } |
---|
589 | default: |
---|
590 | g_assert_not_reached (); |
---|
591 | } |
---|
592 | } |
---|
593 | |
---|
594 | static void |
---|
595 | eog_collection_view_set_prop (BonoboPropertyBag *bag, |
---|
596 | const BonoboArg *arg, |
---|
597 | guint arg_id, |
---|
598 | CORBA_Environment *ev, |
---|
599 | gpointer user_data) |
---|
600 | { |
---|
601 | EogCollectionView *view; |
---|
602 | |
---|
603 | g_return_if_fail (user_data != NULL); |
---|
604 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (user_data)); |
---|
605 | |
---|
606 | view = EOG_COLLECTION_VIEW (user_data); |
---|
607 | |
---|
608 | switch (arg_id) { |
---|
609 | /* all properties are read only yet */ |
---|
610 | default: |
---|
611 | g_assert_not_reached (); |
---|
612 | } |
---|
613 | } |
---|
614 | |
---|
615 | static gint |
---|
616 | update_properties (EogCollectionView *view) |
---|
617 | { |
---|
618 | EogCollectionViewPrivate *priv; |
---|
619 | BonoboArg *arg; |
---|
620 | gint p; |
---|
621 | |
---|
622 | g_return_val_if_fail (view != NULL, FALSE); |
---|
623 | |
---|
624 | priv = view->priv; |
---|
625 | |
---|
626 | arg = bonobo_arg_new (BONOBO_ARG_STRING); |
---|
627 | |
---|
628 | for (p = 0; p < PROP_LAST; p++) { |
---|
629 | if (priv->need_update_prop[p]) { |
---|
630 | eog_collection_view_get_prop (NULL, arg, |
---|
631 | p, NULL, |
---|
632 | view); |
---|
633 | |
---|
634 | g_print ("notify %s listners.\n", property_name[p]); |
---|
635 | bonobo_event_source_notify_listeners (priv->property_bag->es, |
---|
636 | property_name[p], |
---|
637 | arg, NULL); |
---|
638 | priv->need_update_prop[p] = FALSE; |
---|
639 | } |
---|
640 | } |
---|
641 | |
---|
642 | bonobo_arg_release (arg); |
---|
643 | priv->idle_id = -1; |
---|
644 | |
---|
645 | return FALSE; |
---|
646 | } |
---|
647 | |
---|
648 | static void |
---|
649 | update_status_text (EogCollectionView *view) |
---|
650 | { |
---|
651 | view->priv->need_update_prop [PROP_WINDOW_STATUS] = TRUE; |
---|
652 | if (view->priv->idle_id == -1) { |
---|
653 | view->priv->idle_id = gtk_idle_add ((GtkFunction) update_properties, view); |
---|
654 | } |
---|
655 | } |
---|
656 | |
---|
657 | static void |
---|
658 | update_title_text (EogCollectionView *view) |
---|
659 | { |
---|
660 | view->priv->need_update_prop [PROP_WINDOW_TITLE] = TRUE; |
---|
661 | if (view->priv->idle_id == -1) { |
---|
662 | view->priv->idle_id = gtk_idle_add ((GtkFunction) update_properties, view); |
---|
663 | } |
---|
664 | } |
---|
665 | |
---|
666 | static void |
---|
667 | model_size_changed (EogCollectionModel *model, GList *id_list, gpointer data) |
---|
668 | { |
---|
669 | EogCollectionView *view; |
---|
670 | |
---|
671 | g_return_if_fail (data != NULL); |
---|
672 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (data)); |
---|
673 | |
---|
674 | view = EOG_COLLECTION_VIEW (data); |
---|
675 | update_status_text (view); |
---|
676 | } |
---|
677 | |
---|
678 | static void |
---|
679 | model_selection_changed (EogCollectionModel *model, GQuark id, gpointer data) |
---|
680 | { |
---|
681 | EogCollectionView *view; |
---|
682 | |
---|
683 | g_return_if_fail (data != NULL); |
---|
684 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (data)); |
---|
685 | |
---|
686 | view = EOG_COLLECTION_VIEW (data); |
---|
687 | update_status_text (view); |
---|
688 | } |
---|
689 | |
---|
690 | static void |
---|
691 | model_base_uri_changed (EogCollectionModel *model, gpointer data) |
---|
692 | { |
---|
693 | EogCollectionView *view; |
---|
694 | |
---|
695 | g_return_if_fail (data != NULL); |
---|
696 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (data)); |
---|
697 | |
---|
698 | view = EOG_COLLECTION_VIEW (data); |
---|
699 | g_print ("model_base_uri_changed ...\n"); |
---|
700 | update_title_text (view); |
---|
701 | } |
---|
702 | |
---|
703 | static void |
---|
704 | layout_changed_cb (GConfClient *client, guint cnxn_id, |
---|
705 | GConfEntry *entry, gpointer user_data) |
---|
706 | { |
---|
707 | EogCollectionView *view; |
---|
708 | gint layout; |
---|
709 | |
---|
710 | g_return_if_fail (user_data != NULL); |
---|
711 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (user_data)); |
---|
712 | |
---|
713 | view = EOG_COLLECTION_VIEW (user_data); |
---|
714 | |
---|
715 | layout = gconf_value_get_int (entry->value); |
---|
716 | eog_wrap_list_set_layout_mode (EOG_WRAP_LIST (view->priv->wraplist), |
---|
717 | layout); |
---|
718 | } |
---|
719 | |
---|
720 | static void |
---|
721 | color_changed_cb (GConfClient *client, guint cnxn_id, |
---|
722 | GConfEntry *entry, gpointer user_data) |
---|
723 | { |
---|
724 | EogCollectionView *view; |
---|
725 | GdkColor color; |
---|
726 | GSList *l = NULL; |
---|
727 | |
---|
728 | g_return_if_fail (user_data != NULL); |
---|
729 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (user_data)); |
---|
730 | g_return_if_fail (entry->value->type == GCONF_VALUE_LIST); |
---|
731 | |
---|
732 | view = EOG_COLLECTION_VIEW (user_data); |
---|
733 | |
---|
734 | g_assert (gconf_value_get_list_type (entry->value) == GCONF_VALUE_INT); |
---|
735 | |
---|
736 | l = gconf_client_get_list (client, pref_key[PREF_COLOR], |
---|
737 | GCONF_VALUE_INT, NULL); |
---|
738 | |
---|
739 | color.red = GPOINTER_TO_UINT (l->data); |
---|
740 | color.green = GPOINTER_TO_UINT (l->next->data); |
---|
741 | color.blue = GPOINTER_TO_UINT (l->next->next->data); |
---|
742 | |
---|
743 | eog_wrap_list_set_background_color (EOG_WRAP_LIST (view->priv->wraplist), |
---|
744 | &color); |
---|
745 | } |
---|
746 | |
---|
747 | /* read configuration */ |
---|
748 | static void |
---|
749 | set_configuration_values (EogCollectionView *view) |
---|
750 | { |
---|
751 | EogCollectionViewPrivate *priv = NULL; |
---|
752 | gint layout; |
---|
753 | GSList *l; |
---|
754 | GdkColor color; |
---|
755 | |
---|
756 | g_return_if_fail (view != NULL); |
---|
757 | g_return_if_fail (EOG_IS_COLLECTION_VIEW (view)); |
---|
758 | |
---|
759 | priv = view->priv; |
---|
760 | |
---|
761 | /* set layout mode */ |
---|
762 | layout = gconf_client_get_int (priv->client, |
---|
763 | pref_key[PREF_LAYOUT], |
---|
764 | NULL); |
---|
765 | eog_wrap_list_set_layout_mode (EOG_WRAP_LIST (priv->wraplist), |
---|
766 | layout); |
---|
767 | |
---|
768 | /* set background color */ |
---|
769 | l = gconf_client_get_list (priv->client, pref_key[PREF_COLOR], |
---|
770 | GCONF_VALUE_INT, NULL); |
---|
771 | if (l) { |
---|
772 | color.red = GPOINTER_TO_UINT (l->data); |
---|
773 | color.green = GPOINTER_TO_UINT (l->next->data); |
---|
774 | color.blue = GPOINTER_TO_UINT (l->next->next->data); |
---|
775 | } else { |
---|
776 | color.red = 57015; /* default gtk color */ |
---|
777 | color.green = 57015; |
---|
778 | color.blue = 57015; |
---|
779 | } |
---|
780 | eog_wrap_list_set_background_color (EOG_WRAP_LIST (priv->wraplist), |
---|
781 | &color); |
---|
782 | /* add configuration listeners */ |
---|
783 | priv->notify_id[PREF_LAYOUT] = |
---|
784 | gconf_client_notify_add (priv->client, |
---|
785 | pref_key[PREF_LAYOUT], |
---|
786 | layout_changed_cb, |
---|
787 | view, |
---|
788 | NULL, NULL); |
---|
789 | priv->notify_id[PREF_COLOR] = |
---|
790 | gconf_client_notify_add (priv->client, |
---|
791 | pref_key[PREF_COLOR], |
---|
792 | color_changed_cb, |
---|
793 | view, |
---|
794 | NULL, NULL); |
---|
795 | } |
---|
796 | |
---|
797 | static gint |
---|
798 | load_uri_cb (BonoboPersistFile *pf, const CORBA_char *text_uri, |
---|
799 | CORBA_Environment *ev, void *closure) |
---|
800 | { |
---|
801 | EogCollectionViewPrivate *priv; |
---|
802 | |
---|
803 | priv = EOG_COLLECTION_VIEW (closure)->priv; |
---|
804 | |
---|
805 | if (text_uri == CORBA_OBJECT_NIL) return FALSE; |
---|
806 | |
---|
807 | eog_collection_model_set_uri (priv->model, (gchar*)text_uri); |
---|
808 | |
---|
809 | return TRUE; |
---|
810 | } |
---|
811 | |
---|
812 | |
---|
813 | EogCollectionView * |
---|
814 | eog_collection_view_construct (EogCollectionView *list_view) |
---|
815 | { |
---|
816 | EogCollectionViewPrivate *priv = NULL; |
---|
817 | EogItemFactory *factory; |
---|
818 | EogImageLoader *loader; |
---|
819 | BonoboPersistFile *persist_file; |
---|
820 | |
---|
821 | g_return_val_if_fail (list_view != NULL, NULL); |
---|
822 | g_return_val_if_fail (EOG_IS_COLLECTION_VIEW (list_view), NULL); |
---|
823 | |
---|
824 | priv = list_view->priv; |
---|
825 | |
---|
826 | priv->uic = bonobo_ui_component_new ("EogCollectionView"); |
---|
827 | |
---|
828 | /* Make sure GConf is initialized */ |
---|
829 | if (!gconf_is_initialized ()) |
---|
830 | gconf_init (0, NULL, NULL); |
---|
831 | |
---|
832 | priv->client = gconf_client_get_default (); |
---|
833 | gconf_client_add_dir (priv->client, PREF_PREFIX, |
---|
834 | GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); |
---|
835 | |
---|
836 | /* construct widget */ |
---|
837 | g_assert (EOG_IS_COLLECTION_VIEW (list_view)); |
---|
838 | priv->model = eog_collection_model_new (); |
---|
839 | g_signal_connect (G_OBJECT (priv->model), "image-added", |
---|
840 | G_CALLBACK (model_size_changed), |
---|
841 | list_view); |
---|
842 | g_signal_connect (G_OBJECT (priv->model), "image-removed", |
---|
843 | G_CALLBACK (model_size_changed), |
---|
844 | list_view); |
---|
845 | g_signal_connect (G_OBJECT (priv->model), "selection-changed", |
---|
846 | G_CALLBACK (model_selection_changed), |
---|
847 | list_view); |
---|
848 | g_signal_connect (G_OBJECT (priv->model), "base-uri-changed", |
---|
849 | G_CALLBACK (model_base_uri_changed), |
---|
850 | list_view); |
---|
851 | |
---|
852 | #if HAVE_LIBPREVIEW |
---|
853 | loader = eog_image_loader_preview_new (96, 96); |
---|
854 | #else |
---|
855 | loader = eog_image_loader_simple_new (96, 96); |
---|
856 | #endif |
---|
857 | factory = EOG_ITEM_FACTORY (eog_item_factory_clean_new (loader)); |
---|
858 | |
---|
859 | priv->root = gtk_scrolled_window_new (NULL, NULL); |
---|
860 | |
---|
861 | priv->wraplist = eog_wrap_list_new (); |
---|
862 | gtk_container_add (GTK_CONTAINER (priv->root), priv->wraplist); |
---|
863 | eog_wrap_list_set_model (EOG_WRAP_LIST (priv->wraplist), priv->model); |
---|
864 | eog_wrap_list_set_factory (EOG_WRAP_LIST (priv->wraplist), factory); |
---|
865 | eog_wrap_list_set_col_spacing (EOG_WRAP_LIST (priv->wraplist), 20); |
---|
866 | eog_wrap_list_set_row_spacing (EOG_WRAP_LIST (priv->wraplist), 20); |
---|
867 | g_signal_connect (G_OBJECT (priv->wraplist), "double_click", |
---|
868 | G_CALLBACK (handle_double_click), list_view); |
---|
869 | g_signal_connect (G_OBJECT (priv->wraplist), "right_click", |
---|
870 | G_CALLBACK (handle_right_click), list_view); |
---|
871 | |
---|
872 | gtk_widget_show (priv->wraplist); |
---|
873 | gtk_widget_show (priv->root); |
---|
874 | |
---|
875 | g_object_unref (G_OBJECT (factory)); |
---|
876 | g_object_unref (G_OBJECT (loader)); |
---|
877 | |
---|
878 | /* add persist file interface */ |
---|
879 | persist_file = bonobo_persist_file_new (load_uri_cb, NULL, |
---|
880 | "OAFIID:GNOME_EOG_CollectionControl", |
---|
881 | list_view); |
---|
882 | bonobo_object_add_interface (BONOBO_OBJECT (list_view), |
---|
883 | BONOBO_OBJECT (persist_file)); |
---|
884 | |
---|
885 | |
---|
886 | /* Property Bag */ |
---|
887 | priv->property_bag = bonobo_property_bag_new (eog_collection_view_get_prop, |
---|
888 | eog_collection_view_set_prop, |
---|
889 | list_view); |
---|
890 | bonobo_property_bag_add (priv->property_bag, property_name[0], PROP_WINDOW_TITLE, |
---|
891 | BONOBO_ARG_STRING, NULL, _("Window Title"), |
---|
892 | BONOBO_PROPERTY_READABLE); |
---|
893 | bonobo_property_bag_add (priv->property_bag, property_name[1], PROP_WINDOW_STATUS, |
---|
894 | BONOBO_ARG_STRING, NULL, _("Status Text"), |
---|
895 | BONOBO_PROPERTY_READABLE); |
---|
896 | |
---|
897 | /* read user defined configuration */ |
---|
898 | set_configuration_values (list_view); |
---|
899 | |
---|
900 | return list_view; |
---|
901 | } |
---|
902 | |
---|
903 | EogCollectionView * |
---|
904 | eog_collection_view_new (void) |
---|
905 | { |
---|
906 | EogCollectionView *list_view; |
---|
907 | |
---|
908 | list_view = |
---|
909 | EOG_COLLECTION_VIEW (g_object_new (EOG_TYPE_COLLECTION_VIEW, NULL)); |
---|
910 | |
---|
911 | return eog_collection_view_construct (list_view); |
---|
912 | } |
---|
913 | |
---|
914 | BonoboPropertyBag* |
---|
915 | eog_collection_view_get_property_bag (EogCollectionView *view) |
---|
916 | { |
---|
917 | g_return_val_if_fail (view != NULL, NULL); |
---|
918 | g_return_val_if_fail (EOG_IS_COLLECTION_VIEW (view), NULL); |
---|
919 | |
---|
920 | bonobo_object_ref (BONOBO_OBJECT (view->priv->property_bag)); |
---|
921 | |
---|
922 | return view->priv->property_bag; |
---|
923 | } |
---|