gimp.c 35.9 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
Nate Summers's avatar
Nate Summers committed
2
 * Copyright (C) 1995-2002 Spencer Kimball, Peter Mattis, and others
3
 *
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"

Hans Breuer's avatar
updated  
Hans Breuer committed
20 21
#include <string.h> /* strlen */

22
#include <gdk-pixbuf/gdk-pixbuf.h>
23
#include <gegl.h>
24

25
#include "libgimpbase/gimpbase.h"
26
#include "libgimpconfig/gimpconfig.h"
27

28
#include "core-types.h"
29

30 31
#include "config/gimprc.h"

32
#include "gegl/gimp-babl.h"
33

34 35
#include "pdb/gimppdb.h"
#include "pdb/gimp-pdb-compat.h"
36
#include "pdb/internal-procs.h"
37

38
#include "plug-in/gimppluginmanager.h"
39
#include "plug-in/gimppluginmanager-restore.h"
40

41
#include "paint/gimp-paint.h"
42

Michael Natterer's avatar
Michael Natterer committed
43
#include "xcf/xcf.h"
44
#include "file-data/file-data.h"
Michael Natterer's avatar
Michael Natterer committed
45

46
#include "gimp.h"
47
#include "gimp-contexts.h"
48
#include "gimp-data-factories.h"
49
#include "gimp-filter-history.h"
50
#include "gimp-memsize.h"
51
#include "gimp-modules.h"
52
#include "gimp-parasites.h"
53
#include "gimp-templates.h"
54
#include "gimp-units.h"
55
#include "gimp-utils.h"
56
#include "gimpbrush.h"
57
#include "gimpbuffer.h"
Michael Natterer's avatar
Michael Natterer committed
58
#include "gimpcontext.h"
Michael Natterer's avatar
Michael Natterer committed
59
#include "gimpdynamics.h"
60
#include "gimpdocumentlist.h"
61
#include "gimpgradient.h"
Martin Nordholts's avatar
Martin Nordholts committed
62
#include "gimpidtable.h"
63
#include "gimpimage.h"
Michael Natterer's avatar
Michael Natterer committed
64
#include "gimpimagefile.h"
65
#include "gimplist.h"
66
#include "gimpmarshal.h"
67
#include "gimpmybrush.h"
68 69 70
#include "gimppalette.h"
#include "gimpparasitelist.h"
#include "gimppattern.h"
71
#include "gimptemplate.h"
72
#include "gimptoolinfo.h"
73
#include "gimptreeproxy.h"
74

75
#include "gimp-intl.h"
76 77


78 79
enum
{
80 81
  INITIALIZE,
  RESTORE,
82
  EXIT,
83
  CLIPBOARD_CHANGED,
84
  FILTER_HISTORY_CHANGED,
85
  IMAGE_OPENED,
86 87 88
  LAST_SIGNAL
};

89 90 91 92 93
enum
{
  PROP_0,
  PROP_VERBOSE
};
94

95 96 97 98 99 100 101 102 103 104

static void      gimp_constructed          (GObject           *object);
static void      gimp_set_property         (GObject           *object,
                                            guint              property_id,
                                            const GValue      *value,
                                            GParamSpec        *pspec);
static void      gimp_get_property         (GObject           *object,
                                            guint              property_id,
                                            GValue            *value,
                                            GParamSpec        *pspec);
105 106
static void      gimp_dispose              (GObject           *object);
static void      gimp_finalize             (GObject           *object);
107

108 109
static gint64    gimp_get_memsize          (GimpObject        *object,
                                            gint64            *gui_size);
110

111 112 113 114 115 116
static void      gimp_real_initialize      (Gimp              *gimp,
                                            GimpInitStatusFunc status_callback);
static void      gimp_real_restore         (Gimp              *gimp,
                                            GimpInitStatusFunc status_callback);
static gboolean  gimp_real_exit            (Gimp              *gimp,
                                            gboolean           force);
117

