session.c 14.3 KB
Newer Older
1
/* GIMP - The GNU Image Manipulation Program
2 3
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
4 5 6
 * Session-managment stuff
 * Copyright (C) 1998 Sven Neumann <sven@gimp.org>
 *
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 11 12 13 14 15 16 17
 * (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
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 20
 */

21 22
#include "config.h"

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

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

29
#include "gui-types.h"
Sven Neumann's avatar
Sven Neumann committed
30

31
#include "config/gimpconfig-file.h"
32 33
#include "config/gimpguiconfig.h"

34
#include "core/gimp.h"
35
#include "core/gimperror.h"
36

37
#include "widgets/gimpdialogfactory.h"
38
#include "widgets/gimpsessioninfo.h"
39
#include "widgets/gimpwidgets-utils.h"
40

41 42
#include "dialogs/dialogs.h"

43
#include "session.h"
44
#include "gimp-log.h"
45

46
#include "gimp-intl.h"
47 48 49 50 51


enum
{
  SESSION_INFO = 1,
52 53
  HIDE_DOCKS,
  SINGLE_WINDOW_MODE,
54
  SHOW_TABS,
55
  TABS_POSITION,
56
  LAST_TIP_SHOWN
57
};
58

59

60
static GFile * session_file (Gimp *gimp);
61 62


63 64 65 66 67
/*  private variables  */

static gboolean   sessionrc_deleted = FALSE;


68
/*  public functions  */
69

