gui-vtable.c 29.5 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2
3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
8
9
10
11
12
13
14
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
15
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17
18
19
 */

#include "config.h"

20
#include <string.h>
Ell's avatar
Ell committed
21
#include <errno.h>
22

23
#include <gegl.h>
24
#include <gtk/gtk.h>
25
26

#ifdef GDK_WINDOWING_X11
27
#include <gdk/gdkx.h>
28
#endif
29

Ell's avatar
Ell committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#ifdef G_OS_WIN32
#include <windows.h>
#include <fcntl.h>
#include <io.h>

#ifndef pipe
#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
#endif
#else
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#endif

#include "libgimpbase/gimpbase.h"
46
47
48
49
#include "libgimpwidgets/gimpwidgets.h"

#include "gui-types.h"

50
51
#include "config/gimpguiconfig.h"

52
#include "core/gimp.h"
Ell's avatar
Ell committed
53
54
#include "core/gimp-parallel.h"
#include "core/gimp-spawn.h"
55
#include "core/gimp-utils.h"
Ell's avatar
Ell committed
56
#include "core/gimpasync.h"
57
#include "core/gimpbrush.h"
Ell's avatar
Ell committed
58
#include "core/gimpcancelable.h"
59
#include "core/gimpcontainer.h"
60
#include "core/gimpcontext.h"
61
#include "core/gimpgradient.h"
62
#include "core/gimpimage.h"
63
64
#include "core/gimpimagefile.h"
#include "core/gimplist.h"
65
66
#include "core/gimppalette.h"
#include "core/gimppattern.h"
67
#include "core/gimpprogress.h"
Ell's avatar
Ell committed
68
#include "core/gimpwaitable.h"
69
70

#include "text/gimpfont.h"
71

Ell's avatar
Ell committed
72
73
74
#include "pdb/gimppdb.h"
#include "pdb/gimpprocedure.h"

75
#include "plug-in/gimppluginmanager-file.h"
76

77
#include "widgets/gimpactiongroup.h"
78
#include "widgets/gimpbrushselect.h"
79
#include "widgets/gimpdialogfactory.h"
Sven Neumann's avatar
Sven Neumann committed
80
#include "widgets/gimpdocked.h"
81
82
#include "widgets/gimpfontselect.h"
#include "widgets/gimpgradientselect.h"
83
#include "widgets/gimphelp.h"
84
85
86
87
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpmenufactory.h"
#include "widgets/gimppaletteselect.h"
#include "widgets/gimppatternselect.h"
88
#include "widgets/gimpprogressdialog.h"
89
#include "widgets/gimpuimanager.h"
90
#include "widgets/gimpwidgets-utils.h"
91
92
93
94

#include "display/gimpdisplay.h"
#include "display/gimpdisplay-foreach.h"
#include "display/gimpdisplayshell.h"
95
96
#include "display/gimpsinglewindowstrategy.h"
#include "display/gimpmultiwindowstrategy.h"
97

98
99
#include "actions/plug-in-actions.h"

100
101
#include "menus/menus.h"

102
103
#include "dialogs/color-profile-import-dialog.h"

104
#include "gui.h"
105
#include "gui-message.h"
106
#include "gui-vtable.h"
107
#include "icon-themes.h"
Michael Natterer's avatar
Michael Natterer committed
108
#include "themes.h"
109
110
111
112


/*  local function prototypes  */

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
static void           gui_ungrab                 (Gimp                *gimp);

static void           gui_threads_enter          (Gimp                *gimp);
static void           gui_threads_leave          (Gimp                *gimp);

static void           gui_set_busy               (Gimp                *gimp);
static void           gui_unset_busy             (Gimp                *gimp);

static void           gui_help                   (Gimp                *gimp,
                                                  GimpProgress        *progress,
                                                  const gchar         *help_domain,
                                                  const gchar         *help_id);
static const gchar  * gui_get_program_class      (Gimp                *gimp);
static gchar        * gui_get_display_name       (Gimp                *gimp,
                                                  gint                 display_ID,
                                                  GObject            **screen,
                                                  gint                *monitor);