118 119 120 121 122 123
static void      gimp_global_config_notify (GObject           *global_config,
                                            GParamSpec        *param_spec,
                                            GObject           *edit_config);
static void      gimp_edit_config_notify   (GObject           *edit_config,
                                            GParamSpec        *param_spec,
                                            GObject           *global_config);
124 125


126
G_DEFINE_TYPE (Gimp, gimp, GIMP_TYPE_OBJECT)
127 128

#define parent_class gimp_parent_class
129

130 131
static guint gimp_signals[LAST_SIGNAL] = { 0, };

132 133 134 135

static void
gimp_class_init (GimpClass *klass)
{
136 137
  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
138

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
  gimp_signals[INITIALIZE] =
    g_signal_new ("initialize",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, initialize),
                  NULL, NULL,
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);

  gimp_signals[RESTORE] =
    g_signal_new ("restore",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, restore),
                  NULL, NULL,
155 156 157
                  gimp_marshal_VOID__POINTER,
                  G_TYPE_NONE, 1,
                  G_TYPE_POINTER);
158

159 160 161 162 163
  gimp_signals[EXIT] =
    g_signal_new ("exit",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, exit),
164
                  g_signal_accumulator_true_handled, NULL,
165 166 167 168
                  gimp_marshal_BOOLEAN__BOOLEAN,
                  G_TYPE_BOOLEAN, 1,
                  G_TYPE_BOOLEAN);

169 170
  gimp_signals[CLIPBOARD_CHANGED] =
    g_signal_new ("clipboard-changed",
171 172
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
173
                  G_STRUCT_OFFSET (GimpClass, clipboard_changed),
174 175 176 177
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);

178 179 180 181 182 183 184 185 186 187
  gimp_signals[FILTER_HISTORY_CHANGED] =
    g_signal_new ("filter-history-changed",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass,
                                   filter_history_changed),
                  NULL, NULL,
                  gimp_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);

188 189 190 191 192 193
  gimp_signals[IMAGE_OPENED] =
    g_signal_new ("image-opened",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpClass, image_opened),
                  NULL, NULL,
194 195
                  gimp_marshal_VOID__OBJECT,
                  G_TYPE_NONE, 1, G_TYPE_FILE);
196

197 198 199
  object_class->constructed      = gimp_constructed;
  object_class->set_property     = gimp_set_property;
  object_class->get_property     = gimp_get_property;
200 201 202 203
  object_class->dispose          = gimp_dispose;
  object_class->finalize         = gimp_finalize;

  gimp_object_class->get_memsize = gimp_get_memsize;
204

205 206
  klass->initialize              = gimp_real_initialize;
  klass->restore                 = gimp_real_restore;
207
  klass->exit                    = gimp_real_exit;
208
  klass->clipboard_changed       = NULL;
209 210 211 212 213 214

  g_object_class_install_property (object_class, PROP_VERBOSE,
                                   g_param_spec_boolean ("verbose", NULL, NULL,
                                                         FALSE,
                                                         GIMP_PARAM_READWRITE |
                                                         G_PARAM_CONSTRUCT_ONLY));
215 216 217 218 219
}

