1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpsettingsbox.c
5 * Copyright (C) 2008-2017 Michael Natterer <mitch@gimp.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 3 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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "libgimpconfig/gimpconfig.h"
27 #include "libgimpwidgets/gimpwidgets.h"
28
29 #include "widgets-types.h"
30
31 #include "operations/gimp-operation-config.h"
32
33 #include "core/gimp.h"
34 #include "core/gimplist.h"
35 #include "core/gimpmarshal.h"
36
37 #include "gimpcontainercombobox.h"
38 #include "gimpcontainertreestore.h"
39 #include "gimpcontainerview.h"
40 #include "gimpsettingsbox.h"
41 #include "gimpsettingseditor.h"
42 #include "gimpwidgets-utils.h"
43
44 #include "gimp-intl.h"
45
46
47 enum
48 {
49 FILE_DIALOG_SETUP,
50 IMPORT,
51 EXPORT,
52 SELECTED,
53 LAST_SIGNAL
54 };
55
56 enum
57 {
58 PROP_0,
59 PROP_GIMP,
60 PROP_CONFIG,
61 PROP_CONTAINER,
62 PROP_HELP_ID,
63 PROP_IMPORT_TITLE,
64 PROP_EXPORT_TITLE,
65 PROP_DEFAULT_FOLDER,
66 PROP_LAST_FILE
67 };
68
69
70 typedef struct _GimpSettingsBoxPrivate GimpSettingsBoxPrivate;
71
72 struct _GimpSettingsBoxPrivate
73 {
74 GtkWidget *combo;
75 GtkWidget *menu;
76 GtkWidget *import_item;
77 GtkWidget *export_item;
78 GtkWidget *file_dialog;
79 GtkWidget *editor_dialog;
80
81 Gimp *gimp;
82 GObject *config;
83 GimpContainer *container;
84
85 gchar *help_id;
86 gchar *import_title;
87 gchar *export_title;
88 GFile *default_folder;
89 GFile *last_file;
90 };
91
92 #define GET_PRIVATE(item) ((GimpSettingsBoxPrivate *) gimp_settings_box_get_instance_private ((GimpSettingsBox *) (item)))
93
94
95 static void gimp_settings_box_constructed (GObject *object);
96 static void gimp_settings_box_finalize (GObject *object);
97 static void gimp_settings_box_set_property (GObject *object,
98 guint property_id,
99 const GValue *value,
100 GParamSpec *pspec);
101 static void gimp_settings_box_get_property (GObject *object,
102 guint property_id,
103 GValue *value,
104 GParamSpec *pspec);
105
106 static GtkWidget *
107 gimp_settings_box_menu_item_add (GimpSettingsBox *box,
108 const gchar *icon_name,
109 const gchar *label,
110 GCallback callback);
111 static gboolean
112 gimp_settings_box_row_separator_func (GtkTreeModel *model,
113 GtkTreeIter *iter,
114 gpointer data);
115 static void gimp_settings_box_setting_selected (GimpContainerView *view,
116 GimpViewable *object,
117 gpointer insert_data,
118 GimpSettingsBox *box);
119 static gboolean gimp_settings_box_menu_press (GtkWidget *widget,
120 GdkEventButton *bevent,
121 GimpSettingsBox *box);
122 static void gimp_settings_box_favorite_activate (GtkWidget *widget,
123 GimpSettingsBox *box);
124 static void gimp_settings_box_import_activate (GtkWidget *widget,
125 GimpSettingsBox *box);
126 static void gimp_settings_box_export_activate (GtkWidget *widget,
127 GimpSettingsBox *box);
128 static void gimp_settings_box_manage_activate (GtkWidget *widget,
129 GimpSettingsBox *box);
130
131 static void gimp_settings_box_favorite_callback (GtkWidget *query_box,
132 const gchar *string,
133 gpointer data);
134 static void gimp_settings_box_file_dialog (GimpSettingsBox *box,
135 const gchar *title,
136 gboolean save);
137 static void gimp_settings_box_file_response (GtkWidget *dialog,
138 gint response_id,
139 GimpSettingsBox *box);
140 static void gimp_settings_box_toplevel_unmap (GtkWidget *toplevel,
141 GtkWidget *dialog);
142 static void gimp_settings_box_truncate_list (GimpSettingsBox *box,
143 gint max_recent);
144
145
146 G_DEFINE_TYPE_WITH_PRIVATE (GimpSettingsBox, gimp_settings_box, GTK_TYPE_BOX)
147
148 #define parent_class gimp_settings_box_parent_class
149
150 static guint settings_box_signals[LAST_SIGNAL] = { 0 };
151
152
153 static void
gimp_settings_box_class_init(GimpSettingsBoxClass * klass)154 gimp_settings_box_class_init (GimpSettingsBoxClass *klass)
155 {
156 GObjectClass *object_class = G_OBJECT_CLASS (klass);
157
158 settings_box_signals[FILE_DIALOG_SETUP] =
159 g_signal_new ("file-dialog-setup",
160 G_TYPE_FROM_CLASS (klass),
161 G_SIGNAL_RUN_LAST,
162 G_STRUCT_OFFSET (GimpSettingsBoxClass, file_dialog_setup),
163 NULL, NULL,
164 gimp_marshal_VOID__OBJECT_BOOLEAN,
165 G_TYPE_NONE, 2,
166 GTK_TYPE_FILE_CHOOSER_DIALOG,
167 G_TYPE_BOOLEAN);
168
169 settings_box_signals[IMPORT] =
170 g_signal_new ("import",
171 G_TYPE_FROM_CLASS (klass),
172 G_SIGNAL_RUN_LAST,
173 G_STRUCT_OFFSET (GimpSettingsBoxClass, import),
174 NULL, NULL,
175 gimp_marshal_BOOLEAN__OBJECT,
176 G_TYPE_BOOLEAN, 1,
177 G_TYPE_FILE);
178
179 settings_box_signals[EXPORT] =
180 g_signal_new ("export",
181 G_TYPE_FROM_CLASS (klass),
182 G_SIGNAL_RUN_LAST,
183 G_STRUCT_OFFSET (GimpSettingsBoxClass, export),
184 NULL, NULL,
185 gimp_marshal_BOOLEAN__OBJECT,
186 G_TYPE_BOOLEAN, 1,
187 G_TYPE_FILE);
188
189 settings_box_signals[SELECTED] =
190 g_signal_new ("selected",
191 G_TYPE_FROM_CLASS (klass),
192 G_SIGNAL_RUN_LAST,
193 G_STRUCT_OFFSET (GimpSettingsBoxClass, selected),
194 NULL, NULL,
195 gimp_marshal_VOID__OBJECT,
196 G_TYPE_NONE, 1,
197 GIMP_TYPE_CONFIG);
198
199 object_class->constructed = gimp_settings_box_constructed;
200 object_class->finalize = gimp_settings_box_finalize;
201 object_class->set_property = gimp_settings_box_set_property;
202 object_class->get_property = gimp_settings_box_get_property;
203
204 klass->file_dialog_setup = NULL;
205 klass->import = NULL;
206 klass->export = NULL;
207 klass->selected = NULL;
208
209 g_object_class_install_property (object_class, PROP_GIMP,
210 g_param_spec_object ("gimp",
211 NULL, NULL,
212 GIMP_TYPE_GIMP,
213 GIMP_PARAM_READWRITE |
214 G_PARAM_CONSTRUCT_ONLY));
215
216 g_object_class_install_property (object_class, PROP_CONFIG,
217 g_param_spec_object ("config",
218 NULL, NULL,
219 GIMP_TYPE_CONFIG,
220 GIMP_PARAM_READWRITE |
221 G_PARAM_CONSTRUCT));
222
223 g_object_class_install_property (object_class, PROP_CONTAINER,
224 g_param_spec_object ("container",
225 NULL, NULL,
226 GIMP_TYPE_CONTAINER,
227 GIMP_PARAM_READWRITE |
228 G_PARAM_CONSTRUCT));
229
230 g_object_class_install_property (object_class, PROP_HELP_ID,
231 g_param_spec_string ("help-id",
232 NULL, NULL,
233 NULL,
234 GIMP_PARAM_READWRITE |
235 G_PARAM_CONSTRUCT));
236
237 g_object_class_install_property (object_class, PROP_IMPORT_TITLE,
238 g_param_spec_string ("import-title",
239 NULL, NULL,
240 NULL,
241 GIMP_PARAM_READWRITE |
242 G_PARAM_CONSTRUCT));
243
244 g_object_class_install_property (object_class, PROP_EXPORT_TITLE,
245 g_param_spec_string ("export-title",
246 NULL, NULL,
247 NULL,
248 GIMP_PARAM_READWRITE |
249 G_PARAM_CONSTRUCT));
250
251 g_object_class_install_property (object_class, PROP_DEFAULT_FOLDER,
252 g_param_spec_object ("default-folder",
253 NULL, NULL,
254 G_TYPE_FILE,
255 GIMP_PARAM_READWRITE |
256 G_PARAM_CONSTRUCT));
257
258 g_object_class_install_property (object_class, PROP_LAST_FILE,
259 g_param_spec_object ("last-file",
260 NULL, NULL,
261 G_TYPE_FILE,
262 GIMP_PARAM_READWRITE |
263 G_PARAM_CONSTRUCT));
264 }
265
266 static void
gimp_settings_box_init(GimpSettingsBox * box)267 gimp_settings_box_init (GimpSettingsBox *box)
268 {
269 gtk_orientable_set_orientation (GTK_ORIENTABLE (box),
270 GTK_ORIENTATION_HORIZONTAL);
271
272 gtk_box_set_spacing (GTK_BOX (box), 6);
273 }
274
275 static void
gimp_settings_box_constructed(GObject * object)276 gimp_settings_box_constructed (GObject *object)
277 {
278 GimpSettingsBox *box = GIMP_SETTINGS_BOX (object);
279 GimpSettingsBoxPrivate *private = GET_PRIVATE (object);
280 GtkWidget *hbox2;
281 GtkWidget *button;
282 GtkWidget *image;
283 GtkWidget *arrow;
284
285 G_OBJECT_CLASS (parent_class)->constructed (object);
286
287 gimp_assert (GIMP_IS_GIMP (private->gimp));
288 gimp_assert (GIMP_IS_CONFIG (private->config));
289 gimp_assert (GIMP_IS_CONTAINER (private->container));
290
291 private->combo = gimp_container_combo_box_new (private->container,
292 gimp_get_user_context (private->gimp),
293 16, 0);
294 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (private->combo),
295 gimp_settings_box_row_separator_func,
296 NULL, NULL);
297 gtk_box_pack_start (GTK_BOX (box), private->combo, TRUE, TRUE, 0);
298 gtk_widget_show (private->combo);
299
300 gimp_help_set_help_data (private->combo, _("Pick a preset from the list"),
301 NULL);
302
303 g_signal_connect_after (private->combo, "select-item",
304 G_CALLBACK (gimp_settings_box_setting_selected),
305 box);
306
307 hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
308 gtk_box_set_homogeneous (GTK_BOX (hbox2), TRUE);
309 gtk_box_pack_start (GTK_BOX (box), hbox2, FALSE, FALSE, 0);
310 gtk_widget_show (hbox2);
311
312 button = gtk_button_new ();
313 gtk_widget_set_can_focus (button, FALSE);
314 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
315 gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
316 gtk_widget_show (button);
317
318 image = gtk_image_new_from_icon_name (GIMP_ICON_LIST_ADD,
319 GTK_ICON_SIZE_MENU);
320 gtk_container_add (GTK_CONTAINER (button), image);
321 gtk_widget_show (image);
322
323 gimp_help_set_help_data (button,
324 _("Save the current settings as named preset"),
325 NULL);
326
327 g_signal_connect (button, "clicked",
328 G_CALLBACK (gimp_settings_box_favorite_activate),
329 box);
330
331 button = gtk_button_new ();
332 gtk_widget_set_can_focus (button, FALSE);
333 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
334 gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
335 gtk_widget_show (button);
336
337 arrow = gtk_image_new_from_icon_name (GIMP_ICON_MENU_LEFT,
338 GTK_ICON_SIZE_MENU);
339 gtk_container_add (GTK_CONTAINER (button), arrow);
340 gtk_widget_show (arrow);
341
342 gimp_help_set_help_data (button, _("Manage presets"), NULL);
343
344 g_signal_connect (button, "button-press-event",
345 G_CALLBACK (gimp_settings_box_menu_press),
346 box);
347
348 /* Favorites menu */
349
350 private->menu = gtk_menu_new ();
351 gtk_menu_attach_to_widget (GTK_MENU (private->menu), button, NULL);
352
353 private->import_item =
354 gimp_settings_box_menu_item_add (box,
355 GIMP_ICON_DOCUMENT_OPEN,
356 _("_Import Current Settings from File..."),
357 G_CALLBACK (gimp_settings_box_import_activate));
358
359 private->export_item =
360 gimp_settings_box_menu_item_add (box,
361 GIMP_ICON_DOCUMENT_SAVE,
362 _("_Export Current Settings to File..."),
363 G_CALLBACK (gimp_settings_box_export_activate));
364
365 gimp_settings_box_menu_item_add (box, NULL, NULL, NULL);
366
367 gimp_settings_box_menu_item_add (box,
368 GIMP_ICON_EDIT,
369 _("_Manage Saved Presets..."),
370 G_CALLBACK (gimp_settings_box_manage_activate));
371 }
372
373 static void
gimp_settings_box_finalize(GObject * object)374 gimp_settings_box_finalize (GObject *object)
375 {
376 GimpSettingsBoxPrivate *private = GET_PRIVATE (object);
377
378 g_clear_object (&private->config);
379 g_clear_object (&private->container);
380 g_clear_object (&private->last_file);
381 g_clear_object (&private->default_folder);
382
383 g_free (private->help_id);
384 g_free (private->import_title);
385 g_free (private->export_title);
386
387 if (private->editor_dialog)
388 gtk_widget_destroy (private->editor_dialog);
389
390 if (private->file_dialog)
391 gtk_widget_destroy (private->file_dialog);
392
393 G_OBJECT_CLASS (parent_class)->finalize (object);
394 }
395
396 static void
gimp_settings_box_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)397 gimp_settings_box_set_property (GObject *object,
398 guint property_id,
399 const GValue *value,
400 GParamSpec *pspec)
401 {
402 GimpSettingsBoxPrivate *private = GET_PRIVATE (object);
403
404 switch (property_id)
405 {
406 case PROP_GIMP:
407 private->gimp = g_value_get_object (value); /* don't dup */
408 break;
409
410 case PROP_CONFIG:
411 if (private->config)
412 g_object_unref (private->config);
413 private->config = g_value_dup_object (value);
414 break;
415
416 case PROP_CONTAINER:
417 if (private->editor_dialog)
418 gtk_dialog_response (GTK_DIALOG (private->editor_dialog),
419 GTK_RESPONSE_DELETE_EVENT);
420 if (private->file_dialog)
421 gtk_dialog_response (GTK_DIALOG (private->file_dialog),
422 GTK_RESPONSE_DELETE_EVENT);
423 if (private->container)
424 g_object_unref (private->container);
425 private->container = g_value_dup_object (value);
426 if (private->combo)
427 gimp_container_view_set_container (GIMP_CONTAINER_VIEW (private->combo),
428 private->container);
429 break;
430
431 case PROP_HELP_ID:
432 g_free (private->help_id);
433 private->help_id = g_value_dup_string (value);
434 break;
435
436 case PROP_IMPORT_TITLE:
437 g_free (private->import_title);
438 private->import_title = g_value_dup_string (value);
439 break;
440
441 case PROP_EXPORT_TITLE:
442 g_free (private->export_title);
443 private->export_title = g_value_dup_string (value);
444 break;
445
446 case PROP_DEFAULT_FOLDER:
447 if (private->default_folder)
448 g_object_unref (private->default_folder);
449 private->default_folder = g_value_dup_object (value);
450 break;
451
452 case PROP_LAST_FILE:
453 if (private->last_file)
454 g_object_unref (private->last_file);
455 private->last_file = g_value_dup_object (value);
456 break;
457
458 default:
459 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
460 break;
461 }
462 }
463
464 static void
gimp_settings_box_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)465 gimp_settings_box_get_property (GObject *object,
466 guint property_id,
467 GValue *value,
468 GParamSpec *pspec)
469 {
470 GimpSettingsBoxPrivate *private = GET_PRIVATE (object);
471
472 switch (property_id)
473 {
474 case PROP_GIMP:
475 g_value_set_object (value, private->gimp);
476 break;
477
478 case PROP_CONFIG:
479 g_value_set_object (value, private->config);
480 break;
481
482 case PROP_CONTAINER:
483 g_value_set_object (value, private->container);
484 break;
485
486 case PROP_HELP_ID:
487 g_value_set_string (value, private->help_id);
488 break;
489
490 case PROP_IMPORT_TITLE:
491 g_value_set_string (value, private->import_title);
492 break;
493
494 case PROP_EXPORT_TITLE:
495 g_value_set_string (value, private->export_title);
496 break;
497
498 case PROP_DEFAULT_FOLDER:
499 g_value_set_object (value, private->default_folder);
500 break;
501
502 case PROP_LAST_FILE:
503 g_value_set_object (value, private->last_file);
504 break;
505
506 default:
507 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
508 break;
509 }
510 }
511
512 static GtkWidget *
gimp_settings_box_menu_item_add(GimpSettingsBox * box,const gchar * icon_name,const gchar * label,GCallback callback)513 gimp_settings_box_menu_item_add (GimpSettingsBox *box,
514 const gchar *icon_name,
515 const gchar *label,
516 GCallback callback)
517 {
518 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
519 GtkWidget *item;
520
521 if (label)
522 {
523 GtkWidget *image;
524
525 item = gtk_image_menu_item_new_with_mnemonic (label);
526 image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
527 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
528
529 g_signal_connect (item, "activate",
530 callback,
531 box);
532 }
533 else
534 {
535 item = gtk_separator_menu_item_new ();
536 }
537
538 gtk_menu_shell_append (GTK_MENU_SHELL (private->menu), item);
539 gtk_widget_show (item);
540
541 return item;
542 }
543
544 static gboolean
gimp_settings_box_row_separator_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)545 gimp_settings_box_row_separator_func (GtkTreeModel *model,
546 GtkTreeIter *iter,
547 gpointer data)
548 {
549 gchar *name = NULL;
550
551 gtk_tree_model_get (model, iter,
552 GIMP_CONTAINER_TREE_STORE_COLUMN_NAME, &name,
553 -1);
554 g_free (name);
555
556 return name == NULL;
557 }
558
559 static void
gimp_settings_box_setting_selected(GimpContainerView * view,GimpViewable * object,gpointer insert_data,GimpSettingsBox * box)560 gimp_settings_box_setting_selected (GimpContainerView *view,
561 GimpViewable *object,
562 gpointer insert_data,
563 GimpSettingsBox *box)
564 {
565 if (object)
566 g_signal_emit (box, settings_box_signals[SELECTED], 0,
567 object);
568 }
569
570 static void
gimp_settings_box_menu_position(GtkMenu * menu,gint * x,gint * y,gboolean * push_in,gpointer user_data)571 gimp_settings_box_menu_position (GtkMenu *menu,
572 gint *x,
573 gint *y,
574 gboolean *push_in,
575 gpointer user_data)
576 {
577 gimp_button_menu_position (user_data, menu, GTK_POS_LEFT, x, y);
578 }
579
580 static gboolean
gimp_settings_box_menu_press(GtkWidget * widget,GdkEventButton * bevent,GimpSettingsBox * box)581 gimp_settings_box_menu_press (GtkWidget *widget,
582 GdkEventButton *bevent,
583 GimpSettingsBox *box)
584 {
585 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
586
587 if (bevent->type == GDK_BUTTON_PRESS)
588 {
589 gtk_menu_popup (GTK_MENU (private->menu),
590 NULL, NULL,
591 gimp_settings_box_menu_position, widget,
592 bevent->button, bevent->time);
593 }
594
595 return TRUE;
596 }
597
598 static void
gimp_settings_box_favorite_activate(GtkWidget * widget,GimpSettingsBox * box)599 gimp_settings_box_favorite_activate (GtkWidget *widget,
600 GimpSettingsBox *box)
601 {
602 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
603 GtkWidget *dialog;
604
605 dialog = gimp_query_string_box (_("Save Settings as Named Preset"),
606 toplevel,
607 gimp_standard_help_func, NULL,
608 _("Enter a name for the preset"),
609 _("Saved Settings"),
610 G_OBJECT (toplevel), "hide",
611 gimp_settings_box_favorite_callback, box);
612 gtk_widget_show (dialog);
613 }
614
615 static void
gimp_settings_box_import_activate(GtkWidget * widget,GimpSettingsBox * box)616 gimp_settings_box_import_activate (GtkWidget *widget,
617 GimpSettingsBox *box)
618 {
619 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
620
621 gimp_settings_box_file_dialog (box, private->import_title, FALSE);
622 }
623
624 static void
gimp_settings_box_export_activate(GtkWidget * widget,GimpSettingsBox * box)625 gimp_settings_box_export_activate (GtkWidget *widget,
626 GimpSettingsBox *box)
627 {
628 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
629
630 gimp_settings_box_file_dialog (box, private->export_title, TRUE);
631 }
632
633 static void
gimp_settings_box_manage_activate(GtkWidget * widget,GimpSettingsBox * box)634 gimp_settings_box_manage_activate (GtkWidget *widget,
635 GimpSettingsBox *box)
636 {
637 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
638 GtkWidget *toplevel;
639 GtkWidget *editor;
640 GtkWidget *content_area;
641
642 if (private->editor_dialog)
643 {
644 gtk_window_present (GTK_WINDOW (private->editor_dialog));
645 return;
646 }
647
648 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));
649
650 private->editor_dialog = gimp_dialog_new (_("Manage Saved Presets"),
651 "gimp-settings-editor-dialog",
652 toplevel, 0,
653 NULL, NULL,
654
655 _("_Close"), GTK_RESPONSE_CLOSE,
656
657 NULL);
658
659 g_object_add_weak_pointer (G_OBJECT (private->editor_dialog),
660 (gpointer) &private->editor_dialog);
661 g_signal_connect_object (toplevel, "unmap",
662 G_CALLBACK (gimp_settings_box_toplevel_unmap),
663 private->editor_dialog, 0);
664
665 g_signal_connect (private->editor_dialog, "response",
666 G_CALLBACK (gtk_widget_destroy),
667 box);
668
669 editor = gimp_settings_editor_new (private->gimp,
670 private->config,
671 private->container);
672 gtk_container_set_border_width (GTK_CONTAINER (editor), 12);
673
674 content_area = gtk_dialog_get_content_area (GTK_DIALOG (private->editor_dialog));
675 gtk_box_pack_start (GTK_BOX (content_area), editor, TRUE, TRUE, 0);
676 gtk_widget_show (editor);
677
678 gtk_widget_show (private->editor_dialog);
679 }
680
681 static void
gimp_settings_box_favorite_callback(GtkWidget * query_box,const gchar * string,gpointer data)682 gimp_settings_box_favorite_callback (GtkWidget *query_box,
683 const gchar *string,
684 gpointer data)
685 {
686 GimpSettingsBox *box = GIMP_SETTINGS_BOX (data);
687 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
688 GimpConfig *config;
689
690 config = gimp_config_duplicate (GIMP_CONFIG (private->config));
691 gimp_object_set_name (GIMP_OBJECT (config), string);
692 gimp_container_add (private->container, GIMP_OBJECT (config));
693 g_object_unref (config);
694
695 gimp_operation_config_serialize (private->gimp, private->container, NULL);
696 }
697
698 static void
gimp_settings_box_file_dialog(GimpSettingsBox * box,const gchar * title,gboolean save)699 gimp_settings_box_file_dialog (GimpSettingsBox *box,
700 const gchar *title,
701 gboolean save)
702 {
703 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
704 GtkWidget *toplevel;
705 GtkWidget *dialog;
706
707 if (private->file_dialog)
708 {
709 gtk_window_present (GTK_WINDOW (private->file_dialog));
710 return;
711 }
712
713 if (save)
714 gtk_widget_set_sensitive (private->import_item, FALSE);
715 else
716 gtk_widget_set_sensitive (private->export_item, FALSE);
717
718 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));
719
720 private->file_dialog = dialog =
721 gtk_file_chooser_dialog_new (title, GTK_WINDOW (toplevel),
722 save ?
723 GTK_FILE_CHOOSER_ACTION_SAVE :
724 GTK_FILE_CHOOSER_ACTION_OPEN,
725
726 _("_Cancel"), GTK_RESPONSE_CANCEL,
727 save ?
728 _("_Save") : _("_Open"), GTK_RESPONSE_OK,
729
730 NULL);
731
732 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
733 gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
734 GTK_RESPONSE_OK,
735 GTK_RESPONSE_CANCEL,
736 -1);
737
738 g_object_set_data (G_OBJECT (dialog), "save", GINT_TO_POINTER (save));
739
740 gtk_window_set_role (GTK_WINDOW (dialog), "gimp-import-export-settings");
741 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
742 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
743
744 g_object_add_weak_pointer (G_OBJECT (dialog),
745 (gpointer) &private->file_dialog);
746 g_signal_connect_object (toplevel, "unmap",
747 G_CALLBACK (gimp_settings_box_toplevel_unmap),
748 dialog, 0);
749
750 if (save)
751 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
752 TRUE);
753
754 g_signal_connect (dialog, "response",
755 G_CALLBACK (gimp_settings_box_file_response),
756 box);
757 g_signal_connect (dialog, "delete-event",
758 G_CALLBACK (gtk_true),
759 NULL);
760
761 if (private->default_folder &&
762 g_file_query_file_type (private->default_folder,
763 G_FILE_QUERY_INFO_NONE, NULL) ==
764 G_FILE_TYPE_DIRECTORY)
765 {
766 gchar *uri = g_file_get_uri (private->default_folder);
767 gtk_file_chooser_add_shortcut_folder_uri (GTK_FILE_CHOOSER (dialog),
768 uri, NULL);
769 g_free (uri);
770
771 if (! private->last_file)
772 gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
773 private->default_folder,
774 NULL);
775 }
776 else if (! private->last_file)
777 {
778 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
779 g_get_home_dir ());
780 }
781
782 if (private->last_file)
783 gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog),
784 private->last_file, NULL);
785
786 gimp_help_connect (private->file_dialog, gimp_standard_help_func,
787 private->help_id, NULL);
788
789 /* allow callbacks to add widgets to the dialog */
790 g_signal_emit (box, settings_box_signals[FILE_DIALOG_SETUP], 0,
791 private->file_dialog, save);
792
793 gtk_widget_show (private->file_dialog);
794 }
795
796 static void
gimp_settings_box_file_response(GtkWidget * dialog,gint response_id,GimpSettingsBox * box)797 gimp_settings_box_file_response (GtkWidget *dialog,
798 gint response_id,
799 GimpSettingsBox *box)
800 {
801 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
802 gboolean save;
803
804 save = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "save"));
805
806 if (response_id == GTK_RESPONSE_OK)
807 {
808 GFile *file;
809 gboolean success = FALSE;
810
811 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
812
813 if (save)
814 g_signal_emit (box, settings_box_signals[EXPORT], 0, file,
815 &success);
816 else
817 g_signal_emit (box, settings_box_signals[IMPORT], 0, file,
818 &success);
819
820 if (success)
821 {
822 if (private->last_file)
823 g_object_unref (private->last_file);
824 private->last_file = file;
825
826 g_object_notify (G_OBJECT (box), "last-file");
827 }
828 else
829 {
830 g_object_unref (file);
831 }
832 }
833
834 if (save)
835 gtk_widget_set_sensitive (private->import_item, TRUE);
836 else
837 gtk_widget_set_sensitive (private->export_item, TRUE);
838
839 gtk_widget_destroy (dialog);
840 }
841
842 static void
gimp_settings_box_toplevel_unmap(GtkWidget * toplevel,GtkWidget * dialog)843 gimp_settings_box_toplevel_unmap (GtkWidget *toplevel,
844 GtkWidget *dialog)
845 {
846 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_DELETE_EVENT);
847 }
848
849 static void
gimp_settings_box_truncate_list(GimpSettingsBox * box,gint max_recent)850 gimp_settings_box_truncate_list (GimpSettingsBox *box,
851 gint max_recent)
852 {
853 GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
854 GList *list;
855 gint n_recent = 0;
856
857 list = GIMP_LIST (private->container)->queue->head;
858 while (list)
859 {
860 GimpConfig *config = list->data;
861 gint64 t;
862
863 list = g_list_next (list);
864
865 g_object_get (config,
866 "time", &t,
867 NULL);
868
869 if (t > 0)
870 {
871 n_recent++;
872
873 if (n_recent > max_recent)
874 gimp_container_remove (private->container, GIMP_OBJECT (config));
875 }
876 else
877 {
878 break;
879 }
880 }
881 }
882
883
884 /* public functions */
885
886 GtkWidget *
gimp_settings_box_new(Gimp * gimp,GObject * config,GimpContainer * container,const gchar * import_title,const gchar * export_title,const gchar * help_id,GFile * default_folder,GFile * last_file)887 gimp_settings_box_new (Gimp *gimp,
888 GObject *config,
889 GimpContainer *container,
890 const gchar *import_title,
891 const gchar *export_title,
892 const gchar *help_id,
893 GFile *default_folder,
894 GFile *last_file)
895 {
896 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
897 g_return_val_if_fail (GIMP_IS_CONFIG (config), NULL);
898 g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
899 g_return_val_if_fail (default_folder == NULL || G_IS_FILE (default_folder),
900 NULL);
901 g_return_val_if_fail (last_file == NULL || G_IS_FILE (last_file), NULL);
902
903 return g_object_new (GIMP_TYPE_SETTINGS_BOX,
904 "gimp", gimp,
905 "config", config,
906 "container", container,
907 "help-id", help_id,
908 "import-title", import_title,
909 "export-title", export_title,
910 "default-folder", default_folder,
911 "last-file", last_file,
912 NULL);
913 }
914
915 GtkWidget *
gimp_settings_box_get_combo(GimpSettingsBox * box)916 gimp_settings_box_get_combo (GimpSettingsBox *box)
917 {
918 g_return_val_if_fail (GIMP_IS_SETTINGS_BOX (box), NULL);
919
920 return GET_PRIVATE (box)->combo;
921 }
922
923 void
gimp_settings_box_add_current(GimpSettingsBox * box,gint max_recent)924 gimp_settings_box_add_current (GimpSettingsBox *box,
925 gint max_recent)
926 {
927 GimpSettingsBoxPrivate *private;
928 GimpConfig *config = NULL;
929 GList *list;
930
931 g_return_if_fail (GIMP_IS_SETTINGS_BOX (box));
932
933 private = GET_PRIVATE (box);
934
935 for (list = GIMP_LIST (private->container)->queue->head;
936 list;
937 list = g_list_next (list))
938 {
939 gint64 t;
940
941 config = list->data;
942
943 g_object_get (config,
944 "time", &t,
945 NULL);
946
947 if (t > 0 && gimp_config_is_equal_to (config,
948 GIMP_CONFIG (private->config)))
949 {
950 GDateTime *now = g_date_time_new_now_utc ();
951
952 g_object_set (config,
953 "time", g_date_time_to_unix (now),
954 NULL);
955 g_date_time_unref (now);
956
957 break;
958 }
959 }
960
961 if (! list)
962 {
963 GDateTime *now = g_date_time_new_now_utc ();
964
965 config = gimp_config_duplicate (GIMP_CONFIG (private->config));
966
967 g_object_set (config,
968 "time", g_date_time_to_unix (now),
969 NULL);
970 g_date_time_unref (now);
971
972 gimp_container_insert (private->container, GIMP_OBJECT (config), 0);
973 g_object_unref (config);
974 }
975
976 gimp_settings_box_truncate_list (box, max_recent);
977
978 gimp_operation_config_serialize (private->gimp, private->container, NULL);
979 }
980
981 void
gimp_settings_box_unset(GimpSettingsBox * box)982 gimp_settings_box_unset (GimpSettingsBox *box)
983 {
984 GimpSettingsBoxPrivate *private;
985
986 g_return_if_fail (GIMP_IS_SETTINGS_BOX (box));
987
988 private = GET_PRIVATE (box);
989
990 gimp_container_view_select_item (GIMP_CONTAINER_VIEW (private->combo), NULL);
991 }
992