static guint32        gui_get_user_time          (Gimp                *gimp);
131
static GFile        * gui_get_theme_dir          (Gimp                *gimp);
132
static GFile        * gui_get_icon_theme_dir     (Gimp                *gimp);
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
static GimpObject   * gui_get_window_strategy    (Gimp                *gimp);
static GimpObject   * gui_get_empty_display      (Gimp                *gimp);
static GimpObject   * gui_display_get_by_ID      (Gimp                *gimp,
                                                  gint                 ID);
static gint           gui_display_get_ID         (GimpObject          *display);
static guint32        gui_display_get_window_id  (GimpObject          *display);
static GimpObject   * gui_display_create         (Gimp                *gimp,
                                                  GimpImage           *image,
                                                  GimpUnit             unit,
                                                  gdouble              scale,
                                                  GObject             *screen,
                                                  gint                 monitor);
static void           gui_display_delete         (GimpObject          *display);
static void           gui_displays_reconnect     (Gimp                *gimp,
                                                  GimpImage           *old_image,
                                                  GimpImage           *new_image);
Ell's avatar
Ell committed
149
150
151
static gboolean       gui_wait                   (Gimp                *gimp,
                                                  GimpWaitable        *waitable,
                                                  const gchar         *message);
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
static GimpProgress * gui_new_progress           (Gimp                *gimp,
                                                  GimpObject          *display);
static void           gui_free_progress          (Gimp                *gimp,
                                                  GimpProgress        *progress);
static gboolean       gui_pdb_dialog_new         (Gimp                *gimp,
                                                  GimpContext         *context,
                                                  GimpProgress        *progress,
                                                  GimpContainer       *container,
                                                  const gchar         *title,
                                                  const gchar         *callback_name,
                                                  const gchar         *object_name,
                                                  va_list              args);
static gboolean       gui_pdb_dialog_set         (Gimp                *gimp,
                                                  GimpContainer       *container,
                                                  const gchar         *callback_name,
                                                  const gchar         *object_name,
                                                  va_list              args);
static gboolean       gui_pdb_dialog_close       (Gimp                *gimp,
                                                  GimpContainer       *container,
                                                  const gchar         *callback_name);
static gboolean       gui_recent_list_add_file   (Gimp                *gimp,
                                                  GFile               *file,
                                                  const gchar         *mime_type);
static void           gui_recent_list_load       (Gimp                *gimp);

177
178
static GMountOperation
                    * gui_get_mount_operation    (Gimp                *gimp,
179
                                                  GimpProgress        *progress);
180

181
182
183
184
185
static GimpColorProfilePolicy
                      gui_query_profile_policy   (Gimp                *gimp,
                                                  GimpImage           *image,
                                                  GimpContext         *context,
                                                  GimpColorProfile   **dest_profile,
186
187
                                                  GimpColorRenderingIntent *intent,
                                                  gboolean            *bpc,
188
189
                                                  gboolean            *dont_ask);

190
191
192
193
194
195
196
197

/*  public functions  */

void
gui_vtable_init (Gimp *gimp)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));

198
199
200
201
202
203
204
205
206
207
208
  gimp->gui.ungrab                 = gui_ungrab;
  gimp->gui.threads_enter          = gui_threads_enter;
  gimp->gui.threads_leave          = gui_threads_leave;
  gimp->gui.set_busy               = gui_set_busy;
  gimp->gui.unset_busy             = gui_unset_busy;
  gimp->gui.show_message           = gui_message;
  gimp->gui.help                   = gui_help;
  gimp->gui.get_program_class      = gui_get_program_class;
  gimp->gui.get_display_name       = gui_get_display_name;
  gimp->gui.get_user_time          = gui_get_user_time;
  gimp->gui.get_theme_dir          = gui_get_theme_dir;
209
  gimp->gui.get_icon_theme_dir     = gui_get_icon_theme_dir;