static void
gimp_init (Gimp *gimp)
{
220 221 222
  gimp->be_verbose       = FALSE;
  gimp->no_data          = FALSE;
  gimp->no_interface     = FALSE;
223
  gimp->show_gui         = TRUE;
224
  gimp->use_shm          = FALSE;
225
  gimp->use_cpu_accel    = TRUE;
226
  gimp->message_handler  = GIMP_CONSOLE;
227
  gimp->show_playground  = FALSE;
228
  gimp->stack_trace_mode = GIMP_STACK_TRACE_NEVER;
229
  gimp->pdb_compat_mode  = GIMP_PDB_COMPAT_OFF;
230

231
  gimp_gui_init (gimp);
232

233
  gimp->parasites = gimp_parasite_list_new ();
234

235 236
  gimp_units_init (gimp);

237
  gimp->images = gimp_list_new_weak (GIMP_TYPE_IMAGE, FALSE);
238
  gimp_object_set_static_name (GIMP_OBJECT (gimp->images), "images");
239

240
  gimp->next_guide_ID        = 1;
241
  gimp->next_sample_point_ID = 1;
Martin Nordholts's avatar
Martin Nordholts committed
242
  gimp->image_table          = gimp_id_table_new ();
243
  gimp->item_table           = gimp_id_table_new ();
244

245 246 247 248 249
  gimp->displays = g_object_new (GIMP_TYPE_LIST,
                                 "children-type", GIMP_TYPE_OBJECT,
                                 "policy",        GIMP_CONTAINER_POLICY_WEAK,
                                 "append",        TRUE,
                                 NULL);
250
  gimp_object_set_static_name (GIMP_OBJECT (gimp->displays), "displays");
251
  gimp->next_display_ID = 1;
252

253
  gimp->named_buffers = gimp_list_new (GIMP_TYPE_BUFFER, TRUE);
254 255
  gimp_object_set_static_name (GIMP_OBJECT (gimp->named_buffers),
                               "named buffers");
256

257 258
  gimp_data_factories_init (gimp);

259 260 261 262
  gimp->tool_info_list = g_object_new (GIMP_TYPE_LIST,
                                       "children-type", GIMP_TYPE_TOOL_INFO,
                                       "append",        TRUE,
                                       NULL);
263 264
  gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_info_list),
                               "tool infos");
265

266 267 268 269 270 271 272
  gimp->tool_item_list = g_object_new (GIMP_TYPE_LIST,
                                       "children-type", GIMP_TYPE_TOOL_ITEM,
                                       "append",        TRUE,
                                       NULL);
  gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_item_list),
                               "tool items");

273 274 275 276 277
  gimp->tool_item_ui_list = gimp_tree_proxy_new_for_container (
    gimp->tool_item_list);
  gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_item_ui_list),
                               "ui tool items");

278 279
  gimp->documents = gimp_document_list_new (gimp);

280
  gimp->templates = gimp_list_new (GIMP_TYPE_TEMPLATE, TRUE);
281
  gimp_object_set_static_name (GIMP_OBJECT (gimp->templates), "templates");
282 283
}

284 285 286 287 288 289 290 291 292
static void
gimp_constructed (GObject *object)
{
  Gimp *gimp = GIMP (object);

  G_OBJECT_CLASS (parent_class)->constructed (object);

  gimp_modules_init (gimp);

293 294
  gimp_paint_init (gimp);

295 296 297 298
  gimp->plug_in_manager = gimp_plug_in_manager_new (gimp);
  gimp->pdb             = gimp_pdb_new (gimp);

  xcf_init (gimp);
299
  file_data_init (gimp);
300

301 302
  /*  create user and default context  */
  gimp_contexts_init (gimp);
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
}

