1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * dialogs.c
5  * Copyright (C) 2010 Martin Nordholts <martinn@src.gnome.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 "libgimpbase/gimpbase.h"
27 #include "libgimpconfig/gimpconfig.h"
28 #include "libgimpwidgets/gimpwidgets.h"
29 
30 #include "dialogs-types.h"
31 
32 #include "config/gimpguiconfig.h"
33 
34 #include "display/gimpdisplay.h"
35 #include "display/gimpdisplayshell.h"
36 
37 #include "core/gimp.h"
38 #include "core/gimpcontext.h"
39 #include "core/gimplist.h"
40 
41 #include "widgets/gimpdialogfactory.h"
42 #include "widgets/gimpdockwindow.h"
43 #include "widgets/gimphelp-ids.h"
44 #include "widgets/gimpmenufactory.h"
45 #include "widgets/gimpsessioninfo.h"
46 #include "widgets/gimpsessioninfo-aux.h"
47 #include "widgets/gimpsessionmanaged.h"
48 #include "widgets/gimptoolbox.h"
49 
50 #include "dialogs.h"
51 #include "dialogs-constructors.h"
52 
53 #include "gimp-log.h"
54 
55 #include "gimp-intl.h"
56 
57 
58 GimpContainer *global_recent_docks = NULL;
59 
60 
61 #define FOREIGN(id, singleton, remember_size) \
62   { id                     /* identifier       */, \
63     NULL                   /* name             */, \
64     NULL                   /* blurb            */, \
65     NULL                   /* icon_name        */, \
66     NULL                   /* help_id          */, \
67     NULL                   /* new_func         */, \
68     dialogs_restore_dialog /* restore_func     */, \
69     0                      /* view_size        */, \
70     singleton              /* singleton        */, \
71     TRUE                   /* session_managed  */, \
72     remember_size          /* remember_size    */, \
73     FALSE                  /* remember_if_open */, \
74     TRUE                   /* hideable         */, \
75     FALSE                  /* image_window     */, \
76     FALSE                  /* dockable         */}
77 
78 #define IMAGE_WINDOW(id, singleton, remember_size) \
79   { id                     /* identifier       */, \
80     NULL                   /* name             */, \
81     NULL                   /* blurb            */, \
82     NULL                   /* icon_name        */, \
83     NULL                   /* help_id          */, \
84     NULL                   /* new_func         */, \
85     dialogs_restore_window /* restore_func     */, \
86     0                      /* view_size        */, \
87     singleton              /* singleton        */, \
88     TRUE                   /* session_managed  */, \
89     remember_size          /* remember_size    */, \
90     TRUE                   /* remember_if_open */, \
91     FALSE                  /* hideable         */, \
92     TRUE                   /* image_window     */, \
93     FALSE                  /* dockable         */}
94 
95 #define TOPLEVEL(id, new_func, singleton, session_managed, remember_size) \
96   { id                     /* identifier       */, \
97     NULL                   /* name             */, \
98     NULL                   /* blurb            */, \
99     NULL                   /* icon_name        */, \
100     NULL                   /* help_id          */, \
101     new_func               /* new_func         */, \
102     dialogs_restore_dialog /* restore_func     */, \
103     0                      /* view_size        */, \
104     singleton              /* singleton        */, \
105     session_managed        /* session_managed  */, \
106     remember_size          /* remember_size    */, \
107     FALSE                  /* remember_if_open */, \
108     TRUE                   /* hideable         */, \
109     FALSE                  /* image_window     */, \
110     FALSE                  /* dockable         */}
111 
112 #define DOCKABLE(id, name, blurb, icon_name, help_id, new_func, view_size, singleton) \
113   { id                     /* identifier       */, \
114     name                   /* name             */, \
115     blurb                  /* blurb            */, \
116     icon_name              /* icon_name        */, \
117     help_id                /* help_id          */, \
118     new_func               /* new_func         */, \
119     NULL                   /* restore_func     */, \
120     view_size              /* view_size        */, \
121     singleton              /* singleton        */, \
122     FALSE                  /* session_managed  */, \
123     FALSE                  /* remember_size    */, \
124     TRUE                   /* remember_if_open */, \
125     TRUE                   /* hideable         */, \
126     FALSE                  /* image_window     */, \
127     TRUE                   /* dockable         */}
128 
129 #define DOCK(id, new_func) \
130   { id                     /* identifier       */, \
131     NULL                   /* name             */, \
132     NULL                   /* blurb            */, \
133     NULL                   /* icon_name        */, \
134     NULL                   /* help_id          */, \
135     new_func               /* new_func         */, \
136     dialogs_restore_dialog /* restore_func     */, \
137     0                      /* view_size        */, \
138     FALSE                  /* singleton        */, \
139     FALSE                  /* session_managed  */, \
140     FALSE                  /* remember_size    */, \
141     FALSE                  /* remember_if_open */, \
142     TRUE                   /* hideable         */, \
143     FALSE                  /* image_window     */, \
144     FALSE                  /* dockable         */}
145 
146 #define DOCK_WINDOW(id, new_func) \
147   { id                     /* identifier       */, \
148     NULL                   /* name             */, \
149     NULL                   /* blurb            */, \
150     NULL                   /* icon_name        */, \
151     NULL                   /* help_id          */, \
152     new_func               /* new_func         */, \
153     dialogs_restore_dialog /* restore_func     */, \
154     0                      /* view_size        */, \
155     FALSE                  /* singleton        */, \
156     TRUE                   /* session_managed  */, \
157     TRUE                   /* remember_size    */, \
158     TRUE                   /* remember_if_open */, \
159     TRUE                   /* hideable         */, \
160     FALSE                  /* image_window     */, \
161     FALSE                  /* dockable         */}
162 
163 #define LISTGRID(id, new_func, name, blurb, icon_name, help_id, view_size) \
164   { "gimp-"#id"-list"             /* identifier       */,  \
165     name                          /* name             */,  \
166     blurb                         /* blurb            */,  \
167     icon_name                     /* icon_name        */,  \
168     help_id                       /* help_id          */,  \
169     dialogs_##new_func##_list_view_new /* new_func         */,  \
170     NULL                          /* restore_func     */,  \
171     view_size                     /* view_size        */,  \
172     FALSE                         /* singleton        */,  \
173     FALSE                         /* session_managed  */,  \
174     FALSE                         /* remember_size    */,  \
175     TRUE                          /* remember_if_open */,  \
176     TRUE                          /* hideable         */,  \
177     FALSE                         /* image_window     */,  \
178     TRUE                          /* dockable         */}, \
179   { "gimp-"#id"-grid"             /* identifier       */,  \
180     name                          /* name             */,  \
181     blurb                         /* blurb            */,  \
182     icon_name                     /* icon_name        */,  \
183     help_id                       /* help_id          */,  \
184     dialogs_##new_func##_grid_view_new /* new_func         */,  \
185     NULL                          /* restore_func     */,  \
186     view_size                     /* view_size        */,  \
187     FALSE                         /* singleton        */,  \
188     FALSE                         /* session_managed  */,  \
189     FALSE                         /* remember_size    */,  \
190     TRUE                          /* remember_if_open */,  \
191     TRUE                          /* hideable         */,  \
192     FALSE                         /* image_window     */,  \
193     TRUE                          /* dockable         */}
194 
195 #define LIST(id, new_func, name, blurb, icon_name, help_id, view_size) \
196   { "gimp-"#id"-list"                   /* identifier       */, \
197     name                                /* name             */, \
198     blurb                               /* blurb            */, \
199     icon_name                            /* icon_name         */, \
200     help_id                             /* help_id          */, \
201     dialogs_##new_func##_list_view_new  /* new_func         */, \
202     NULL                                /* restore_func     */, \
203     view_size                           /* view_size        */, \
204     FALSE                               /* singleton        */, \
205     FALSE                               /* session_managed  */, \
206     FALSE                               /* remember_size    */, \
207     TRUE                                /* remember_if_open */, \
208     TRUE                                /* hideable         */, \
209     FALSE                               /* image_window     */, \
210     TRUE                                /* dockable         */}
211 
212 
213 static GtkWidget * dialogs_restore_dialog (GimpDialogFactory *factory,
214                                            GdkScreen         *screen,
215                                            gint               monitor,
216                                            GimpSessionInfo   *info);
217 static GtkWidget * dialogs_restore_window (GimpDialogFactory *factory,
218                                            GdkScreen         *screen,
219                                            gint               monitor,
220                                            GimpSessionInfo   *info);
221 
222 
223 static const GimpDialogFactoryEntry entries[] =
224 {
225   /*  foreign toplevels without constructor  */
226   FOREIGN ("gimp-brightness-contrast-tool-dialog", TRUE,  FALSE),
227   FOREIGN ("gimp-color-balance-tool-dialog",       TRUE,  FALSE),
228   FOREIGN ("gimp-color-picker-tool-dialog",        TRUE,  TRUE),
229   FOREIGN ("gimp-colorize-tool-dialog",            TRUE,  FALSE),
230   FOREIGN ("gimp-crop-tool-dialog",                TRUE,  FALSE),
231   FOREIGN ("gimp-curves-tool-dialog",              TRUE,  TRUE),
232   FOREIGN ("gimp-desaturate-tool-dialog",          TRUE,  FALSE),
233   FOREIGN ("gimp-foreground-select-tool-dialog",   TRUE,  FALSE),
234   FOREIGN ("gimp-gegl-tool-dialog",                TRUE,  FALSE),
235   FOREIGN ("gimp-gradient-tool-dialog",            TRUE,  FALSE),
236   FOREIGN ("gimp-hue-saturation-tool-dialog",      TRUE,  FALSE),
237   FOREIGN ("gimp-levels-tool-dialog",              TRUE,  TRUE),
238   FOREIGN ("gimp-measure-tool-dialog",             TRUE,  FALSE),
239   FOREIGN ("gimp-offset-tool-dialog",              TRUE,  FALSE),
240   FOREIGN ("gimp-operation-tool-dialog",           TRUE,  FALSE),
241   FOREIGN ("gimp-posterize-tool-dialog",           TRUE,  FALSE),
242   FOREIGN ("gimp-rotate-tool-dialog",              TRUE,  FALSE),
243   FOREIGN ("gimp-scale-tool-dialog",               TRUE,  FALSE),
244   FOREIGN ("gimp-shear-tool-dialog",               TRUE,  FALSE),
245   FOREIGN ("gimp-text-tool-dialog",                TRUE,  TRUE),
246   FOREIGN ("gimp-threshold-tool-dialog",           TRUE,  FALSE),
247   FOREIGN ("gimp-transform-3d-tool-dialog",        TRUE,  FALSE),
248   FOREIGN ("gimp-perspective-tool-dialog",         TRUE,  FALSE),
249   FOREIGN ("gimp-unified-transform-tool-dialog",   TRUE,  FALSE),
250   FOREIGN ("gimp-handle-transform-tool-dialog",    TRUE,  FALSE),
251 
252   FOREIGN ("gimp-toolbox-color-dialog",            TRUE,  FALSE),
253   FOREIGN ("gimp-gradient-editor-color-dialog",    TRUE,  FALSE),
254   FOREIGN ("gimp-palette-editor-color-dialog",     TRUE,  FALSE),
255   FOREIGN ("gimp-colormap-editor-color-dialog",    TRUE,  FALSE),
256 
257   FOREIGN ("gimp-controller-editor-dialog",        FALSE, TRUE),
258   FOREIGN ("gimp-controller-action-dialog",        FALSE, TRUE),
259 
260   /*  ordinary toplevels  */
261   TOPLEVEL ("gimp-image-new-dialog",
262             dialogs_image_new_new,          FALSE, TRUE, FALSE),
263   TOPLEVEL ("gimp-file-open-dialog",
264             dialogs_file_open_new,          TRUE,  TRUE, TRUE),
265   TOPLEVEL ("gimp-file-open-location-dialog",
266             dialogs_file_open_location_new, FALSE, TRUE, FALSE),
267   TOPLEVEL ("gimp-file-save-dialog",
268             dialogs_file_save_new,          FALSE, TRUE, TRUE),
269   TOPLEVEL ("gimp-file-export-dialog",
270             dialogs_file_export_new,        FALSE, TRUE, TRUE),
271 
272   /*  singleton toplevels  */
273   TOPLEVEL ("gimp-preferences-dialog",
274             dialogs_preferences_get,        TRUE, TRUE,  TRUE),
275   TOPLEVEL ("gimp-input-devices-dialog",
276             dialogs_input_devices_get,      TRUE, TRUE,  FALSE),
277   TOPLEVEL ("gimp-keyboard-shortcuts-dialog",
278             dialogs_keyboard_shortcuts_get, TRUE, TRUE,  TRUE),
279   TOPLEVEL ("gimp-module-dialog",
280             dialogs_module_get,             TRUE, TRUE,  TRUE),
281   TOPLEVEL ("gimp-palette-import-dialog",
282             dialogs_palette_import_get,     TRUE, TRUE,  TRUE),
283   TOPLEVEL ("gimp-tips-dialog",
284             dialogs_tips_get,               TRUE, FALSE, FALSE),
285   TOPLEVEL ("gimp-about-dialog",
286             dialogs_about_get,              TRUE, FALSE, FALSE),
287   TOPLEVEL ("gimp-action-search-dialog",
288             dialogs_action_search_get,      TRUE, TRUE,  TRUE),
289   TOPLEVEL ("gimp-error-dialog",
290             dialogs_error_get,              TRUE, FALSE, FALSE),
291   TOPLEVEL ("gimp-critical-dialog",
292             dialogs_critical_get,           TRUE, FALSE, FALSE),
293   TOPLEVEL ("gimp-close-all-dialog",
294             dialogs_close_all_get,          TRUE, FALSE, FALSE),
295   TOPLEVEL ("gimp-quit-dialog",
296             dialogs_quit_get,               TRUE, FALSE, FALSE),
297 
298   /*  docks  */
299   DOCK ("gimp-dock",
300         dialogs_dock_new),
301   DOCK ("gimp-toolbox",
302         dialogs_toolbox_new),
303 
304   /*  dock windows  */
305   DOCK_WINDOW ("gimp-dock-window",
306                dialogs_dock_window_new),
307   DOCK_WINDOW ("gimp-toolbox-window",
308                dialogs_toolbox_dock_window_new),
309 
310   /*  singleton dockables  */
311   DOCKABLE ("gimp-tool-options",
312             N_("Tool Options"), NULL, GIMP_ICON_DIALOG_TOOL_OPTIONS,
313             GIMP_HELP_TOOL_OPTIONS_DIALOG,
314             dialogs_tool_options_new, 0, TRUE),
315   DOCKABLE ("gimp-device-status",
316             N_("Devices"), N_("Device Status"), GIMP_ICON_DIALOG_DEVICE_STATUS,
317             GIMP_HELP_DEVICE_STATUS_DIALOG,
318             dialogs_device_status_new, 0, TRUE),
319   DOCKABLE ("gimp-error-console",
320             N_("Errors"), N_("Error Console"), GIMP_ICON_DIALOG_WARNING,
321             GIMP_HELP_ERRORS_DIALOG,
322             dialogs_error_console_new, 0, TRUE),
323   DOCKABLE ("gimp-cursor-view",
324             N_("Pointer"), N_("Pointer Information"), GIMP_ICON_CURSOR,
325             GIMP_HELP_POINTER_INFO_DIALOG,
326             dialogs_cursor_view_new, 0, TRUE),
327   DOCKABLE ("gimp-dashboard",
328             N_("Dashboard"), N_("Dashboard"), GIMP_ICON_DIALOG_DASHBOARD,
329             GIMP_HELP_DASHBOARD_DIALOG,
330             dialogs_dashboard_new, 0, TRUE),
331 
332   /*  list & grid views  */
333   LISTGRID (image, image,
334             N_("Images"), NULL, GIMP_ICON_DIALOG_IMAGES,
335             GIMP_HELP_IMAGE_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
336   LISTGRID (brush, brush,
337             N_("Brushes"), NULL, GIMP_ICON_BRUSH,
338             GIMP_HELP_BRUSH_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
339   LISTGRID (dynamics, dynamics,
340             N_("Paint Dynamics"), NULL, GIMP_ICON_DYNAMICS,
341             GIMP_HELP_DYNAMICS_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
342   LISTGRID (mypaint-brush, mypaint_brush,
343             N_("MyPaint Brushes"), NULL, GIMP_ICON_MYPAINT_BRUSH,
344             GIMP_HELP_MYPAINT_BRUSH_DIALOG, GIMP_VIEW_SIZE_LARGE),
345   LISTGRID (pattern, pattern,
346             N_("Patterns"), NULL, GIMP_ICON_PATTERN,
347             GIMP_HELP_PATTERN_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
348   LISTGRID (gradient, gradient,
349             N_("Gradients"), NULL, GIMP_ICON_GRADIENT,
350             GIMP_HELP_GRADIENT_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
351   LISTGRID (palette, palette,
352             N_("Palettes"), NULL, GIMP_ICON_PALETTE,
353             GIMP_HELP_PALETTE_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
354   LISTGRID (font, font,
355             N_("Fonts"), NULL, GIMP_ICON_FONT,
356             GIMP_HELP_FONT_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
357   LISTGRID (buffer, buffer,
358             N_("Buffers"), NULL, GIMP_ICON_BUFFER,
359             GIMP_HELP_BUFFER_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
360   LISTGRID (tool-preset, tool_preset,
361             N_("Tool Presets"), NULL, GIMP_ICON_TOOL_PRESET,
362             GIMP_HELP_TOOL_PRESET_DIALOG, GIMP_VIEW_SIZE_MEDIUM),
363   LISTGRID (document, document,
364             N_("History"), N_("Document History"), GIMP_ICON_DOCUMENT_OPEN_RECENT,
365             GIMP_HELP_DOCUMENT_DIALOG, GIMP_VIEW_SIZE_LARGE),
366   LISTGRID (template, template,
367             N_("Templates"), N_("Image Templates"), GIMP_ICON_TEMPLATE,
368             GIMP_HELP_TEMPLATE_DIALOG, GIMP_VIEW_SIZE_SMALL),
369 
370   /*  image related  */
371   DOCKABLE ("gimp-layer-list",
372             N_("Layers"), NULL, GIMP_ICON_DIALOG_LAYERS,
373             GIMP_HELP_LAYER_DIALOG,
374             dialogs_layer_list_view_new, 0, FALSE),
375   DOCKABLE ("gimp-channel-list",
376             N_("Channels"), NULL, GIMP_ICON_DIALOG_CHANNELS,
377             GIMP_HELP_CHANNEL_DIALOG,
378             dialogs_channel_list_view_new, 0, FALSE),
379   DOCKABLE ("gimp-vectors-list",
380             N_("Paths"), NULL, GIMP_ICON_DIALOG_PATHS,
381             GIMP_HELP_PATH_DIALOG,
382             dialogs_vectors_list_view_new, 0, FALSE),
383   DOCKABLE ("gimp-indexed-palette",
384             N_("Colormap"), NULL, GIMP_ICON_COLORMAP,
385             GIMP_HELP_INDEXED_PALETTE_DIALOG,
386             dialogs_colormap_editor_new, 0, FALSE),
387   DOCKABLE ("gimp-histogram-editor",
388             N_("Histogram"), NULL, GIMP_ICON_HISTOGRAM,
389             GIMP_HELP_HISTOGRAM_DIALOG,
390             dialogs_histogram_editor_new, 0, FALSE),
391   DOCKABLE ("gimp-selection-editor",
392             N_("Selection"), N_("Selection Editor"), GIMP_ICON_SELECTION,
393             GIMP_HELP_SELECTION_DIALOG,
394             dialogs_selection_editor_new, 0, FALSE),
395   DOCKABLE ("gimp-symmetry-editor",
396             N_("Symmetry Painting"), NULL, GIMP_ICON_SYMMETRY,
397             GIMP_HELP_SYMMETRY_DIALOG,
398             dialogs_symmetry_editor_new, 0, FALSE),
399   DOCKABLE ("gimp-undo-history",
400             N_("Undo"), N_("Undo History"), GIMP_ICON_DIALOG_UNDO_HISTORY,
401             GIMP_HELP_UNDO_DIALOG,
402             dialogs_undo_editor_new, 0, FALSE),
403   DOCKABLE ("gimp-sample-point-editor",
404             N_("Sample Points"), N_("Sample Points"), GIMP_ICON_SAMPLE_POINT,
405             GIMP_HELP_SAMPLE_POINT_DIALOG,
406             dialogs_sample_point_editor_new, 0, FALSE),
407 
408   /*  display related  */
409   DOCKABLE ("gimp-navigation-view",
410             N_("Navigation"), N_("Display Navigation"), GIMP_ICON_DIALOG_NAVIGATION,
411             GIMP_HELP_NAVIGATION_DIALOG,
412             dialogs_navigation_editor_new, 0, FALSE),
413 
414   /*  editors  */
415   DOCKABLE ("gimp-color-editor",
416             N_("FG/BG"), N_("FG/BG Color"), GIMP_ICON_COLORS_DEFAULT,
417             GIMP_HELP_COLOR_DIALOG,
418             dialogs_color_editor_new, 0, FALSE),
419 
420   /*  singleton editors  */
421   DOCKABLE ("gimp-brush-editor",
422             N_("Brush Editor"), NULL, GIMP_ICON_BRUSH,
423             GIMP_HELP_BRUSH_EDITOR_DIALOG,
424             dialogs_brush_editor_get, 0, TRUE),
425   DOCKABLE ("gimp-dynamics-editor",
426             N_("Paint Dynamics Editor"), NULL, GIMP_ICON_DYNAMICS,
427             GIMP_HELP_DYNAMICS_EDITOR_DIALOG,
428             dialogs_dynamics_editor_get, 0, TRUE),
429   DOCKABLE ("gimp-gradient-editor",
430             N_("Gradient Editor"), NULL, GIMP_ICON_GRADIENT,
431             GIMP_HELP_GRADIENT_EDITOR_DIALOG,
432             dialogs_gradient_editor_get, 0, TRUE),
433   DOCKABLE ("gimp-palette-editor",
434             N_("Palette Editor"), NULL, GIMP_ICON_PALETTE,
435             GIMP_HELP_PALETTE_EDITOR_DIALOG,
436             dialogs_palette_editor_get, 0, TRUE),
437   DOCKABLE ("gimp-tool-preset-editor",
438             N_("Tool Preset Editor"), NULL, GIMP_ICON_TOOL_PRESET,
439             GIMP_HELP_TOOL_PRESET_EDITOR_DIALOG,
440             dialogs_tool_preset_editor_get, 0, TRUE),
441 
442   /*  image windows  */
443   IMAGE_WINDOW ("gimp-empty-image-window",
444                 TRUE, TRUE),
445   IMAGE_WINDOW ("gimp-single-image-window",
446                 TRUE, TRUE)
447 };
448 
449 /**
450  * dialogs_restore_dialog:
451  * @factory:
452  * @screen:
453  * @monitor:
454  * @info:
455  *
456  * Creates a top level widget based on the given session info object
457  * in which other widgets later can be be put, typically also restored
458  * from the same session info object.
459  *
460  * Returns:
461  **/
462 static GtkWidget *
dialogs_restore_dialog(GimpDialogFactory * factory,GdkScreen * screen,gint monitor,GimpSessionInfo * info)463 dialogs_restore_dialog (GimpDialogFactory *factory,
464                         GdkScreen         *screen,
465                         gint               monitor,
466                         GimpSessionInfo   *info)
467 {
468   GtkWidget      *dialog;
469   GimpCoreConfig *config = gimp_dialog_factory_get_context (factory)->gimp->config;
470 
471   GIMP_LOG (DIALOG_FACTORY, "restoring toplevel \"%s\" (info %p)",
472             gimp_session_info_get_factory_entry (info)->identifier,
473             info);
474 
475   dialog =
476     gimp_dialog_factory_dialog_new (factory, screen, monitor,
477                                     NULL /*ui_manager*/,
478                                     gimp_session_info_get_factory_entry (info)->identifier,
479                                     gimp_session_info_get_factory_entry (info)->view_size,
480                                     ! GIMP_GUI_CONFIG (config)->hide_docks);
481 
482   g_object_set_data (G_OBJECT (dialog), GIMP_DIALOG_VISIBILITY_KEY,
483                      GINT_TO_POINTER (GIMP_GUI_CONFIG (config)->hide_docks ?
484                                       GIMP_DIALOG_VISIBILITY_HIDDEN :
485                                       GIMP_DIALOG_VISIBILITY_VISIBLE));
486 
487   return dialog;
488 }
489 
490 /**
491  * dialogs_restore_window:
492  * @factory:
493  * @screen:
494  * @monitor:
495  * @info:
496  *
497  * "restores" the image window. We don't really restore anything since
498  * the image window is created earlier, so we just look for and return
499  * the already-created image window.
500  *
501  * Returns:
502  **/
503 static GtkWidget *
dialogs_restore_window(GimpDialogFactory * factory,GdkScreen * screen,gint monitor,GimpSessionInfo * info)504 dialogs_restore_window (GimpDialogFactory *factory,
505                         GdkScreen         *screen,
506                         gint               monitor,
507                         GimpSessionInfo   *info)
508 {
509   Gimp             *gimp    = gimp_dialog_factory_get_context (factory)->gimp;
510   GimpDisplay      *display = GIMP_DISPLAY (gimp_get_empty_display (gimp));
511   GimpDisplayShell *shell   = gimp_display_get_shell (display);
512   GtkWidget        *dialog;
513 
514   dialog = GTK_WIDGET (gimp_display_shell_get_window (shell));
515 
516   return dialog;
517 }
518 
519 
520 /*  public functions  */
521 
522 void
dialogs_init(Gimp * gimp,GimpMenuFactory * menu_factory)523 dialogs_init (Gimp            *gimp,
524               GimpMenuFactory *menu_factory)
525 {
526   GimpDialogFactory *factory = NULL;
527   gint               i       = 0;
528 
529   g_return_if_fail (GIMP_IS_GIMP (gimp));
530   g_return_if_fail (GIMP_IS_MENU_FACTORY (menu_factory));
531 
532   factory = gimp_dialog_factory_new ("toplevel",
533                                      gimp_get_user_context (gimp),
534                                      menu_factory);
535   gimp_dialog_factory_set_singleton (factory);
536 
537   for (i = 0; i < G_N_ELEMENTS (entries); i++)
538     gimp_dialog_factory_register_entry (factory,
539                                         entries[i].identifier,
540                                         gettext (entries[i].name),
541                                         gettext (entries[i].blurb),
542                                         entries[i].icon_name,
543                                         entries[i].help_id,
544                                         entries[i].new_func,
545                                         entries[i].restore_func,
546                                         entries[i].view_size,
547                                         entries[i].singleton,
548                                         entries[i].session_managed,
549                                         entries[i].remember_size,
550                                         entries[i].remember_if_open,
551                                         entries[i].hideable,
552                                         entries[i].image_window,
553                                         entries[i].dockable);
554 
555   global_recent_docks = gimp_list_new (GIMP_TYPE_SESSION_INFO, FALSE);
556 }
557 
558 void
dialogs_exit(Gimp * gimp)559 dialogs_exit (Gimp *gimp)
560 {
561   g_return_if_fail (GIMP_IS_GIMP (gimp));
562 
563   if (gimp_dialog_factory_get_singleton ())
564     {
565       /* run dispose manually so the factory destroys its dialogs, which
566        * might in turn directly or indirectly ref the factory
567        */
568       g_object_run_dispose (G_OBJECT (gimp_dialog_factory_get_singleton ()));
569 
570       g_object_unref (gimp_dialog_factory_get_singleton ());
571       gimp_dialog_factory_set_singleton (NULL);
572     }
573 
574   g_clear_object (&global_recent_docks);
575 }
576 
577 static void
dialogs_ensure_factory_entry_on_recent_dock(GimpSessionInfo * info)578 dialogs_ensure_factory_entry_on_recent_dock (GimpSessionInfo *info)
579 {
580   if (! gimp_session_info_get_factory_entry (info))
581     {
582       GimpDialogFactoryEntry *entry = NULL;
583 
584       /* The recent docks container only contains session infos for
585        * dock windows
586        */
587       entry = gimp_dialog_factory_find_entry (gimp_dialog_factory_get_singleton (),
588                                               "gimp-dock-window");
589 
590       gimp_session_info_set_factory_entry (info, entry);
591     }
592 }
593 
594 static GFile *
dialogs_get_dockrc_file(void)595 dialogs_get_dockrc_file (void)
596 {
597   const gchar *basename;
598 
599   basename = g_getenv ("GIMP_TESTING_DOCKRC_NAME");
600   if (! basename)
601     basename = "dockrc";
602 
603   return gimp_directory_file (basename, NULL);
604 }
605 
606 void
dialogs_load_recent_docks(Gimp * gimp)607 dialogs_load_recent_docks (Gimp *gimp)
608 {
609   GFile  *file;
610   GError *error = NULL;
611 
612   g_return_if_fail (GIMP_IS_GIMP (gimp));
613 
614   file = dialogs_get_dockrc_file ();
615 
616   if (gimp->be_verbose)
617     g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
618 
619   if (! gimp_config_deserialize_gfile (GIMP_CONFIG (global_recent_docks),
620                                        file,
621                                        NULL, &error))
622     {
623       if (error->code != GIMP_CONFIG_ERROR_OPEN_ENOENT)
624         gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
625 
626       g_clear_error (&error);
627     }
628 
629   g_object_unref (file);
630 
631   /* In GIMP 2.6 dockrc did not contain the factory entries for the
632    * session infos, so set that up manually if needed
633    */
634   gimp_container_foreach (global_recent_docks,
635                           (GFunc) dialogs_ensure_factory_entry_on_recent_dock,
636                           NULL);
637 
638   gimp_list_reverse (GIMP_LIST (global_recent_docks));
639 }
640 
641 void
dialogs_save_recent_docks(Gimp * gimp)642 dialogs_save_recent_docks (Gimp *gimp)
643 {
644   GFile  *file;
645   GError *error = NULL;
646 
647   g_return_if_fail (GIMP_IS_GIMP (gimp));
648 
649   file = dialogs_get_dockrc_file ();
650 
651   if (gimp->be_verbose)
652     g_print ("Writing '%s'\n", gimp_file_get_utf8_name (file));
653 
654   if (! gimp_config_serialize_to_gfile (GIMP_CONFIG (global_recent_docks),
655                                         file,
656                                         "recently closed docks",
657                                         "end of recently closed docks",
658                                         NULL, &error))
659     {
660       gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
661       g_clear_error (&error);
662     }
663 
664   g_object_unref (file);
665 }
666 
667 GtkWidget *
dialogs_get_toolbox(void)668 dialogs_get_toolbox (void)
669 {
670   GList *list;
671 
672   g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (gimp_dialog_factory_get_singleton ()), NULL);
673 
674   for (list = gimp_dialog_factory_get_open_dialogs (gimp_dialog_factory_get_singleton ());
675        list;
676        list = g_list_next (list))
677     {
678       if (GIMP_IS_DOCK_WINDOW (list->data) &&
679           gimp_dock_window_has_toolbox (list->data))
680         return list->data;
681     }
682 
683   return NULL;
684 }
685 
686 GtkWidget *
dialogs_get_dialog(GObject * attach_object,const gchar * attach_key)687 dialogs_get_dialog (GObject     *attach_object,
688                     const gchar *attach_key)
689 {
690   g_return_val_if_fail (G_IS_OBJECT (attach_object), NULL);
691   g_return_val_if_fail (attach_key != NULL, NULL);
692 
693   return g_object_get_data (attach_object, attach_key);
694 }
695 
696 void
dialogs_attach_dialog(GObject * attach_object,const gchar * attach_key,GtkWidget * dialog)697 dialogs_attach_dialog (GObject     *attach_object,
698                        const gchar *attach_key,
699                        GtkWidget   *dialog)
700 {
701   g_return_if_fail (G_IS_OBJECT (attach_object));
702   g_return_if_fail (attach_key != NULL);
703   g_return_if_fail (GTK_IS_WIDGET (dialog));
704 
705   g_object_set_data (attach_object, attach_key, dialog);
706   g_object_set_data (G_OBJECT (dialog), "gimp-dialogs-attach-key",
707                      (gpointer) attach_key);
708 
709   g_signal_connect_object (dialog, "destroy",
710                            G_CALLBACK (dialogs_detach_dialog),
711                            attach_object,
712                            G_CONNECT_SWAPPED);
713 }
714 
715 void
dialogs_detach_dialog(GObject * attach_object,GtkWidget * dialog)716 dialogs_detach_dialog (GObject   *attach_object,
717                        GtkWidget *dialog)
718 {
719   const gchar *attach_key;
720 
721   g_return_if_fail (G_IS_OBJECT (attach_object));
722   g_return_if_fail (GTK_IS_WIDGET (dialog));
723 
724   attach_key = g_object_get_data (G_OBJECT (dialog),
725                                   "gimp-dialogs-attach-key");
726 
727   g_return_if_fail (attach_key != NULL);
728 
729   g_object_set_data (attach_object, attach_key, NULL);
730 
731   g_signal_handlers_disconnect_by_func (dialog,
732                                         dialogs_detach_dialog,
733                                         attach_object);
734 }
735 
736 void
dialogs_destroy_dialog(GObject * attach_object,const gchar * attach_key)737 dialogs_destroy_dialog (GObject     *attach_object,
738                         const gchar *attach_key)
739 {
740   GtkWidget *dialog;
741 
742   g_return_if_fail (G_IS_OBJECT (attach_object));
743   g_return_if_fail (attach_key != NULL);
744 
745   dialog = g_object_get_data (attach_object, attach_key);
746 
747   if (dialog)
748     gtk_widget_destroy (dialog);
749 }
750