210
211
212
213
214
215
216
217
  gimp->gui.get_window_strategy    = gui_get_window_strategy;
  gimp->gui.get_empty_display      = gui_get_empty_display;
  gimp->gui.display_get_by_id      = gui_display_get_by_ID;
  gimp->gui.display_get_id         = gui_display_get_ID;
  gimp->gui.display_get_window_id  = gui_display_get_window_id;
  gimp->gui.display_create         = gui_display_create;
  gimp->gui.display_delete         = gui_display_delete;
  gimp->gui.displays_reconnect     = gui_displays_reconnect;
Ell's avatar
Ell committed
218
  gimp->gui.wait                   = gui_wait;
219
220
221
222
223
224
225
  gimp->gui.progress_new           = gui_new_progress;
  gimp->gui.progress_free          = gui_free_progress;
  gimp->gui.pdb_dialog_new         = gui_pdb_dialog_new;
  gimp->gui.pdb_dialog_set         = gui_pdb_dialog_set;
  gimp->gui.pdb_dialog_close       = gui_pdb_dialog_close;
  gimp->gui.recent_list_add_file   = gui_recent_list_add_file;
  gimp->gui.recent_list_load       = gui_recent_list_load;
226
  gimp->gui.get_mount_operation    = gui_get_mount_operation;
227
  gimp->gui.query_profile_policy   = gui_query_profile_policy;
228
229
230
231
232
}


/*  private functions  */

233
234
235
236
237
static void
gui_ungrab (Gimp *gimp)
{
  GdkDisplay *display = gdk_display_get_default ();

Sven Neumann's avatar
Sven Neumann committed
238
239
240
241
242
  if (display)
    {
      gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
      gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
    }
243
244
}

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
static void
gui_threads_enter (Gimp *gimp)
{
  GDK_THREADS_ENTER ();
}

static void
gui_threads_leave (Gimp *gimp)
{
  GDK_THREADS_LEAVE ();
}

static void
gui_set_busy (Gimp *gimp)
{
  gimp_displays_set_busy (gimp);
261
  gimp_dialog_factory_set_busy (gimp_dialog_factory_get_singleton ());
262
263
264
265
266
267
268
269

  gdk_flush ();
}

static void
gui_unset_busy (Gimp *gimp)
{
  gimp_displays_unset_busy (gimp);
270
  gimp_dialog_factory_unset_busy (gimp_dialog_factory_get_singleton ());
271
272
273
274
275

  gdk_flush ();
}

static void
276
277
278
279
gui_help (Gimp         *gimp,
          GimpProgress *progress,
          const gchar  *help_domain,
          const gchar  *help_id)
280
{
281
  gimp_help_show (gimp, progress, help_domain, help_id);
282
283
}

284
285
286
287
288
289
290
static const gchar *
gui_get_program_class (Gimp *gimp)
{
  return gdk_get_program_class ();
}

static gchar *
291
292
293
294
gui_get_display_name (Gimp     *gimp,
                      gint      display_ID,
                      GObject **screen,
                      gint     *monitor)
295
{
296
297
  GimpDisplay *display   = NULL;
  GdkScreen   *my_screen = NULL;
298

299
300
  if (display_ID > 0)
    display = gimp_display_get_by_ID (gimp, display_ID);
301

302
  if (display)
303
    {
304
305
      GimpDisplayShell *shell  = gimp_display_get_shell (display);
      GdkWindow        *window = gtk_widget_get_window (GTK_WIDGET (shell));
306

307
308
      my_screen = gtk_widget_get_screen (GTK_WIDGET (shell));
      *monitor = gdk_screen_get_monitor_at_window (my_screen, window);
309
310
311
    }
  else
    {
312
313
314
315
      *monitor = gui_get_initial_monitor (gimp, &my_screen);

      if (*monitor == -1)
        *monitor = gimp_get_monitor_at_pointer (&my_screen);
316
317
    }

318
  *screen = G_OBJECT (my_screen);
319

320
321
  if (my_screen)
    return gdk_screen_make_display_name (my_screen);
322
323
324
325

  return NULL;
}

326
327
328
329
330
331
332
333
334
static guint32
gui_get_user_time (Gimp *gimp)
{
#ifdef GDK_WINDOWING_X11
  return gdk_x11_display_get_user_time (gdk_display_get_default ());
#endif
  return 0;
}