static void
gimp_set_property (GObject           *object,
                   guint              property_id,
                   const GValue      *value,
                   GParamSpec        *pspec)
{
  Gimp *gimp = GIMP (object);

  switch (property_id)
    {
    case PROP_VERBOSE:
      gimp->be_verbose = g_value_get_boolean (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
gimp_get_property (GObject    *object,
                   guint       property_id,
                   GValue     *value,
                   GParamSpec *pspec)
{
  Gimp *gimp = GIMP (object);

  switch (property_id)
    {
    case PROP_VERBOSE:
      g_value_set_boolean (value, gimp->be_verbose);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

345
static void
346 347
gimp_dispose (GObject *object)
{
348
  Gimp *gimp = GIMP (object);
349

350 351 352
  if (gimp->be_verbose)
    g_print ("EXIT: %s\n", G_STRFUNC);

353
  gimp_data_factories_clear (gimp);
Alexia Death's avatar
Alexia Death committed
354

355 356
  gimp_filter_history_clear (gimp);

357 358
  g_clear_object (&gimp->edit_config);
  g_clear_object (&gimp->config);
359 360 361

  gimp_contexts_exit (gimp);

362
  g_clear_object (&gimp->image_new_last_template);
363

364 365 366 367 368 369
  G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
gimp_finalize (GObject *object)
{
370 371
  Gimp  *gimp      = GIMP (object);
  GList *standards = NULL;
372

373
  if (gimp->be_verbose)
374
    g_print ("EXIT: %s\n", G_STRFUNC);
375

376 377 378 379
  standards = g_list_prepend (standards,
                              gimp_brush_get_standard (gimp->user_context));
  standards = g_list_prepend (standards,
                              gimp_dynamics_get_standard (gimp->user_context));
380 381
  standards = g_list_prepend (standards,
                              gimp_mybrush_get_standard (gimp->user_context));
382 383 384 385 386 387 388
  standards = g_list_prepend (standards,
                              gimp_pattern_get_standard (gimp->user_context));
  standards = g_list_prepend (standards,
                              gimp_gradient_get_standard (gimp->user_context));
  standards = g_list_prepend (standards,
                              gimp_palette_get_standard (gimp->user_context));

389 390
  g_clear_object (&gimp->templates);
  g_clear_object (&gimp->documents);
Michael Natterer's avatar
Michael Natterer committed
391

392 393
  gimp_tool_info_set_standard (gimp, NULL);

394 395 396
  g_clear_object (&gimp->tool_item_list);
  g_clear_object (&gimp->tool_item_ui_list);

397 398
  if (gimp->tool_info_list)
    {
399 400
      gimp_container_foreach (gimp->tool_info_list,
                              (GFunc) g_object_run_dispose, NULL);
401
      g_clear_object (&gimp->tool_info_list);
402 403
    }

404
  file_data_exit (gimp);
Michael Natterer's avatar
Michael Natterer committed
405 406
  xcf_exit (gimp);

407
  g_clear_object (&gimp->pdb);
Michael Natterer's avatar
Michael Natterer committed
408

409
  gimp_data_factories_exit (gimp);
410

411 412 413 414 415 416 417 418
  g_clear_object (&gimp->named_buffers);
  g_clear_object (&gimp->clipboard_buffer);
  g_clear_object (&gimp->clipboard_image);
  g_clear_object (&gimp->displays);
  g_clear_object (&gimp->item_table);
  g_clear_object (&gimp->image_table);
  g_clear_object (&gimp->images);
  g_clear_object (&gimp->plug_in_manager);
419

420
  if (gimp->module_db)
Michael Natterer's avatar
Michael Natterer committed
421 422
    gimp_modules_exit (gimp);

423
  gimp_paint_exit (gimp);
424

425 426
  g_clear_object (&gimp->parasites);
  g_clear_object (&gimp->default_folder);
427

428
  g_clear_pointer (&gimp->session_name, g_free);
429

Sven Neumann's avatar
Sven Neumann committed
430 431
  if (gimp->context_list)
    {
432 433 434 435 436 437 438 439
      GList *list;

      g_warning ("%s: list of contexts not empty upon exit (%d contexts left)\n",
                 G_STRFUNC, g_list_length (gimp->context_list));

      for (list = gimp->context_list; list; list = g_list_next (list))
        g_printerr ("stale context: %s\n", gimp_object_get_name (list->data));

Sven Neumann's avatar
Sven Neumann committed
440 441 442 443
      g_list_free (gimp->context_list);
      gimp->context_list = NULL;
    }

444 445 446
  g_list_foreach (standards, (GFunc) g_object_unref, NULL);
  g_list_free (standards);

447
  gimp_units_exit (gimp);
448

449
  G_OBJECT_CLASS (parent_class)->finalize (object);
450 451
}

452
static gint64
453
gimp_get_memsize (GimpObject *object,
454
                  gint64     *gui_size)
455
{
456
  Gimp   *gimp    = GIMP (object);
457
  gint64  memsize = 0;
458

459
  memsize += gimp_g_list_get_memsize (gimp->user_units, 0 /* FIXME */);
460

461 462
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->parasites),
                                      gui_size);
463

464 465 466
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->paint_info_list),
                                      gui_size);

467
  memsize += gimp_g_object_get_memsize (G_OBJECT (gimp->module_db));
468 469
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->plug_in_manager),
                                      gui_size);
470

471 472 473 474 475
  memsize += gimp_g_list_get_memsize_foreach (gimp->filter_history,
                                              (GimpMemsizeFunc)
                                              gimp_object_get_memsize,
                                              gui_size);

Martin Nordholts's avatar
Martin Nordholts committed
476 477
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->image_table), 0);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->item_table),  0);
478

