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