335
static GFile *
336
337
338
339
340
gui_get_theme_dir (Gimp *gimp)
{
  return themes_get_theme_dir (gimp, GIMP_GUI_CONFIG (gimp->config)->theme);
}

341
342
343
344
345
346
static GFile *
gui_get_icon_theme_dir (Gimp *gimp)
{
  return icon_themes_get_theme_dir (gimp, GIMP_GUI_CONFIG (gimp->config)->icon_theme);
}

347
348
349
350
351
352
353
354
355
static GimpObject *
gui_get_window_strategy (Gimp *gimp)
{
  if (GIMP_GUI_CONFIG (gimp->config)->single_window_mode)
    return gimp_single_window_strategy_get_singleton ();
  else
    return gimp_multi_window_strategy_get_singleton ();
}

356
357
358
359
360
static GimpObject *
gui_get_empty_display (Gimp *gimp)
{
  GimpObject *display = NULL;

361
  if (gimp_container_get_n_children (gimp->displays) == 1)
362
    {
363
      display = gimp_container_get_first_child (gimp->displays);
364

365
      if (gimp_display_get_image (GIMP_DISPLAY (display)))
366
367
368
369
370
371
372
373
374
        {
          /* The display was not empty */
          display = NULL;
        }
    }

  return display;
}

375
376
377
378
379
380
381
382
383
384
385
386
387
static GimpObject *
gui_display_get_by_ID (Gimp *gimp,
                       gint  ID)
{
  return (GimpObject *) gimp_display_get_by_ID (gimp, ID);
}

static gint
gui_display_get_ID (GimpObject *display)
{
  return gimp_display_get_ID (GIMP_DISPLAY (display));
}

Sven Neumann's avatar
Sven Neumann committed
388
static guint32
389
gui_display_get_window_id (GimpObject *display)
Sven Neumann's avatar
Sven Neumann committed
390
{
391
392
  GimpDisplay      *disp  = GIMP_DISPLAY (display);
  GimpDisplayShell *shell = gimp_display_get_shell (disp);
393

394
  if (shell)
395
    {
396
      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
397
398

      if (GTK_IS_WINDOW (toplevel))
399
        return gimp_window_get_native_id (GTK_WINDOW (toplevel));
400
    }
401

Sven Neumann's avatar
Sven Neumann committed
402
403
404
  return 0;
}

405
static GimpObject *
406
407
gui_display_create (Gimp      *gimp,
                    GimpImage *image,
408
                    GimpUnit   unit,
409
410
411
                    gdouble    scale,
                    GObject   *screen,
                    gint       monitor)
412
{
413
  GimpContext *context = gimp_get_user_context (gimp);
414
  GimpDisplay *display = GIMP_DISPLAY (gui_get_empty_display (gimp));
415

416
417
418
  if (! screen)
    monitor = gimp_get_monitor_at_pointer ((GdkScreen **) &screen);

419
  if (display)
420
    {
421
      gimp_display_fill (display, image, unit, scale);
422
423
424
425
    }
  else
    {
      GList *image_managers = gimp_ui_managers_from_name ("<Image>");
426

427
      g_return_val_if_fail (image_managers != NULL, NULL);
428

429
      display = gimp_display_new (gimp, image, unit, scale,
430
                                  image_managers->data,
431
432
433
                                  gimp_dialog_factory_get_singleton (),
                                  GDK_SCREEN (screen),
                                  monitor);
434
   }
435

436
437
438
439
440
441
442
443
444
  if (gimp_context_get_display (context) == display)
    {
      gimp_context_set_image (context, image);
      gimp_context_display_changed (context);
    }
  else
    {
      gimp_context_set_display (context, display);
    }
445

446
  return GIMP_OBJECT (display);
447
448
449
450
451
}

static void
gui_display_delete (GimpObject *display)
{
452
  gimp_display_close (GIMP_DISPLAY (display));
453
454
455
456
457
458
459
460
461
462
}