479
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->displays), gui_size);
480

481 482
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->clipboard_image),
                                      gui_size);
483
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->clipboard_buffer),
484
                                      gui_size);
485 486
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->named_buffers),
                                      gui_size);
487

488
  memsize += gimp_data_factories_get_memsize (gimp, gui_size);
489

490
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->pdb), gui_size);
491

492 493 494 495 496 497 498 499 500 501
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_info_list),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->standard_tool_info),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->documents),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->templates),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->image_new_last_template),
                                      gui_size);
502

503
  memsize += gimp_g_list_get_memsize (gimp->context_list, 0);
504

505 506 507 508
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->default_context),
                                      gui_size);
  memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->user_context),
                                      gui_size);
509

510 511
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
                                                                  gui_size);
512 513
}

514 515 516 517 518
static void
gimp_real_initialize (Gimp               *gimp,
                      GimpInitStatusFunc  status_callback)
{
  if (gimp->be_verbose)
519
    g_print ("INIT: %s\n", G_STRFUNC);
520

521 522
  status_callback (_("Initialization"), NULL, 0.0);

523
  /*  set the last values used to default values  */
524 525
  gimp->image_new_last_template =
    gimp_config_duplicate (GIMP_CONFIG (gimp->config->default_image));
526

527 528
  /*  add data objects that need the user context  */
  gimp_data_factories_add_builtin (gimp);
529

530
  /*  register all internal procedures  */
Sven Neumann's avatar
Sven Neumann committed
531
  status_callback (NULL, _("Internal Procedures"), 0.2);
532 533
  internal_procs_init (gimp->pdb);
  gimp_pdb_compat_procs_register (gimp->pdb, gimp->pdb_compat_mode);
534

535
  gimp_plug_in_manager_initialize (gimp->plug_in_manager, status_callback);
536 537

  status_callback (NULL, "", 1.0);
538 539 540 541
}

static void
gimp_real_restore (Gimp               *gimp,
542
                   GimpInitStatusFunc  status_callback)
543 544
{
  if (gimp->be_verbose)
545
    g_print ("INIT: %s\n", G_STRFUNC);
546

547 548
  gimp_plug_in_manager_restore (gimp->plug_in_manager,
                                gimp_get_user_context (gimp), status_callback);
549

550 551 552 553
  /*  initialize babl fishes  */
  status_callback (_("Initialization"), "Babl Fishes", 0.0);
  gimp_babl_init_fishes (status_callback);

554
  gimp->restored = TRUE;
555 556
}

557 558
static gboolean
gimp_real_exit (Gimp     *gimp,
559
                gboolean  force)
560
{
561
  if (gimp->be_verbose)
562
    g_print ("EXIT: %s\n", G_STRFUNC);
563

564
  gimp_plug_in_manager_exit (gimp->plug_in_manager);
565
  gimp_modules_unload (gimp);
566

567
  gimp_data_factories_save (gimp);
Alexia Death's avatar
Alexia Death committed
568

569
  gimp_templates_save (gimp);
570 571 572 573 574 575
  gimp_parasiterc_save (gimp);
  gimp_unitrc_save (gimp);

  return FALSE; /* continue exiting */
}