70
void
71
session_init (Gimp *gimp)
72
{
73
  GFile      *file;
74 75 76
  GScanner   *scanner;
  GTokenType  token;
  GError     *error = NULL;
77

78 79
  g_return_if_fail (GIMP_IS_GIMP (gimp));

80
  file = session_file (gimp);
81

82
  scanner = gimp_scanner_new_gfile (file, &error);
83

84 85 86
  if (! scanner && error->code == GIMP_CONFIG_ERROR_OPEN_ENOENT)
    {
      g_clear_error (&error);
87
      g_object_unref (file);
88

89
      file = gimp_sysconf_directory_file ("sessionrc", NULL);
90 91

      scanner = gimp_scanner_new_gfile (file, NULL);
92 93
    }

94
  if (! scanner)
95
    {
96
      g_clear_error (&error);
97
      g_object_unref (file);
98
      return;
99 100
    }

101
  if (gimp->be_verbose)
102
    g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
103

104 105
  g_scanner_scope_add_symbol (scanner, 0, "session-info",
                              GINT_TO_POINTER (SESSION_INFO));
106 107 108 109
  g_scanner_scope_add_symbol (scanner, 0,  "hide-docks",
                              GINT_TO_POINTER (HIDE_DOCKS));
  g_scanner_scope_add_symbol (scanner, 0,  "single-window-mode",
                              GINT_TO_POINTER (SINGLE_WINDOW_MODE));
110 111
  g_scanner_scope_add_symbol (scanner, 0,  "show-tabs",
                              GINT_TO_POINTER (SHOW_TABS));
112 113
  g_scanner_scope_add_symbol (scanner, 0,  "tabs-position",
                              GINT_TO_POINTER (TABS_POSITION));
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
  g_scanner_scope_add_symbol (scanner, 0,  "last-tip-shown",
                              GINT_TO_POINTER (LAST_TIP_SHOWN));

  token = G_TOKEN_LEFT_PAREN;

  while (g_scanner_peek_next_token (scanner) == token)
    {
      token = g_scanner_get_next_token (scanner);

      switch (token)
        {
        case G_TOKEN_LEFT_PAREN:
          token = G_TOKEN_SYMBOL;
          break;

        case G_TOKEN_SYMBOL:
          if (scanner->value.v_symbol == GINT_TO_POINTER (SESSION_INFO))
            {
132 133 134 135 136
              GimpDialogFactory      *factory      = NULL;
              GimpSessionInfo        *info         = NULL;
              gchar                  *factory_name = NULL;
              gchar                  *entry_name   = NULL;
              GimpDialogFactoryEntry *entry        = NULL;
137

138 139 140 141 142
              token = G_TOKEN_STRING;

              if (! gimp_scanner_parse_string (scanner, &factory_name))
                break;

143
              /* In versions <= GIMP 2.6 there was a "toolbox", a
144
               * "dock", a "display" and a "toplevel" factory. These
145
               * are now merged to a single gimp_dialog_factory_get_singleton (). We
146
               * need the legacy name though, so keep it around.
147
               */
148
              factory = gimp_dialog_factory_get_singleton ();
149 150 151

              info = gimp_session_info_new ();

152 153
              /* GIMP 2.6 has the entry name as part of the
               * session-info header, so try to get it
154
               */
155 156
              gimp_scanner_parse_string (scanner, &entry_name);
              if (entry_name)
157
                {
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
                  /* Previously, GimpDock was a toplevel. That is why
                   * versions <= GIMP 2.6 has "dock" as the entry name. We
                   * want "dock" to be interpreted as 'dock window'
                   * however so have some special-casing for that. When
                   * the entry name is "dock" the factory name is either
                   * "dock" or "toolbox".
                   */
                  if (strcmp (entry_name, "dock") == 0)
                    {
                      entry =
                        gimp_dialog_factory_find_entry (factory,
                                                        (strcmp (factory_name, "toolbox") == 0 ?
                                                         "gimp-toolbox-window" :
                                                         "gimp-dock-window"));
                    }
                  else
                    {
                      entry = gimp_dialog_factory_find_entry (factory,
                                                              entry_name);
                    }
178 179
                }

180 181
              /* We're done with these now */
              g_free (factory_name);
182 183
              g_free (entry_name);

184 185 186
              /* We can get the factory entry either now (the GIMP <=
               * 2.6 way), or when we deserialize (the GIMP 2.8 way)
               */
187 188 189 190 191
              if (entry)
                {
                  gimp_session_info_set_factory_entry (info, entry);
                }

192
              /* Always try to deserialize */
193
              if (gimp_config_deserialize (GIMP_CONFIG (info), scanner, 1, NULL))
194
                {
195 196 197 198
                  /* Make sure we got a factory entry either the 2.6
                   * or 2.8 way
                   */
                  if (gimp_session_info_get_factory_entry (info))
199
                    {
200 201 202 203
                      GIMP_LOG (DIALOG_FACTORY,
                                "successfully parsed and added session info %p",
                                info);

204
                      gimp_dialog_factory_add_session_info (factory, info);
205 206 207
                    }
                  else
                    {
208 209 210
                      GIMP_LOG (DIALOG_FACTORY,
                                "failed to parse session info %p, not adding",
                                info);
211
                    }
212 213

                  g_object_unref (info);
214 215 216 217
                }
              else
                {
                  g_object_unref (info);
218 219 220 221 222 223

                  /* set token to left paren to we won't set another
                   * error below, gimp_config_deserialize() already did
                   */
                  token = G_TOKEN_LEFT_PAREN;
                  goto error;
224
                }
225
            }
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
          else if (scanner->value.v_symbol == GINT_TO_POINTER (HIDE_DOCKS))
            {
              gboolean hide_docks;

              token = G_TOKEN_IDENTIFIER;

              if (! gimp_scanner_parse_boolean (scanner, &hide_docks))
                break;

              g_object_set (gimp->config,
                            "hide-docks", hide_docks,
                            NULL);
            }
          else if (scanner->value.v_symbol == GINT_TO_POINTER (SINGLE_WINDOW_MODE))
            {
              gboolean single_window_mode;

              token = G_TOKEN_IDENTIFIER;

              if (! gimp_scanner_parse_boolean (scanner, &single_window_mode))
                break;

              g_object_set (gimp->config,
                            "single-window-mode", single_window_mode,
                            NULL);
            }
252 253 254 255 256 257 258 259 260 261 262 263 264
          else if (scanner->value.v_symbol == GINT_TO_POINTER (SHOW_TABS))
          {
            gboolean show_tabs;

            token = G_TOKEN_IDENTIFIER;

            if (! gimp_scanner_parse_boolean (scanner, &show_tabs))
              break;

            g_object_set (gimp->config,
                          "show-tabs", show_tabs,
                          NULL);
          }
265 266 267 268 269 270 271 272 273 274 275 276 277
          else if (scanner->value.v_symbol == GINT_TO_POINTER (TABS_POSITION))
            {
              gint tabs_position;

              token = G_TOKEN_INT;

              if (! gimp_scanner_parse_int (scanner, &tabs_position))
                break;

              g_object_set (gimp->config,
                            "tabs-position", tabs_position,
                            NULL);
            }
278 279
          else if (scanner->value.v_symbol == GINT_TO_POINTER (LAST_TIP_SHOWN))
            {
280
              gint last_tip_shown;
281

282 283
              token = G_TOKEN_INT;

284
              if (! gimp_scanner_parse_int (scanner, &last_tip_shown))
285
                break;
286 287 288 289

              g_object_set (gimp->config,
                            "last-tip-shown", last_tip_shown,
                            NULL);
290 291 292 293 294 295 296 297 298 299 300 301 302
            }
          token = G_TOKEN_RIGHT_PAREN;
          break;

        case G_TOKEN_RIGHT_PAREN:
          token = G_TOKEN_LEFT_PAREN;
          break;

        default: /* do nothing */
          break;
        }
    }

303 304
 error:

305 306 307 308 309 310 311 312 313
  if (token != G_TOKEN_LEFT_PAREN)
    {
      g_scanner_get_next_token (scanner);
      g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
                             _("fatal parse error"), TRUE);
    }

  if (error)
    {
314
      gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
315
      g_clear_error (&error);
316

317
      gimp_config_file_backup_on_error (file, "sessionrc", NULL);
318 319 320
    }

  gimp_scanner_destroy (scanner);
