
Instead of including dialogs/dialogs.h everywhere, introduce gimp_dialog_factory_get_singleton(). The dialog factory singleton is still initialized by dialogs.c though. Right now the assumption is that we never will have another dialog factory instance around. There were so many problems before when we had four of them, so let's just keep one of them around.
379 lines
10 KiB
C
379 lines
10 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* Session-managment stuff
|
|
* Copyright (C) 1998 Sven Neumann <sven@gimp.org>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (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
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <glib/gstdio.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpconfig/gimpconfig.h"
|
|
|
|
#ifdef G_OS_WIN32
|
|
#include "libgimpbase/gimpwin32-io.h"
|
|
#endif
|
|
|
|
#include "gui-types.h"
|
|
|
|
#include "config/gimpconfig-file.h"
|
|
#include "config/gimpguiconfig.h"
|
|
|
|
#include "core/gimp.h"
|
|
|
|
#include "widgets/gimpdialogfactory.h"
|
|
#include "widgets/gimpsessioninfo.h"
|
|
|
|
#include "dialogs/dialogs.h"
|
|
|
|
#include "session.h"
|
|
#include "gimp-log.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
enum
|
|
{
|
|
SESSION_INFO = 1,
|
|
LAST_TIP_SHOWN
|
|
};
|
|
|
|
|
|
static gchar * session_filename (Gimp *gimp);
|
|
|
|
|
|
/* private variables */
|
|
|
|
static gboolean sessionrc_deleted = FALSE;
|
|
|
|
|
|
/* public functions */
|
|
|
|
void
|
|
session_init (Gimp *gimp)
|
|
{
|
|
gchar *filename;
|
|
GScanner *scanner;
|
|
GTokenType token;
|
|
GError *error = NULL;
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
filename = session_filename (gimp);
|
|
|
|
scanner = gimp_scanner_new_file (filename, &error);
|
|
|
|
if (! scanner && error->code == GIMP_CONFIG_ERROR_OPEN_ENOENT)
|
|
{
|
|
g_clear_error (&error);
|
|
g_free (filename);
|
|
|
|
filename = g_build_filename (gimp_sysconf_directory (),
|
|
"sessionrc", NULL);
|
|
scanner = gimp_scanner_new_file (filename, NULL);
|
|
}
|
|
|
|
if (! scanner)
|
|
{
|
|
g_clear_error (&error);
|
|
g_free (filename);
|
|
return;
|
|
}
|
|
|
|
if (gimp->be_verbose)
|
|
g_print ("Parsing '%s'\n", gimp_filename_to_utf8 (filename));
|
|
|
|
g_scanner_scope_add_symbol (scanner, 0, "session-info",
|
|
GINT_TO_POINTER (SESSION_INFO));
|
|
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))
|
|
{
|
|
GimpDialogFactory *factory = NULL;
|
|
GimpSessionInfo *info = NULL;
|
|
gchar *factory_name = NULL;
|
|
gchar *entry_name = NULL;
|
|
GimpDialogFactoryEntry *entry = NULL;
|
|
|
|
token = G_TOKEN_STRING;
|
|
|
|
if (! gimp_scanner_parse_string (scanner, &factory_name))
|
|
break;
|
|
|
|
/* In versions <= GIMP 2.6 there was a "toolbox", a
|
|
* "dock", a "display" and a "toplevel" factory. These
|
|
* are now merged to a single gimp_dialog_factory_get_singleton (). We
|
|
* need the legacy name though, so keep it around.
|
|
*/
|
|
factory = gimp_dialog_factory_get_singleton ();
|
|
|
|
info = gimp_session_info_new ();
|
|
|
|
/* GIMP 2.6 has the entry name as part of the
|
|
* session-info header, so try to get it
|
|
*/
|
|
gimp_scanner_parse_string (scanner, &entry_name);
|
|
if (entry_name)
|
|
{
|
|
/* 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);
|
|
}
|
|
}
|
|
|
|
/* We're done with these now */
|
|
g_free (factory_name);
|
|
g_free (entry_name);
|
|
|
|
/* We can get the factory entry either now (the GIMP <=
|
|
* 2.6 way), or when we deserialize (the GIMP 2.8 way)
|
|
*/
|
|
if (entry)
|
|
{
|
|
gimp_session_info_set_factory_entry (info, entry);
|
|
}
|
|
|
|
/* Always try to deserialize */
|
|
if (gimp_config_deserialize (GIMP_CONFIG (info), scanner, 1, NULL))
|
|
{
|
|
/* Make sure we got a factory entry either the 2.6
|
|
* or 2.8 way
|
|
*/
|
|
if (gimp_session_info_get_factory_entry (info))
|
|
{
|
|
GIMP_LOG (DIALOG_FACTORY,
|
|
"successfully parsed and added session info %p",
|
|
info);
|
|
|
|
gimp_dialog_factory_add_session_info (factory, info);
|
|
}
|
|
else
|
|
{
|
|
GIMP_LOG (DIALOG_FACTORY,
|
|
"failed to parse session info %p, not adding",
|
|
info);
|
|
|
|
g_object_unref (info);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_object_unref (info);
|
|
break;
|
|
}
|
|
}
|
|
else if (scanner->value.v_symbol == GINT_TO_POINTER (LAST_TIP_SHOWN))
|
|
{
|
|
GimpGuiConfig *config = GIMP_GUI_CONFIG (gimp->config);
|
|
|
|
token = G_TOKEN_INT;
|
|
|
|
if (! gimp_scanner_parse_int (scanner, &config->last_tip))
|
|
break;
|
|
}
|
|
token = G_TOKEN_RIGHT_PAREN;
|
|
break;
|
|
|
|
case G_TOKEN_RIGHT_PAREN:
|
|
token = G_TOKEN_LEFT_PAREN;
|
|
break;
|
|
|
|
default: /* do nothing */
|
|
break;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
|
|
g_clear_error (&error);
|
|
|
|
gimp_config_file_backup_on_error (filename, "sessionrc", NULL);
|
|
}
|
|
|
|
gimp_scanner_destroy (scanner);
|
|
g_free (filename);
|
|
|
|
dialogs_load_recent_docks (gimp);
|
|
}
|
|
|
|
void
|
|
session_exit (Gimp *gimp)
|
|
{
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
}
|
|
|
|
void
|
|
session_restore (Gimp *gimp)
|
|
{
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
gimp_dialog_factory_restore (gimp_dialog_factory_get_singleton ());
|
|
}
|
|
|
|
void
|
|
session_save (Gimp *gimp,
|
|
gboolean always_save)
|
|
{
|
|
GimpConfigWriter *writer;
|
|
gchar *filename;
|
|
GError *error = NULL;
|
|
|
|
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
|
|
|
if (sessionrc_deleted && ! always_save)
|
|
return;
|
|
|
|
filename = session_filename (gimp);
|
|
|
|
if (gimp->be_verbose)
|
|
g_print ("Writing '%s'\n", gimp_filename_to_utf8 (filename));
|
|
|
|
writer =
|
|
gimp_config_writer_new_file (filename,
|
|
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_free (filename);
|
|
|
|
if (!writer)
|
|
return;
|
|
|
|
gimp_dialog_factory_save (gimp_dialog_factory_get_singleton (), writer);
|
|
gimp_config_writer_linefeed (writer);
|
|
|
|
/* save last tip shown
|
|
*
|
|
* FIXME: Make last-tip-shown increment only when used within the
|
|
* session
|
|
*/
|
|
gimp_config_writer_open (writer, "last-tip-shown");
|
|
gimp_config_writer_printf (writer, "%d",
|
|
GIMP_GUI_CONFIG (gimp->config)->last_tip);
|
|
gimp_config_writer_close (writer);
|
|
|
|
if (! gimp_config_writer_finish (writer, "end of sessionrc", &error))
|
|
{
|
|
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
|
|
dialogs_save_recent_docks (gimp);
|
|
|
|
sessionrc_deleted = FALSE;
|
|
}
|
|
|
|
gboolean
|
|
session_clear (Gimp *gimp,
|
|
GError **error)
|
|
{
|
|
gchar *filename;
|
|
gboolean success = TRUE;
|
|
|
|
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
|
|
filename = session_filename (gimp);
|
|
|
|
if (g_unlink (filename) != 0 && errno != ENOENT)
|
|
{
|
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
|
_("Deleting \"%s\" failed: %s"),
|
|
gimp_filename_to_utf8 (filename), g_strerror (errno));
|
|
success = FALSE;
|
|
}
|
|
else
|
|
{
|
|
sessionrc_deleted = TRUE;
|
|
}
|
|
|
|
g_free (filename);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
static gchar *
|
|
session_filename (Gimp *gimp)
|
|
{
|
|
gchar *filename = gimp_personal_rc_file ("sessionrc");
|
|
|
|
if (gimp->session_name)
|
|
{
|
|
gchar *tmp = g_strconcat (filename, ".", gimp->session_name, NULL);
|
|
|
|
g_free (filename);
|
|
filename = tmp;
|
|
}
|
|
|
|
return filename;
|
|
}
|