576
Gimp *
577
gimp_new (const gchar       *name,
578
          const gchar       *session_name,
579
          GFile             *default_folder,
580
          gboolean           be_verbose,
Michael Natterer's avatar
Michael Natterer committed
581
          gboolean           no_data,
582
          gboolean           no_fonts,
Michael Natterer's avatar
Michael Natterer committed
583
          gboolean           no_interface,
584
          gboolean           use_shm,
585
          gboolean           use_cpu_accel,
586
          gboolean           console_messages,
587
          gboolean           show_playground,
588
          gboolean           show_debug_menu,
589 590
          GimpStackTraceMode stack_trace_mode,
          GimpPDBCompatMode  pdb_compat_mode)
591 592 593
{
  Gimp *gimp;

594 595
  g_return_val_if_fail (name != NULL, NULL);

596
  gimp = g_object_new (GIMP_TYPE_GIMP,
597 598
                       "name",    name,
                       "verbose", be_verbose ? TRUE : FALSE,
599
                       NULL);
600

601 602 603
  if (default_folder)
    gimp->default_folder = g_object_ref (default_folder);

604
  gimp->session_name     = g_strdup (session_name);
605
  gimp->no_data          = no_data          ? TRUE : FALSE;
606
  gimp->no_fonts         = no_fonts         ? TRUE : FALSE;
607 608
  gimp->no_interface     = no_interface     ? TRUE : FALSE;
  gimp->use_shm          = use_shm          ? TRUE : FALSE;
609
  gimp->use_cpu_accel    = use_cpu_accel    ? TRUE : FALSE;
610
  gimp->console_messages = console_messages ? TRUE : FALSE;
611
  gimp->show_playground  = show_playground  ? TRUE : FALSE;
612
  gimp->show_debug_menu  = show_debug_menu  ? TRUE : FALSE;
Michael Natterer's avatar
Michael Natterer committed
613
  gimp->stack_trace_mode = stack_trace_mode;
614
  gimp->pdb_compat_mode  = pdb_compat_mode;
Michael Natterer's avatar
Michael Natterer committed
615

616 617 618
  return gimp;
}

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
/**
 * gimp_set_show_gui:
 * @gimp:
 * @show:
 *
 * Test cases that tests the UI typically don't want any windows to be
 * presented during the test run. Allow them to set this.
 **/
void
gimp_set_show_gui (Gimp     *gimp,
                   gboolean  show_gui)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));

  gimp->show_gui = show_gui;
}

/**
 * gimp_get_show_gui:
 * @gimp:
 *
 * Returns: %TRUE if the GUI should be shown, %FALSE otherwise.
 **/
gboolean
gimp_get_show_gui (Gimp *gimp)
{
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);

  return gimp->show_gui;
}

650 651 652 653 654
static void
gimp_global_config_notify (GObject    *global_config,
                           GParamSpec *param_spec,
                           GObject    *edit_config)
{
655 656
  GValue global_value = G_VALUE_INIT;
  GValue edit_value   = G_VALUE_INIT;
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685

  g_value_init (&global_value, param_spec->value_type);
  g_value_init (&edit_value,   param_spec->value_type);

  g_object_get_property (global_config, param_spec->name, &global_value);
  g_object_get_property (edit_config,   param_spec->name, &edit_value);

  if (g_param_values_cmp (param_spec, &global_value, &edit_value))
    {
      g_signal_handlers_block_by_func (edit_config,
                                       gimp_edit_config_notify,
                                       global_config);

      g_object_set_property (edit_config, param_spec->name, &global_value);

      g_signal_handlers_unblock_by_func (edit_config,
                                         gimp_edit_config_notify,
                                         global_config);
    }

  g_value_unset (&global_value);
  g_value_unset (&edit_value);
}