static void
gui_displays_reconnect (Gimp      *gimp,
                        GimpImage *old_image,
                        GimpImage *new_image)
{
  gimp_displays_reconnect (gimp, old_image, new_image);
}

Ell's avatar
Ell committed
463
464
465
466
467
468
469
470
static void
gui_wait_input_async (GimpAsync  *async,
                      const gint  input_pipe[2])
{
  guint8 buffer[1];

  while (read (input_pipe[0], buffer, sizeof (buffer)) == -1 &&
         errno == EINTR);
Ell's avatar
Ell committed
471
472

  gimp_async_finish (async, NULL);
Ell's avatar
Ell committed
473
474
475
}

static gboolean
Ell's avatar
Ell committed
476
477
478
gui_wait (Gimp         *gimp,
          GimpWaitable *waitable,
          const gchar  *message)
Ell's avatar
Ell committed
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
{
  GimpProcedure  *procedure;
  GimpValueArray *args;
  GimpAsync      *input_async = NULL;
  GError         *error       = NULL;
  gint            input_pipe[2];
  gint            output_pipe[2];

  procedure = gimp_pdb_lookup_procedure (gimp->pdb, "plug-in-busy-dialog");

  if (! procedure)
    return FALSE;

  if (pipe (input_pipe))
    return FALSE;

  if (pipe (output_pipe))
    {
      close (input_pipe[0]);
      close (input_pipe[1]);

      return FALSE;
    }

  gimp_spawn_set_cloexec (input_pipe[0]);
  gimp_spawn_set_cloexec (output_pipe[1]);

  args = gimp_procedure_get_arguments (procedure);
  gimp_value_array_truncate (args, 5);

  g_value_set_int    (gimp_value_array_index (args, 0),
                      GIMP_RUN_INTERACTIVE);
  g_value_set_int    (gimp_value_array_index (args, 1),
                      output_pipe[0]);
  g_value_set_int    (gimp_value_array_index (args, 2),
                      input_pipe[1]);
  g_value_set_string (gimp_value_array_index (args, 3),
                      message);
  g_value_set_int    (gimp_value_array_index (args, 4),
                      GIMP_IS_CANCELABLE (waitable));

  gimp_procedure_execute_async (procedure, gimp,
                                gimp_get_user_context (gimp),
                                NULL, args, NULL, &error);

  gimp_value_array_unref (args);

  close (input_pipe[1]);
  close (output_pipe[0]);

  if (error)
    {
      g_clear_error (&error);

      close (input_pipe[0]);
      close (output_pipe[1]);

      return FALSE;
    }

  if (GIMP_IS_CANCELABLE (waitable))
    {
      /* listens for a cancellation request */
542
      input_async = gimp_parallel_run_async_independent (
Ell's avatar
Ell committed
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
        (GimpParallelRunAsyncFunc) gui_wait_input_async,
        input_pipe);

      while (! gimp_waitable_wait_for (waitable, 0.1 * G_TIME_SPAN_SECOND))
        {
          /* check for a cancellation request */
          if (gimp_waitable_try_wait (GIMP_WAITABLE (input_async)))
            {
              gimp_cancelable_cancel (GIMP_CANCELABLE (waitable));

              break;
            }
        }
    }

  gimp_waitable_wait (waitable);

  /* signal completion to the plug-in */
  close (output_pipe[1]);

Ell's avatar
Ell committed
563
564
565
566
567
568
  if (input_async)
    {
      gimp_waitable_wait (GIMP_WAITABLE (input_async));

      g_object_unref (input_async);
    }
Ell's avatar
Ell committed
569
570
571
572
573
574

  close (input_pipe[0]);

  return TRUE;
}

575
static GimpProgress *
576
577
gui_new_progress (Gimp       *gimp,
                  GimpObject *display)
578
{
579
  g_return_val_if_fail (display == NULL || GIMP_IS_DISPLAY (display), NULL);
580
581
582
583

  if (display)
    return GIMP_PROGRESS (display);

584
  return GIMP_PROGRESS (gimp_progress_dialog_new ());
585
586
587
}

static void
588
589
gui_free_progress (Gimp          *gimp,
                   GimpProgress  *progress)