321
  g_object_unref (file);
322 323

  dialogs_load_recent_docks (gimp);
324
}
325

326 327 328 329 330 331
void
session_exit (Gimp *gimp)
{
  g_return_if_fail (GIMP_IS_GIMP (gimp));
}

332
void
333 334
session_restore (Gimp       *gimp,
                 GdkMonitor *monitor)
335
{
336
  g_return_if_fail (GIMP_IS_GIMP (gimp));
337
  g_return_if_fail (GDK_IS_MONITOR (monitor));
338 339

  gimp_dialog_factory_restore (gimp_dialog_factory_get_singleton (),
340
                               monitor);
341 342 343 344 345 346 347 348 349

  /* make sure GimpImageWindow acts upon hide-docks at the right time,
   * see bug #678043.
   */
  if (GIMP_GUI_CONFIG (gimp->config)->single_window_mode &&
      GIMP_GUI_CONFIG (gimp->config)->hide_docks)
    {
      g_object_notify (G_OBJECT (gimp->config), "hide-docks");
    }
350 351 352
}

void
353 354
session_save (Gimp     *gimp,
              gboolean  always_save)
355
{
356
  GimpConfigWriter *writer;
357
  GFile            *file;
358
  GError           *error = NULL;
359

360 361
  g_return_if_fail (GIMP_IS_GIMP (gimp));

362 363 364
  if (sessionrc_deleted && ! always_save)
    return;

365
  file = session_file (gimp);
366

367
  if (gimp->be_verbose)
368
    g_print ("Writing '%s'\n", gimp_file_get_utf8_name (file));
369

370
  writer =
371 372 373 374 375 376 377 378 379 380 381 382 383
    gimp_config_writer_new_gfile (file,
                                  TRUE,
                                  "GIMP sessionrc\n\n"
                                  "This file takes session-specific info "
                                  "(that is info, you want to keep between "
                                  "two GIMP sessions).  You are not supposed "
                                  "to edit it manually, but of course you "
                                  "can do.  The sessionrc will be entirely "
                                  "rewritten every time you quit GIMP.  "
                                  "If this file isn't found, defaults are "
                                  "used.",
                                  NULL);
  g_object_unref (file);
384 385

  if (!writer)
386
    return;
387

388
  gimp_dialog_factory_save (gimp_dialog_factory_get_singleton (), writer);
389
  gimp_config_writer_linefeed (writer);
390

391 392 393 394 395 396 397 398 399 400 401 402
  gimp_config_writer_open (writer, "hide-docks");
  gimp_config_writer_identifier (writer,
                                 GIMP_GUI_CONFIG (gimp->config)->hide_docks ?
                                 "yes" : "no");
  gimp_config_writer_close (writer);

  gimp_config_writer_open (writer, "single-window-mode");
  gimp_config_writer_identifier (writer,
                                 GIMP_GUI_CONFIG (gimp->config)->single_window_mode ?
                                 "yes" : "no");
  gimp_config_writer_close (writer);

403 404 405 406 407 408
  gimp_config_writer_open (writer, "show-tabs");
  gimp_config_writer_printf (writer,
                             GIMP_GUI_CONFIG (gimp->config)->show_tabs ?
                             "yes" : "no");
  gimp_config_writer_close (writer);

409 410 411 412 413
  gimp_config_writer_open (writer, "tabs-position");
  gimp_config_writer_printf (writer, "%d",
                             GIMP_GUI_CONFIG (gimp->config)->tabs_position);
  gimp_config_writer_close (writer);

414 415
  gimp_config_writer_open (writer, "last-tip-shown");
  gimp_config_writer_printf (writer, "%d",
416
                             GIMP_GUI_CONFIG (gimp->config)->last_tip_shown);
417
  gimp_config_writer_close (writer);
Michael Natterer's avatar
Michael Natterer committed
418

419 420
  if (! gimp_config_writer_finish (writer, "end of sessionrc", &error))
    {
421
      gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
422 423
      g_clear_error (&error);
    }
424

425 426
  dialogs_save_recent_docks (gimp);

427
  sessionrc_deleted = FALSE;
428
}
429