static void
gimp_edit_config_notify (GObject    *edit_config,
                         GParamSpec *param_spec,
                         GObject    *global_config)
{
686 687
  GValue edit_value   = G_VALUE_INIT;
  GValue global_value = G_VALUE_INIT;
688 689 690 691 692 693 694 695 696

  g_value_init (&edit_value,   param_spec->value_type);
  g_value_init (&global_value, param_spec->value_type);

  g_object_get_property (edit_config,   param_spec->name, &edit_value);
  g_object_get_property (global_config, param_spec->name, &global_value);

  if (g_param_values_cmp (param_spec, &edit_value, &global_value))
    {
697
      if (param_spec->flags & GIMP_CONFIG_PARAM_RESTART)
698
        {
Sven Neumann's avatar
Sven Neumann committed
699
#ifdef GIMP_CONFIG_DEBUG
700 701 702
          g_print ("NOT Applying edit_config change of '%s' to global_config "
                   "because it needs restart\n",
                   param_spec->name);
Sven Neumann's avatar
Sven Neumann committed
703
#endif
704 705 706
        }
      else
        {
Sven Neumann's avatar
Sven Neumann committed
707
#ifdef GIMP_CONFIG_DEBUG
708 709
          g_print ("Applying edit_config change of '%s' to global_config\n",
                   param_spec->name);
Sven Neumann's avatar
Sven Neumann committed
710
#endif
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
          g_signal_handlers_block_by_func (global_config,
                                           gimp_global_config_notify,
                                           edit_config);

          g_object_set_property (global_config, param_spec->name, &edit_value);

          g_signal_handlers_unblock_by_func (global_config,
                                             gimp_global_config_notify,
                                             edit_config);
        }
    }

  g_value_unset (&edit_value);
  g_value_unset (&global_value);
}

void
728 729 730
gimp_load_config (Gimp  *gimp,
                  GFile *alternate_system_gimprc,
                  GFile *alternate_gimprc)
731
{
732 733
  GimpRc *gimprc;

734
  g_return_if_fail (GIMP_IS_GIMP (gimp));
735 736 737 738
  g_return_if_fail (alternate_system_gimprc == NULL ||
                    G_IS_FILE (alternate_system_gimprc));
  g_return_if_fail (alternate_gimprc == NULL ||
                    G_IS_FILE (alternate_gimprc));
739 740 741
  g_return_if_fail (gimp->config == NULL);
  g_return_if_fail (gimp->edit_config == NULL);

742
  if (gimp->be_verbose)
743
    g_print ("INIT: %s\n", G_STRFUNC);
744 745 746 747 748 749

  /*  this needs to be done before gimprc loading because gimprc can
   *  use user defined units
   */
  gimp_unitrc_load (gimp);

750 751
  gimprc = gimp_rc_new (G_OBJECT (gimp),
                        alternate_system_gimprc,
752 753 754 755
                        alternate_gimprc,
                        gimp->be_verbose);

  gimp->config = GIMP_CORE_CONFIG (gimprc);
756

757
  gimp->edit_config = gimp_config_duplicate (GIMP_CONFIG (gimp->config));
758 759 760 761 762 763 764

  g_signal_connect_object (gimp->config, "notify",
                           G_CALLBACK (gimp_global_config_notify),
                           gimp->edit_config, 0);
  g_signal_connect_object (gimp->edit_config, "notify",
                           G_CALLBACK (gimp_edit_config_notify),
                           gimp->config, 0);
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792

  if (! gimp->show_playground)
    {
      gboolean    use_opencl;
      gboolean    use_npd_tool;
      gboolean    use_seamless_clone_tool;

      /* Playground preferences is shown by default for unstable
       * versions and if the associated CLI option was set. Additionally
       * we want to show it if any of the playground options had been
       * enabled. Otherwise you might end up getting blocked with a
       * playground feature and forget where you can even disable it.
       *
       * Also we check this once at start when loading config, and not
       * inside preferences-dialog.c because we don't want to end up
       * with inconsistent behavior where you open once the Preferences,
       * deactivate features, then back to preferences and the tab is
       * gone.
       */

      g_object_get (gimp->edit_config,
                    "use-opencl",                     &use_opencl,
                    "playground-npd-tool",            &use_npd_tool,
                    "playground-seamless-clone-tool", &use_seamless_clone_tool,
                    NULL);
      if (use_opencl || use_npd_tool || use_seamless_clone_tool)
        gimp->show_playground = TRUE;
    }
793 794
}