590
{
591
  g_return_if_fail (GIMP_IS_PROGRESS_DIALOG (progress));
592

593
594
  if (GIMP_IS_PROGRESS_DIALOG (progress))
    gtk_widget_destroy (GTK_WIDGET (progress));
595
596
}

597
598
599
600
601
602
603
604
static gboolean
gui_pdb_dialog_present (GtkWindow *window)
{
  gtk_window_present (window);

  return FALSE;
}

605
606
607
static gboolean
gui_pdb_dialog_new (Gimp          *gimp,
                    GimpContext   *context,
608
                    GimpProgress  *progress,
609
610
611
612
613
614
                    GimpContainer *container,
                    const gchar   *title,
                    const gchar   *callback_name,
                    const gchar   *object_name,
                    va_list        args)
{
615
616
617
  GType        dialog_type = G_TYPE_NONE;
  const gchar *dialog_role = NULL;
  const gchar *help_id     = NULL;
618

619
  if (gimp_container_get_children_type (container) == GIMP_TYPE_BRUSH)
620
621
622
623
624
    {
      dialog_type = GIMP_TYPE_BRUSH_SELECT;
      dialog_role = "gimp-brush-selection";
      help_id     = GIMP_HELP_BRUSH_DIALOG;
    }
625
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_FONT)
626
627
628
629
630
    {
      dialog_type = GIMP_TYPE_FONT_SELECT;
      dialog_role = "gimp-font-selection";
      help_id     = GIMP_HELP_FONT_DIALOG;
    }
631
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_GRADIENT)
632
633
634
635
636
    {
      dialog_type = GIMP_TYPE_GRADIENT_SELECT;
      dialog_role = "gimp-gradient-selection";
      help_id     = GIMP_HELP_GRADIENT_DIALOG;
    }
637
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_PALETTE)
638
639
640
641
642
    {
      dialog_type = GIMP_TYPE_PALETTE_SELECT;
      dialog_role = "gimp-palette-selection";
      help_id     = GIMP_HELP_PALETTE_DIALOG;
    }
643
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_PATTERN)
644
645
646
647
648
649
650
651
652
653
654
655
656
657
    {
      dialog_type = GIMP_TYPE_PATTERN_SELECT;
      dialog_role = "gimp-pattern-selection";
      help_id     = GIMP_HELP_PATTERN_DIALOG;
    }

  if (dialog_type != G_TYPE_NONE)
    {
      GimpObject *object = NULL;

      if (object_name && strlen (object_name))
        object = gimp_container_get_child_by_name (container, object_name);

      if (! object)
658
659
        object = gimp_context_get_by_type (context,
                                           gimp_container_get_children_type (container));
660
661
662

      if (object)
        {
663
664
665
          gint        n_properties = 0;
          gchar     **names        = NULL;
          GValue     *values       = NULL;
666
          GtkWidget  *dialog;
Sven Neumann's avatar
Sven Neumann committed
667
          GtkWidget  *view;
668

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
          names = gimp_properties_append (dialog_type,
                                          &n_properties, names, &values,
                                          "title",          title,
                                          "role",           dialog_role,
                                          "help-func",      gimp_standard_help_func,
                                          "help-id",        help_id,
                                          "pdb",            gimp->pdb,
                                          "context",        context,
                                          "select-type",    gimp_container_get_children_type (container),
                                          "initial-object", object,
                                          "callback-name",  callback_name,
                                          "menu-factory",   global_menu_factory,
                                          NULL);

          names = gimp_properties_append_valist (dialog_type,
                                                 &n_properties, names, &values,
                                                 args);

          dialog = (GtkWidget *)
            g_object_new_with_properties (dialog_type,
                                          n_properties,
                                          (const gchar **) names,
                                          (const GValue *) values);

          gimp_properties_free (n_properties, names, values);
694

Sven Neumann's avatar
Sven Neumann committed
695
696
697
698
          view = GIMP_PDB_DIALOG (dialog)->view;
          if (view)
            gimp_docked_set_show_button_bar (GIMP_DOCKED (view), FALSE);

699
700
          if (progress)
            {
701
              guint32 window_id = gimp_progress_get_window_id (progress);
702

703
704
              if (window_id)
                gimp_window_set_transient_for (GTK_WINDOW (dialog), window_id);
705
706
            }

707
708
          gtk_widget_show (dialog);

709
710
          /*  workaround for bug #360106  */
          {
Sven Neumann's avatar
Sven Neumann committed
711
712
713
714
715
            GSource  *source = g_timeout_source_new (100);
            GClosure *closure;

            closure = g_cclosure_new_object (G_CALLBACK (gui_pdb_dialog_present),
                                             G_OBJECT (dialog));
716
717
718
719
720
721

            g_source_set_closure (source, closure);
            g_source_attach (source, NULL);
            g_source_unref (source);
          }

722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
          return TRUE;
        }
    }

  return FALSE;
}