430 431 432
gboolean
session_clear (Gimp    *gimp,
               GError **error)
433
{
434 435 436
  GFile    *file;
  GError   *my_error = NULL;
  gboolean  success  = TRUE;
437 438 439 440

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

441
  file = session_file (gimp);
442

443 444
  if (! g_file_delete (file, NULL, &my_error) &&
      my_error->code != G_IO_ERROR_NOT_FOUND)
445 446
    {
      success = FALSE;
447 448 449 450

      g_set_error (error, GIMP_ERROR, GIMP_FAILED,
                   _("Deleting \"%s\" failed: %s"),
                   gimp_file_get_utf8_name (file), my_error->message);
451 452 453 454 455 456
    }
  else
    {
      sessionrc_deleted = TRUE;
    }

457 458
  g_clear_error (&my_error);
  g_object_unref (file);
459

460
  return success;
461
}
462 463


464 465
static GFile *
session_file (Gimp *gimp)
466
{
467 468
  const gchar *basename;
  gchar       *filename;
469
  GFile       *file;
470

471 472 473
  basename = g_getenv ("GIMP_TESTING_SESSIONRC_NAME");
  if (! basename)
    basename = "sessionrc";
474

475
  if (gimp->session_name)
476 477 478
    filename = g_strconcat (basename, ".", gimp->session_name, NULL);
  else
    filename = g_strdup (basename);
479

480
  file = gimp_directory_file (filename, NULL);
481

482 483 484
  g_free (filename);

  return file;
485
}