795
void
796 797
gimp_initialize (Gimp               *gimp,
                 GimpInitStatusFunc  status_callback)
798 799
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));
800
  g_return_if_fail (status_callback != NULL);
801
  g_return_if_fail (GIMP_IS_CORE_CONFIG (gimp->config));
802

803
  if (gimp->be_verbose)
804
    g_print ("INIT: %s\n", G_STRFUNC);
805

806
  g_signal_emit (gimp, gimp_signals[INITIALIZE], 0, status_callback);
807 808
}

809 810 811 812 813 814 815 816 817
/**
 * gimp_restore:
 * @gimp: a #Gimp object
 * @error: a #GError for uncessful loading.
 *
 * This function always succeeds. If present, @error may be filled for
 * possible feedback on data which failed to load. It doesn't imply any
 * fatale error.
 **/
818
void
819 820 821
gimp_restore (Gimp                *gimp,
              GimpInitStatusFunc   status_callback,
              GError             **error)
822 823
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));
824
  g_return_if_fail (status_callback != NULL);
825

826
  if (gimp->be_verbose)
827
    g_print ("INIT: %s\n", G_STRFUNC);
828

829
  /*  initialize  the global parasite table  */
830
  status_callback (_("Looking for data files"), _("Parasites"), 0.0);
831
  gimp_parasiterc_load (gimp);
832

833 834
  /*  initialize the lists of gimp brushes, dynamics, patterns etc.  */
  gimp_data_factories_load (gimp, status_callback);
Alexia Death's avatar
Alexia Death committed
835

836
  /*  initialize the template list  */
837
  status_callback (NULL, _("Templates"), 0.8);
838 839
  gimp_templates_load (gimp);

840
  /*  initialize the module list  */
841
  status_callback (NULL, _("Modules"), 0.9);
Michael Natterer's avatar
Michael Natterer committed
842
  gimp_modules_load (gimp);
843

844
  g_signal_emit (gimp, gimp_signals[RESTORE], 0, status_callback);
845 846

  /* when done, make sure everything is clean, to clean out dirty
847
   * states from data objects which reference each other and got
848 849
   * dirtied by loading the referenced object
   */
850
  gimp_data_factories_data_clean (gimp);
851
}
852

853 854 855 856 857 858 859 860 861 862 863 864 865 866
/**
 * gimp_is_restored:
 * @gimp: a #Gimp object
 *
 * Return value: %TRUE if GIMP is completely started, %FALSE otherwise.
 **/
gboolean
gimp_is_restored (Gimp *gimp)
{
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);

  return gimp->restored;
}

867 868 869 870 871 872 873 874
/**
 * gimp_exit:
 * @gimp: a #Gimp object
 * @force: whether to force the application to quit
 *
 * Exit this GIMP session. Unless @force is %TRUE, the user is queried
 * whether unsaved images should be saved and can cancel the operation.
 **/
875
void
876
gimp_exit (Gimp     *gimp,
877
           gboolean  force)
878
{
879 880
  gboolean  handled;
  GList    *image_iter;
881

882 883
  g_return_if_fail (GIMP_IS_GIMP (gimp));

884
  if (gimp->be_verbose)
885
    g_print ("EXIT: %s\n", G_STRFUNC);
886

887
  g_signal_emit (gimp, gimp_signals[EXIT], 0,
888
                 force ? TRUE : FALSE,
889
                 &handled);
890

891 892 893
  if (handled)
    return;

894 895 896 897 898 899 900 901 902 903 904
  /* Get rid of images without display. We do this *after* handling the
   * usual exit callbacks, because the things that are torn down there
   * might have references to these images (for instance GimpActions
   * in the UI manager).
   */
  while ((image_iter = gimp_get_image_iter (gimp)))
    {
      GimpImage *image = image_iter->data;

      g_object_unref (image);
    }
905 906
}

907 908 909 910 911
GList *
gimp_get_image_iter (Gimp *gimp)
{
  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);

912
  return GIMP_LIST (gimp->images)->queue->head;
Michael Natterer's avatar