static gboolean
gui_pdb_dialog_set (Gimp          *gimp,
                    GimpContainer *container,
                    const gchar   *callback_name,
                    const gchar   *object_name,
                    va_list        args)
{
  GimpPdbDialogClass *klass = NULL;

738
  if (gimp_container_get_children_type (container) == GIMP_TYPE_BRUSH)
739
    klass = g_type_class_peek (GIMP_TYPE_BRUSH_SELECT);
740
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_FONT)
741
    klass = g_type_class_peek (GIMP_TYPE_FONT_SELECT);
742
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_GRADIENT)
743
    klass = g_type_class_peek (GIMP_TYPE_GRADIENT_SELECT);
744
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_PALETTE)
745
    klass = g_type_class_peek (GIMP_TYPE_PALETTE_SELECT);
746
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_PATTERN)
747
748
749
750
751
752
753
754
    klass = g_type_class_peek (GIMP_TYPE_PATTERN_SELECT);

  if (klass)
    {
      GimpPdbDialog *dialog;

      dialog = gimp_pdb_dialog_get_by_callback (klass, callback_name);

755
      if (dialog && dialog->select_type == gimp_container_get_children_type (container))
756
757
758
759
760
761
762
        {
          GimpObject *object;

          object = gimp_container_get_child_by_name (container, object_name);

          if (object)
            {
763
              const gchar *prop_name = va_arg (args, const gchar *);
764
765
766
767
768
769
770
771

              gimp_context_set_by_type (dialog->context, dialog->select_type,
                                        object);

              if (prop_name)
                g_object_set_valist (G_OBJECT (dialog), prop_name, args);

              gtk_window_present (GTK_WINDOW (dialog));
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
              return TRUE;
            }
        }
    }

  return FALSE;
}

static gboolean
gui_pdb_dialog_close (Gimp          *gimp,
                      GimpContainer *container,
                      const gchar   *callback_name)
{
  GimpPdbDialogClass *klass = NULL;

788
  if (gimp_container_get_children_type (container) == GIMP_TYPE_BRUSH)
789
    klass = g_type_class_peek (GIMP_TYPE_BRUSH_SELECT);
790
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_FONT)
791
    klass = g_type_class_peek (GIMP_TYPE_FONT_SELECT);
792
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_GRADIENT)
793
    klass = g_type_class_peek (GIMP_TYPE_GRADIENT_SELECT);
794
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_PALETTE)
795
    klass = g_type_class_peek (GIMP_TYPE_PALETTE_SELECT);
796
  else if (gimp_container_get_children_type (container) == GIMP_TYPE_PATTERN)
797
798
799
800
801
802
803
804
    klass = g_type_class_peek (GIMP_TYPE_PATTERN_SELECT);

  if (klass)
    {
      GimpPdbDialog *dialog;

      dialog = gimp_pdb_dialog_get_by_callback (klass, callback_name);

805
      if (dialog && dialog->select_type == gimp_container_get_children_type (container))
806
807
808
809
810
811
812
813
        {
          gtk_widget_destroy (GTK_WIDGET (dialog));
          return TRUE;
        }
    }

  return FALSE;
}
814
815

static gboolean
816
817
818
gui_recent_list_add_file (Gimp        *gimp,
                          GFile       *file,
                          const gchar *mime_type)
