mirror of https://github.com/GNOME/gimp.git
app: add support for tool groups in toolrc
Add a new Gimp::tool_item_list list, in addition to Gimp::tool_info_list. The latter may contain arbitrary tool items, including tool groups, and is intended for use in the UI (namely, the toolbox and the preferences tool editor). In gimp-tools, use Gimp::tool_item_list for representing the UI tool order (while still using Gimp::tool_info_list as a flat list of all GimpToolInfo objects), and add support for saving and loading tool groups to/from toolrc. Introduce file-version tracking in toolrc, and drop its contents on version mismatch, or when new tools are introduced. This is slightly disruptive, but merging new changes with existing toolrc files is non-trivial, and it doesn't happen very often. Add support for a sysconf toolrc file, which is used if there's no user toolrc file (i.e., on first use). If neither file is found, the hard-coded flat tool order is used. This commit doesn't provide a default toolrc file, but the next commits will. Make the gimp-tools serialization and deserialization functions public, for use in GimpToolEditor in the next commits.
This commit is contained in:
parent
a63bf32310
commit
cd2adfbede
|
@ -269,6 +269,13 @@ gimp_init (Gimp *gimp)
|
|||
gimp_object_set_static_name (GIMP_OBJECT (gimp->tool_info_list),
|
||||
"tool infos");
|
||||
|
||||
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");
|
||||
|
||||
gimp->documents = gimp_document_list_new (gimp);
|
||||
|
||||
gimp->templates = gimp_list_new (GIMP_TYPE_TEMPLATE, TRUE);
|
||||
|
@ -398,6 +405,8 @@ gimp_finalize (GObject *object)
|
|||
g_clear_object (&gimp->tool_info_list);
|
||||
}
|
||||
|
||||
g_clear_object (&gimp->tool_item_list);
|
||||
|
||||
file_data_exit (gimp);
|
||||
xcf_exit (gimp);
|
||||
|
||||
|
@ -915,6 +924,14 @@ gimp_get_tool_info_iter (Gimp *gimp)
|
|||
return GIMP_LIST (gimp->tool_info_list)->queue->head;
|
||||
}
|
||||
|
||||
GList *
|
||||
gimp_get_tool_item_iter (Gimp *gimp)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
|
||||
|
||||
return GIMP_LIST (gimp->tool_item_list)->queue->head;
|
||||
}
|
||||
|
||||
GimpObject *
|
||||
gimp_get_clipboard_object (Gimp *gimp)
|
||||
{
|
||||
|
|
|
@ -111,6 +111,8 @@ struct _Gimp
|
|||
GimpContainer *tool_info_list;
|
||||
GimpToolInfo *standard_tool_info;
|
||||
|
||||
GimpContainer *tool_item_list;
|
||||
|
||||
/* the opened and saved images in MRU order */
|
||||
GimpContainer *documents;
|
||||
|
||||
|
@ -187,6 +189,7 @@ GList * gimp_get_display_iter (Gimp *gimp);
|
|||
GList * gimp_get_image_windows (Gimp *gimp);
|
||||
GList * gimp_get_paint_info_iter (Gimp *gimp);
|
||||
GList * gimp_get_tool_info_iter (Gimp *gimp);
|
||||
GList * gimp_get_tool_item_iter (Gimp *gimp);
|
||||
|
||||
GimpObject * gimp_get_clipboard_object (Gimp *gimp);
|
||||
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
#include "core/gimp.h"
|
||||
#include "core/gimp-contexts.h"
|
||||
#include "core/gimp-internal-data.h"
|
||||
#include "core/gimpcontext.h"
|
||||
#include "core/gimplist.h"
|
||||
#include "core/gimptoolgroup.h"
|
||||
#include "core/gimptoolinfo.h"
|
||||
#include "core/gimptooloptions.h"
|
||||
|
||||
|
@ -89,23 +91,32 @@
|
|||
#include "gimpvectortool.h"
|
||||
#include "gimpwarptool.h"
|
||||
|
||||
#include "gimp-intl.h"
|
||||
|
||||
|
||||
#define TOOL_RC_FILE_VERSION 1
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void gimp_tools_register (GType tool_type,
|
||||
GType tool_options_type,
|
||||
GimpToolOptionsGUIFunc options_gui_func,
|
||||
GimpContextPropMask context_props,
|
||||
const gchar *identifier,
|
||||
const gchar *label,
|
||||
const gchar *tooltip,
|
||||
const gchar *menu_label,
|
||||
const gchar *menu_accel,
|
||||
const gchar *help_domain,
|
||||
const gchar *help_data,
|
||||
const gchar *icon_name,
|
||||
gpointer data);
|
||||
static void gimp_tools_register (GType tool_type,
|
||||
GType tool_options_type,
|
||||
GimpToolOptionsGUIFunc options_gui_func,
|
||||
GimpContextPropMask context_props,
|
||||
const gchar *identifier,
|
||||
const gchar *label,
|
||||
const gchar *tooltip,
|
||||
const gchar *menu_label,
|
||||
const gchar *menu_accel,
|
||||
const gchar *help_domain,
|
||||
const gchar *help_data,
|
||||
const gchar *icon_name,
|
||||
gpointer data);
|
||||
|
||||
static void gimp_tools_copy_structure (Gimp *gimp,
|
||||
GimpContainer *src_container,
|
||||
GimpContainer *dest_container,
|
||||
GHashTable *tools);
|
||||
|
||||
/* private variables */
|
||||
|
||||
|
@ -225,18 +236,10 @@ gimp_tools_init (Gimp *gimp)
|
|||
void
|
||||
gimp_tools_exit (Gimp *gimp)
|
||||
{
|
||||
GList *default_order;
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
|
||||
default_order = g_object_get_data (G_OBJECT (gimp),
|
||||
"gimp-tools-default-order");
|
||||
|
||||
g_list_free_full (default_order, (GDestroyNotify) g_free);
|
||||
|
||||
g_object_set_data (G_OBJECT (gimp), "gimp-tools-default-order", NULL);
|
||||
|
||||
tool_manager_exit (gimp);
|
||||
|
||||
gimp_tool_options_manager_exit (gimp);
|
||||
|
@ -254,70 +257,14 @@ gimp_tools_exit (Gimp *gimp)
|
|||
void
|
||||
gimp_tools_restore (Gimp *gimp)
|
||||
{
|
||||
GimpContainer *gimp_list;
|
||||
GimpObject *object;
|
||||
GFile *file;
|
||||
GList *list;
|
||||
GError *error = NULL;
|
||||
GimpObject *object;
|
||||
GList *list;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
|
||||
gimp_list = g_object_new (GIMP_TYPE_LIST,
|
||||
"children-type", GIMP_TYPE_TOOL_INFO,
|
||||
"append", TRUE,
|
||||
NULL);
|
||||
|
||||
file = gimp_directory_file ("toolrc", NULL);
|
||||
|
||||
if (gimp->be_verbose)
|
||||
g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
|
||||
|
||||
if (gimp_config_deserialize_file (GIMP_CONFIG (gimp_list), file,
|
||||
NULL, &error))
|
||||
{
|
||||
gint i = 0;
|
||||
|
||||
for (list = GIMP_LIST (gimp_list)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
const gchar *name = gimp_object_get_name (list->data);
|
||||
|
||||
object = gimp_container_get_child_by_name (gimp->tool_info_list,
|
||||
name);
|
||||
|
||||
if (object)
|
||||
{
|
||||
GimpToolItem *tool_item = list->data;
|
||||
|
||||
while (! gimp_container_get_child_by_name (
|
||||
gimp_list,
|
||||
gimp_object_get_name (
|
||||
gimp_container_get_child_by_index (
|
||||
gimp->tool_info_list, i))))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
g_object_set (object,
|
||||
"visible", gimp_tool_item_is_visible (tool_item),
|
||||
NULL);
|
||||
|
||||
gimp_container_reorder (gimp->tool_info_list,
|
||||
object, i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error->code != G_IO_ERROR_NOT_FOUND)
|
||||
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING, error->message);
|
||||
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
g_object_unref (gimp_list);
|
||||
/* restore tool order */
|
||||
gimp_tools_reset (gimp, gimp->tool_item_list, TRUE);
|
||||
|
||||
/* make the generic operation tool invisible by default */
|
||||
object = gimp_container_get_child_by_name (gimp->tool_info_list,
|
||||
|
@ -395,7 +342,8 @@ gimp_tools_save (Gimp *gimp,
|
|||
gboolean save_tool_options,
|
||||
gboolean always_save)
|
||||
{
|
||||
GFile *file;
|
||||
GimpConfigWriter *writer;
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
|
||||
|
@ -435,11 +383,15 @@ gimp_tools_save (Gimp *gimp,
|
|||
if (gimp->be_verbose)
|
||||
g_print ("Writing '%s'\n", gimp_file_get_utf8_name (file));
|
||||
|
||||
gimp_config_serialize_to_file (GIMP_CONFIG (gimp->tool_info_list),
|
||||
file,
|
||||
"GIMP toolrc",
|
||||
"end of toolrc",
|
||||
NULL, NULL);
|
||||
writer = gimp_config_writer_new_from_file (file, TRUE, "GIMP toolrc", NULL);
|
||||
|
||||
if (writer)
|
||||
{
|
||||
gimp_tools_serialize (gimp, gimp->tool_item_list, writer);
|
||||
|
||||
gimp_config_writer_finish (writer, "end of toolrc", NULL);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
|
@ -473,6 +425,214 @@ gimp_tools_clear (Gimp *gimp,
|
|||
return success;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_tools_serialize (Gimp *gimp,
|
||||
GimpContainer *container,
|
||||
GimpConfigWriter *writer)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
||||
g_return_val_if_fail (GIMP_IS_CONTAINER (container), FALSE);
|
||||
|
||||
gimp_config_writer_open (writer, "file-version");
|
||||
gimp_config_writer_printf (writer, "%d", TOOL_RC_FILE_VERSION);
|
||||
gimp_config_writer_close (writer);
|
||||
|
||||
gimp_config_writer_linefeed (writer);
|
||||
|
||||
return gimp_config_serialize (GIMP_CONFIG (container), writer, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_tools_deserialize (Gimp *gimp,
|
||||
GimpContainer *container,
|
||||
GScanner *scanner)
|
||||
{
|
||||
enum
|
||||
{
|
||||
FILE_VERSION = 1
|
||||
};
|
||||
|
||||
GimpContainer *src_container;
|
||||
GTokenType token;
|
||||
guint scope_id;
|
||||
guint old_scope_id;
|
||||
gint file_version = 0;
|
||||
gboolean result = FALSE;
|
||||
|
||||
scope_id = g_type_qname (GIMP_TYPE_TOOL_GROUP);
|
||||
old_scope_id = g_scanner_set_scope (scanner, scope_id);
|
||||
|
||||
g_scanner_scope_add_symbol (scanner, scope_id,
|
||||
"file-version",
|
||||
GINT_TO_POINTER (FILE_VERSION));
|
||||
|
||||
token = G_TOKEN_LEFT_PAREN;
|
||||
|
||||
while (g_scanner_peek_next_token (scanner) == token &&
|
||||
(token != G_TOKEN_LEFT_PAREN ||
|
||||
! file_version))
|
||||
{
|
||||
token = g_scanner_get_next_token (scanner);
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case G_TOKEN_LEFT_PAREN:
|
||||
token = G_TOKEN_SYMBOL;
|
||||
break;
|
||||
|
||||
case G_TOKEN_SYMBOL:
|
||||
switch (GPOINTER_TO_INT (scanner->value.v_symbol))
|
||||
{
|
||||
case FILE_VERSION:
|
||||
token = G_TOKEN_INT;
|
||||
if (gimp_scanner_parse_int (scanner, &file_version))
|
||||
token = G_TOKEN_RIGHT_PAREN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case G_TOKEN_RIGHT_PAREN:
|
||||
token = G_TOKEN_LEFT_PAREN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_scanner_set_scope (scanner, old_scope_id);
|
||||
|
||||
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);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (file_version != TOOL_RC_FILE_VERSION)
|
||||
{
|
||||
g_scanner_error (scanner, "wrong toolrc file format version");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gimp_container_freeze (container);
|
||||
|
||||
g_type_class_unref (g_type_class_ref (GIMP_TYPE_TOOL_GROUP));
|
||||
|
||||
gimp_container_clear (container);
|
||||
|
||||
src_container = g_object_new (GIMP_TYPE_LIST,
|
||||
"children-type", GIMP_TYPE_TOOL_ITEM,
|
||||
"append", TRUE,
|
||||
NULL);
|
||||
|
||||
if (gimp_config_deserialize (GIMP_CONFIG (src_container),
|
||||
scanner, 0, NULL))
|
||||
{
|
||||
GHashTable *tools;
|
||||
GList *list;
|
||||
|
||||
result = TRUE;
|
||||
|
||||
tools = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
gimp_tools_copy_structure (gimp, src_container, container, tools);
|
||||
|
||||
for (list = gimp_get_tool_info_iter (gimp);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpToolInfo *tool_info = list->data;
|
||||
|
||||
if (! tool_info->hidden && ! g_hash_table_contains (tools, tool_info))
|
||||
{
|
||||
g_scanner_error (scanner, "missing tools in toolrc file");
|
||||
|
||||
result = FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_unref (tools);
|
||||
}
|
||||
|
||||
g_object_unref (src_container);
|
||||
|
||||
gimp_container_thaw (container);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_tools_reset (Gimp *gimp,
|
||||
GimpContainer *container,
|
||||
gboolean user_toolrc)
|
||||
{
|
||||
GList *files = NULL;
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||||
g_return_if_fail (GIMP_IS_CONTAINER (container));
|
||||
|
||||
if (user_toolrc)
|
||||
files = g_list_prepend (files, gimp_directory_file ("toolrc", NULL));
|
||||
files = g_list_prepend (files, gimp_sysconf_directory_file ("toolrc", NULL));
|
||||
|
||||
files = g_list_reverse (files);
|
||||
|
||||
gimp_container_freeze (container);
|
||||
|
||||
gimp_container_clear (container);
|
||||
|
||||
for (list = files; list; list = g_list_next (list))
|
||||
{
|
||||
GScanner *scanner;
|
||||
GFile *file = list->data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (gimp->be_verbose)
|
||||
g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
|
||||
|
||||
scanner = gimp_scanner_new_file (file, &error);
|
||||
|
||||
if (scanner && gimp_tools_deserialize (gimp, container, scanner))
|
||||
{
|
||||
gimp_scanner_unref (scanner);
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error->code != G_IO_ERROR_NOT_FOUND)
|
||||
{
|
||||
gimp_message_literal (gimp, NULL,
|
||||
GIMP_MESSAGE_WARNING, error->message);
|
||||
}
|
||||
|
||||
g_clear_error (&error);
|
||||
|
||||
gimp_container_clear (container);
|
||||
}
|
||||
|
||||
g_clear_pointer (&scanner, gimp_scanner_unref);
|
||||
}
|
||||
|
||||
g_list_free_full (files, g_object_unref);
|
||||
|
||||
if (gimp_container_is_empty (container))
|
||||
{
|
||||
if (gimp->be_verbose)
|
||||
g_print ("Using default tool order\n");
|
||||
|
||||
gimp_tools_copy_structure (gimp, gimp->tool_info_list, container, NULL);
|
||||
}
|
||||
|
||||
gimp_container_thaw (container);
|
||||
}
|
||||
|
||||
GList *
|
||||
gimp_tools_get_default_order (Gimp *gimp)
|
||||
{
|
||||
|
@ -582,9 +742,9 @@ gimp_tools_register (GType tool_type,
|
|||
|
||||
visible = (! g_type_is_a (tool_type, GIMP_TYPE_FILTER_TOOL));
|
||||
|
||||
g_object_set (tool_info, "visible", visible, NULL);
|
||||
gimp_tool_item_set_visible (GIMP_TOOL_ITEM (tool_info), visible);
|
||||
|
||||
/* hack to make the operation tools always invisible */
|
||||
/* hack to hide the operation tool entirely */
|
||||
if (tool_type == GIMP_TYPE_OPERATION_TOOL)
|
||||
tool_info->hidden = TRUE;
|
||||
|
||||
|
@ -600,3 +760,55 @@ gimp_tools_register (GType tool_type,
|
|||
if (tool_type == GIMP_TYPE_PAINTBRUSH_TOOL)
|
||||
gimp_tool_info_set_standard (gimp, tool_info);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_tools_copy_structure (Gimp *gimp,
|
||||
GimpContainer *src_container,
|
||||
GimpContainer *dest_container,
|
||||
GHashTable *tools)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = GIMP_LIST (src_container)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
GimpToolItem *src_tool_item = list->data;
|
||||
GimpToolItem *dest_tool_item = NULL;
|
||||
|
||||
if (GIMP_IS_TOOL_GROUP (src_tool_item))
|
||||
{
|
||||
dest_tool_item = GIMP_TOOL_ITEM (gimp_tool_group_new ());
|
||||
|
||||
gimp_tools_copy_structure (
|
||||
gimp,
|
||||
gimp_viewable_get_children (GIMP_VIEWABLE (src_tool_item)),
|
||||
gimp_viewable_get_children (GIMP_VIEWABLE (dest_tool_item)),
|
||||
tools);
|
||||
|
||||
gimp_tool_group_set_active_tool (
|
||||
GIMP_TOOL_GROUP (dest_tool_item),
|
||||
gimp_tool_group_get_active_tool (GIMP_TOOL_GROUP (src_tool_item)));
|
||||
}
|
||||
else
|
||||
{
|
||||
dest_tool_item = GIMP_TOOL_ITEM (
|
||||
gimp_get_tool_info (gimp, gimp_object_get_name (src_tool_item)));
|
||||
|
||||
if (dest_tool_item && GIMP_TOOL_INFO (dest_tool_item)->hidden)
|
||||
dest_tool_item = NULL;
|
||||
else if (tools)
|
||||
g_hash_table_add (tools, dest_tool_item);
|
||||
}
|
||||
|
||||
if (dest_tool_item)
|
||||
{
|
||||
gimp_tool_item_set_visible (
|
||||
dest_tool_item,
|
||||
gimp_tool_item_get_visible (src_tool_item));
|
||||
|
||||
gimp_container_add (dest_container,
|
||||
GIMP_OBJECT (dest_tool_item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,18 +19,29 @@
|
|||
#define __GIMP_TOOLS_H__
|
||||
|
||||
|
||||
void gimp_tools_init (Gimp *gimp);
|
||||
void gimp_tools_exit (Gimp *gimp);
|
||||
void gimp_tools_init (Gimp *gimp);
|
||||
void gimp_tools_exit (Gimp *gimp);
|
||||
|
||||
void gimp_tools_restore (Gimp *gimp);
|
||||
void gimp_tools_save (Gimp *gimp,
|
||||
gboolean save_tool_options,
|
||||
gboolean always_save);
|
||||
void gimp_tools_restore (Gimp *gimp);
|
||||
void gimp_tools_save (Gimp *gimp,
|
||||
gboolean save_tool_options,
|
||||
gboolean always_save);
|
||||
|
||||
gboolean gimp_tools_clear (Gimp *gimp,
|
||||
GError **error);
|
||||
gboolean gimp_tools_clear (Gimp *gimp,
|
||||
GError **error);
|
||||
|
||||
GList * gimp_tools_get_default_order (Gimp *gimp);
|
||||
gboolean gimp_tools_serialize (Gimp *gimp,
|
||||
GimpContainer *container,
|
||||
GimpConfigWriter *writer);
|
||||
gboolean gimp_tools_deserialize (Gimp *gimp,
|
||||
GimpContainer *container,
|
||||
GScanner *scanner);
|
||||
|
||||
void gimp_tools_reset (Gimp *gimp,
|
||||
GimpContainer *container,
|
||||
gboolean user_toolrc);
|
||||
|
||||
GList * gimp_tools_get_default_order (Gimp *gimp);
|
||||
|
||||
|
||||
#endif /* __GIMP_TOOLS_H__ */
|
||||
|
|
|
@ -416,6 +416,7 @@ app/text/gimptextlayer-xcf.c
|
|||
app/text/gimptextlayout.c
|
||||
app/text/text-enums.c
|
||||
|
||||
app/tools/gimp-tools.c
|
||||
app/tools/gimpairbrushtool.c
|
||||
app/tools/gimpalignoptions.c
|
||||
app/tools/gimpaligntool.c
|
||||
|
|
Loading…
Reference in New Issue