819
{
820
821
  GtkRecentData  recent;
  const gchar   *groups[2] = { "Graphics", NULL };
822
823
  gchar         *uri;
  gboolean       success;
824
825

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
826
  g_return_val_if_fail (G_IS_FILE (file), FALSE);
827
828
829

  /* use last part of the URI */
  recent.display_name = NULL;
830

831
  /* no special description */
832
  recent.description  = NULL;
833
834
  recent.mime_type    = (mime_type ?
                         (gchar *) mime_type : "application/octet-stream");
835
  recent.app_name     = "GNU Image Manipulation Program";
836
  recent.app_exec     = GIMP_COMMAND " %u";
837
  recent.groups       = (gchar **) groups;
838
  recent.is_private   = FALSE;
839

840
841
842
843
844
845
846
847
  uri = g_file_get_uri (file);

  success = gtk_recent_manager_add_full (gtk_recent_manager_get_default (),
                                         uri, &recent);

  g_free (uri);

  return success;
848
849
}

850
851
852
853
854
855
856
857
static gint
gui_recent_list_compare (gconstpointer a,
                         gconstpointer b)
{
  return (gtk_recent_info_get_modified ((GtkRecentInfo *) a) -
          gtk_recent_info_get_modified ((GtkRecentInfo *) b));
}

858
859
860
861
862
863
864
865
866
867
868
869
870
static void
gui_recent_list_load (Gimp *gimp)
{
  GList *items;
  GList *list;

  g_return_if_fail (GIMP_IS_GIMP (gimp));

  gimp_container_freeze (gimp->documents);
  gimp_container_clear (gimp->documents);

  items = gtk_recent_manager_get_items (gtk_recent_manager_get_default ());

871
872
  items = g_list_sort (items, gui_recent_list_compare);

873
874
875
876
877
878
879
  for (list = items; list; list = list->next)
    {
      GtkRecentInfo *info = list->data;

      if (gtk_recent_info_has_application (info,
                                           "GNU Image Manipulation Program"))
        {
880
          const gchar *mime_type = gtk_recent_info_get_mime_type (info);
881

882
          if (mime_type &&
883
884
885
              gimp_plug_in_manager_file_procedure_find_by_mime_type (gimp->plug_in_manager,
                                                                     GIMP_FILE_PROCEDURE_GROUP_OPEN,
                                                                     mime_type))
886
887
            {
              GimpImagefile *imagefile;
888
              GFile         *file;
889

890
891
892
              file = g_file_new_for_uri (gtk_recent_info_get_uri (info));
              imagefile = gimp_imagefile_new (gimp, file);
              g_object_unref (file);
893

894
895
896
897
898
              gimp_imagefile_set_mime_type (imagefile, mime_type);

              gimp_container_add (gimp->documents, GIMP_OBJECT (imagefile));
              g_object_unref (imagefile);
            }
899
900
901
902
903
904
905
906
        }

      gtk_recent_info_unref (info);
    }

  g_list_free (items);

  gimp_container_thaw (gimp->documents);
907
}
908

909
910
911
static GMountOperation *
gui_get_mount_operation (Gimp         *gimp,
                         GimpProgress *progress)
912
{
913
  GtkWidget *toplevel = NULL;
914
915
916
917

  if (GTK_IS_WIDGET (progress))
    toplevel = gtk_widget_get_toplevel (GTK_WIDGET (progress));

918
  return gtk_mount_operation_new (GTK_WINDOW (toplevel));
919
}
920
921

static GimpColorProfilePolicy
922
923
924
925
926
927
928
gui_query_profile_policy (Gimp                      *gimp,
                          GimpImage                 *image,
                          GimpContext               *context,
                          GimpColorProfile         **dest_profile,
                          GimpColorRenderingIntent  *intent,
                          gboolean                  *bpc,
                          gboolean                  *dont_ask)
929
930
{
  return color_profile_import_dialog_run (image, context, NULL,
931
932
933
                                          dest_profile,
                                          intent, bpc,
                                          dont_ask);
934
}