drop own recently used files code in favour of GtkRecentManager:

* app/core/gimp-gui.c (gimp_recent_list_add_uri), app/core/gimp-gui.h,
app/gui/gui-vtable.c (gui_recent_list_add_uri): add
{gimp,gui}_recent_list_add_uri(), gui_recent_list_add_uri() dispatches to
GtkRecentManager

* app/dialogs/file-save-dialog.c (file_save_dialog_save_image),
app/actions/file-commands.c (file_save_cmd_callback),
app/widgets/gimpdnd-xds.c (gimp_dnd_xds_save_image): pass Gimp instance to
file_save() calls

* app/file/file-open.c (file_open_with_proc_and_display,
file_open_layers), app/file/file-save.c (file_save), app/file/file-save.h:
pass Gimp instance to gimp_recent_list_add_uri() calls

* app/file/gimprecentitem.c, app/file/gimprecentitem.h,
app/file/gimprecentlist.c, app/file/gimprecentlist.h: removed

* app/file/Makefile.am: drop reference to removed files

svn path=/trunk/; revision=23526
This commit is contained in:
Nils Philippsen 2007-09-13 14:19:30 +00:00
parent 6a832ba3ee
commit 8ff9c4c84c
15 changed files with 93 additions and 1027 deletions

View File

@ -1,3 +1,26 @@
2007-09-13 Nils Philippsen <nphilipp@redhat.com>
drop own recently used files code in favour of GtkRecentManager:
* app/core/gimp-gui.c (gimp_recent_list_add_uri), app/core/gimp-gui.h,
app/gui/gui-vtable.c (gui_recent_list_add_uri): add
{gimp,gui}_recent_list_add_uri(), gui_recent_list_add_uri() dispatches to
GtkRecentManager
* app/dialogs/file-save-dialog.c (file_save_dialog_save_image),
app/actions/file-commands.c (file_save_cmd_callback),
app/widgets/gimpdnd-xds.c (gimp_dnd_xds_save_image): pass Gimp instance to
file_save() calls
* app/file/file-open.c (file_open_with_proc_and_display,
file_open_layers), app/file/file-save.c (file_save), app/file/file-save.h:
pass Gimp instance to gimp_recent_list_add_uri() calls
* app/file/gimprecentitem.c, app/file/gimprecentitem.h,
app/file/gimprecentlist.c, app/file/gimprecentlist.h: removed
* app/file/Makefile.am: drop reference to removed files
2007-09-13 Michael Natterer <mitch@gimp.org>
* configure.in: : remove PANGO_DISABLE_DEPRECATED only for

View File

@ -230,7 +230,8 @@ file_save_cmd_callback (GtkAction *action,
FALSE);
}
status = file_save (image, action_data_get_context (data),
status = file_save (image->gimp, image,
action_data_get_context (data),
GIMP_PROGRESS (display),
uri, save_proc,
GIMP_RUN_WITH_LAST_VALS, FALSE, &error);

View File

@ -61,6 +61,7 @@ gimp_gui_init (Gimp *gimp)
gimp->gui.progress_free = NULL;
gimp->gui.pdb_dialog_set = NULL;
gimp->gui.pdb_dialog_close = NULL;
gimp->gui.recent_list_add_uri = NULL;
}
void
@ -415,3 +416,17 @@ gimp_pdb_dialog_close (Gimp *gimp,
return FALSE;
}
gboolean
gimp_recent_list_add_uri (Gimp *gimp,
const gchar *uri,
const gchar *mime_type)
{
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
if (gimp->gui.recent_list_add_uri)
return gimp->gui.recent_list_add_uri (gimp, uri, mime_type);
return FALSE;
}

View File

@ -80,6 +80,10 @@ struct _GimpGui
gboolean (* pdb_dialog_close) (Gimp *gimp,
GimpContainer *container,
const gchar *callback_name);
gboolean (* recent_list_add_uri) (Gimp *gimp,
const gchar *uri,
const gchar *mime_type);
};
@ -146,6 +150,8 @@ gboolean gimp_pdb_dialog_set (Gimp *gimp,
gboolean gimp_pdb_dialog_close (Gimp *gimp,
GimpContainer *container,
const gchar *callback_name);
gboolean gimp_recent_list_add_uri (Gimp *gimp,
const gchar *uri,
const gchar *mime_type);
#endif /* __GIMP_GUI_H__ */

View File

@ -511,7 +511,7 @@ file_save_dialog_save_image (GtkWidget *save_dialog,
g_object_ref (image);
status = file_save (image, gimp_get_user_context (image->gimp),
status = file_save (image->gimp, image, gimp_get_user_context (image->gimp),
GIMP_PROGRESS (save_dialog),
uri, save_proc,
GIMP_RUN_INTERACTIVE, save_a_copy, &error);

View File

@ -22,10 +22,6 @@ libappfile_a_SOURCES = \
file-save.c \
file-save.h \
file-utils.c \
file-utils.h \
gimprecentitem.c \
gimprecentitem.h \
gimprecentlist.c \
gimprecentlist.h
file-utils.h
EXTRA_DIST = makefile.msc

View File

@ -69,7 +69,6 @@
#include "file-open.h"
#include "file-procedure.h"
#include "file-utils.h"
#include "gimprecentlist.h"
#include "gimp-intl.h"
@ -353,7 +352,7 @@ file_open_with_proc_and_display (Gimp *gimp,
}
if (gimp->config->save_document_history)
gimp_recent_list_add_uri (uri, mime_type);
gimp_recent_list_add_uri (gimp, uri, mime_type);
}
/* the display owns the image now */
@ -463,7 +462,7 @@ file_open_layers (Gimp *gimp,
uri, mime_type);
if (gimp->config->save_document_history)
gimp_recent_list_add_uri (uri, mime_type);
gimp_recent_list_add_uri (gimp, uri, mime_type);
}
else
{

View File

@ -60,7 +60,6 @@
#include "file-save.h"
#include "file-utils.h"
#include "gimprecentlist.h"
#include "gimp-intl.h"
@ -68,7 +67,8 @@
/* public functions */
GimpPDBStatusType
file_save (GimpImage *image,
file_save (Gimp *gimp,
GimpImage *image,
GimpContext *context,
GimpProgress *progress,
const gchar *uri,
@ -84,6 +84,7 @@ file_save (GimpImage *image,
gint32 image_ID;
gint32 drawable_ID;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), GIMP_PDB_CALLING_ERROR);
g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_PDB_CALLING_ERROR);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_PDB_CALLING_ERROR);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress),
@ -185,7 +186,7 @@ file_save (GimpImage *image,
gimp_imagefile_save_thumbnail (imagefile, file_proc->mime_type, image);
if (image->gimp->config->save_document_history)
gimp_recent_list_add_uri (uri, file_proc->mime_type);
gimp_recent_list_add_uri (gimp, uri, file_proc->mime_type);
}
else if (status != GIMP_PDB_CANCEL)
{

View File

@ -22,7 +22,8 @@
#define __FILE_SAVE_H__
GimpPDBStatusType file_save (GimpImage *image,
GimpPDBStatusType file_save (Gimp *gimp,
GimpImage *image,
GimpContext *context,
GimpProgress *progress,
const gchar *uri,

View File

@ -1,256 +0,0 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Recent File Storage,
* see http://freedesktop.org/Standards/recent-file-spec/
*
* This code is taken from libegg and has been adapted to the GIMP needs.
* The original author is James Willcox <jwillcox@cs.indiana.edu>,
* responsible for bugs in this version is 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <time.h>
#include <glib-object.h>
#include "gimprecentitem.h"
struct _GimpRecentItem
{
gchar *uri;
gchar *mime_type;
time_t timestamp;
gboolean private_data;
GList *groups;
gint refcount;
};
GimpRecentItem *
gimp_recent_item_new (void)
{
GimpRecentItem *item;
item = g_slice_new (GimpRecentItem);
item->groups = NULL;
item->private_data = FALSE;
item->uri = NULL;
item->mime_type = NULL;
item->refcount = 1;
return item;
}
static void
gimp_recent_item_free (GimpRecentItem *item)
{
if (item->uri)
g_free (item->uri);
if (item->mime_type)
g_free (item->mime_type);
if (item->groups)
{
g_list_foreach (item->groups, (GFunc) g_free, NULL);
g_list_free (item->groups);
item->groups = NULL;
}
g_slice_free (GimpRecentItem, item);
}
GimpRecentItem *
gimp_recent_item_ref (GimpRecentItem *item)
{
item->refcount++;
return item;
}
GimpRecentItem *
gimp_recent_item_unref (GimpRecentItem *item)
{
item->refcount--;
if (item->refcount == 0)
gimp_recent_item_free (item);
return item;
}
GimpRecentItem *
gimp_recent_item_new_from_uri (const gchar *uri)
{
GimpRecentItem *item;
g_return_val_if_fail (uri != NULL, NULL);
item = gimp_recent_item_new ();
if (!gimp_recent_item_set_uri (item ,uri))
{
gimp_recent_item_free (item);
return NULL;
}
return item;
}
gboolean
gimp_recent_item_set_uri (GimpRecentItem *item,
const gchar *uri)
{
gchar *utf8_uri = g_filename_to_utf8 (uri, -1, NULL, NULL, NULL);
if (! utf8_uri)
{
g_warning ("%s: URI can't be converted to UTF-8", G_STRFUNC);
return FALSE;
}
g_free (utf8_uri);
if (item->uri)
g_free (item->uri);
item->uri = g_strdup (uri);
return TRUE;
}
const gchar *
gimp_recent_item_get_uri (const GimpRecentItem *item)
{
return item->uri;
}
gchar *
gimp_recent_item_get_uri_utf8 (const GimpRecentItem *item)
{
/* this could fail, but it's not likely, since we've already done it
* once in set_uri()
*/
return g_filename_to_utf8 (item->uri, -1, NULL, NULL, NULL);
}
void
gimp_recent_item_set_mime_type (GimpRecentItem *item,
const gchar *mime)
{
if (item->mime_type)
g_free (item->mime_type);
item->mime_type = g_strdup (mime);
}
const gchar *
gimp_recent_item_get_mime_type (const GimpRecentItem *item)
{
return item->mime_type;
}
void
gimp_recent_item_set_timestamp (GimpRecentItem *item,
time_t timestamp)
{
if (timestamp == (time_t) -1)
time (&timestamp);
item->timestamp = timestamp;
}
time_t
gimp_recent_item_get_timestamp (const GimpRecentItem *item)
{
return item->timestamp;
}
const GList *
gimp_recent_item_get_groups (const GimpRecentItem *item)
{
return item->groups;
}
gboolean
gimp_recent_item_in_group (const GimpRecentItem *item,
const gchar *group_name)
{
GList *tmp = item->groups;
for (tmp = item->groups; tmp; tmp = tmp->next)
{
const gchar *value = tmp->data;
if (strcmp (group_name, value) == 0)
return TRUE;
}
return FALSE;
}
void
gimp_recent_item_add_group (GimpRecentItem *item,
const gchar *group_name)
{
g_return_if_fail (group_name != NULL);
if (!gimp_recent_item_in_group (item, group_name))
item->groups = g_list_append (item->groups, g_strdup (group_name));
}
void
gimp_recent_item_remove_group (GimpRecentItem *item,
const gchar *group_name)
{
GList *tmp;
g_return_if_fail (group_name != NULL);
for (tmp = item->groups; tmp; tmp = tmp->next)
{
gchar *value = tmp->data;
if (strcmp (group_name, value) == 0)
{
item->groups = g_list_remove (item->groups, value);
g_free (value);
break;
}
}
}
void
gimp_recent_item_set_private (GimpRecentItem *item,
gboolean priv)
{
item->private_data = priv;
}
gboolean
gimp_recent_item_get_private (const GimpRecentItem *item)
{
return item->private_data;
}

View File

@ -1,71 +0,0 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Recent File Storage,
* see http://freedesktop.org/Standards/recent-file-spec/
*
* This code is taken from libegg and has been adapted to the GIMP needs.
* The original author is James Willcox <jwillcox@cs.indiana.edu>,
* responsible for bugs in this version is 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_RECENT_ITEM_H__
#define __GIMP_RECENT_ITEM_H__
typedef struct _GimpRecentItem GimpRecentItem;
GimpRecentItem * gimp_recent_item_new (void);
GimpRecentItem * gimp_recent_item_ref (GimpRecentItem *item);
GimpRecentItem * gimp_recent_item_unref (GimpRecentItem *item);
GimpRecentItem * gimp_recent_item_new_from_uri (const gchar *uri);
gboolean gimp_recent_item_set_uri (GimpRecentItem *item,
const gchar *uri);
const gchar * gimp_recent_item_get_uri (const GimpRecentItem *item);
gchar * gimp_recent_item_get_uri_utf8 (const GimpRecentItem *item);
void gimp_recent_item_set_mime_type (GimpRecentItem *item,
const gchar *mime);
const gchar * gimp_recent_item_get_mime_type (const GimpRecentItem *item);
void gimp_recent_item_set_timestamp (GimpRecentItem *item,
time_t timestamp);
time_t gimp_recent_item_get_timestamp (const GimpRecentItem *item);
/* groups */
const GList * gimp_recent_item_get_groups (const GimpRecentItem *item);
gboolean gimp_recent_item_in_group (const GimpRecentItem *item,
const gchar *group_name);
void gimp_recent_item_add_group (GimpRecentItem *item,
const gchar *group_name);
void gimp_recent_item_remove_group (GimpRecentItem *item,
const gchar *group_name);
void gimp_recent_item_set_private (GimpRecentItem *item,
gboolean priv);
gboolean gimp_recent_item_get_private (const GimpRecentItem *item);
#endif /* __GIMP_RECENT_ITEM_H__ */

View File

@ -1,649 +0,0 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Recent File Storage,
* see http://freedesktop.org/Standards/recent-file-spec/
*
* This code is taken from libegg and has been adapted to the GIMP needs.
* The original author is James Willcox <jwillcox@cs.indiana.edu>,
* responsible for bugs in this version is 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#define _GNU_SOURCE /* need lockf() and F_TLOCK/F_ULOCK */
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <glib-object.h>
#include <glib/gstdio.h>
#ifndef G_OS_WIN32 /* This code doesn't compile on win32 and the use of
* the freedesktop standard doesn't make much sense
* there anyway. If someone wants to contribute a win32
* specific implementation, that would be appreciated.
*/
#include "config/config-types.h"
#include "config/gimpxmlparser.h"
#include "gimprecentitem.h"
#include "gimprecentlist.h"
#define GIMP_RECENT_LIST_FILE_NAME ".recently-used"
#define GIMP_RECENT_LIST_MAX_ITEMS 500
#define GIMP_RECENT_LIST_GROUP_GIMP "gimp"
#define GIMP_RECENT_ITEM_LIST_UNREF(list) \
g_list_foreach (list, (GFunc) gimp_recent_item_unref, NULL); \
g_list_free (list);
typedef struct
{
GSList *states;
GList *items;
GimpRecentItem *current_item;
} ParseInfo;
typedef enum
{
STATE_START,
STATE_RECENT_FILES,
STATE_RECENT_ITEM,
STATE_URI,
STATE_MIME_TYPE,
STATE_TIMESTAMP,
STATE_PRIVATE,
STATE_GROUPS,
STATE_GROUP
} ParseState;
#define TAG_RECENT_FILES "RecentFiles"
#define TAG_RECENT_ITEM "RecentItem"
#define TAG_URI "URI"
#define TAG_MIME_TYPE "Mime-Type"
#define TAG_TIMESTAMP "Timestamp"
#define TAG_PRIVATE "Private"
#define TAG_GROUPS "Groups"
#define TAG_GROUP "Group"
static void start_element_handler (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error);
static void end_element_handler (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error);
static void text_handler (GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error);
static const GMarkupParser markup_parser =
{
start_element_handler,
end_element_handler,
text_handler,
NULL,
NULL
};
static void
gimp_recent_list_add_new_groups (GimpRecentItem *item,
GimpRecentItem *upd_item)
{
const GList *tmp;
for (tmp = gimp_recent_item_get_groups (upd_item); tmp; tmp = tmp->next)
{
const gchar *group = tmp->data;
if (! gimp_recent_item_in_group (item, group))
gimp_recent_item_add_group (item, group);
}
}
static gboolean
gimp_recent_list_update_item (GList *items,
GimpRecentItem *upd_item)
{
const char *uri = gimp_recent_item_get_uri (upd_item);
GList *tmp;
for (tmp = items; tmp; tmp = tmp->next)
{
GimpRecentItem *item = tmp->data;
/* gnome_vfs_uris_match (gimp_recent_item_get_uri (item), uri) */
if (strcmp (gimp_recent_item_get_uri (item), uri) == 0)
{
gimp_recent_item_set_timestamp (item, (time_t) -1);
gimp_recent_list_add_new_groups (item, upd_item);
return TRUE;
}
}
return FALSE;
}
static void
parse_info_init (ParseInfo *info)
{
info->states = g_slist_prepend (NULL, GINT_TO_POINTER (STATE_START));
info->items = NULL;
}
static void
parse_info_free (ParseInfo *info)
{
g_slist_free (info->states);
}
static void
push_state (ParseInfo *info,
ParseState state)
{
info->states = g_slist_prepend (info->states, GINT_TO_POINTER (state));
}
static void
pop_state (ParseInfo *info)
{
g_return_if_fail (info->states != NULL);
info->states = g_slist_remove (info->states, info->states->data);
}
static ParseState
peek_state (ParseInfo *info)
{
g_return_val_if_fail (info->states != NULL, STATE_START);
return GPOINTER_TO_INT (info->states->data);
}
#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
static void
start_element_handler (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error)
{
ParseInfo *info = user_data;
if (ELEMENT_IS (TAG_RECENT_FILES))
{
push_state (info, STATE_RECENT_FILES);
}
else if (ELEMENT_IS (TAG_RECENT_ITEM))
{
info->current_item = gimp_recent_item_new ();
push_state (info, STATE_RECENT_ITEM);
}
else if (ELEMENT_IS (TAG_URI))
{
push_state (info, STATE_URI);
}
else if (ELEMENT_IS (TAG_MIME_TYPE))
{
push_state (info, STATE_MIME_TYPE);
}
else if (ELEMENT_IS (TAG_TIMESTAMP))
{
push_state (info, STATE_TIMESTAMP);
}
else if (ELEMENT_IS (TAG_PRIVATE))
{
push_state (info, STATE_PRIVATE);
gimp_recent_item_set_private (info->current_item, TRUE);
}
else if (ELEMENT_IS (TAG_GROUPS))
{
push_state (info, STATE_GROUPS);
}
else if (ELEMENT_IS (TAG_GROUP))
{
push_state (info, STATE_GROUP);
}
}
static void
end_element_handler (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error)
{
ParseInfo *info = user_data;
switch (peek_state (info))
{
case STATE_RECENT_ITEM:
info->items = g_list_prepend (info->items, info->current_item);
break;
default:
break;
}
pop_state (info);
}
static void
text_handler (GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error)
{
ParseInfo *info = user_data;
switch (peek_state (info))
{
case STATE_START:
case STATE_RECENT_FILES:
case STATE_RECENT_ITEM:
case STATE_PRIVATE:
case STATE_GROUPS:
break;
case STATE_URI:
gimp_recent_item_set_uri (info->current_item, text);
break;
case STATE_MIME_TYPE:
gimp_recent_item_set_mime_type (info->current_item, text);
break;
case STATE_TIMESTAMP:
gimp_recent_item_set_timestamp (info->current_item, (time_t) atoi (text));
break;
case STATE_GROUP:
gimp_recent_item_add_group (info->current_item, text);
break;
}
}
static void
gimp_recent_list_enforce_limit (GList *list,
gint limit)
{
gint len;
GList *end;
/* limit < 0 means unlimited */
if (limit <= 0)
return;
len = g_list_length (list);
if (len > limit)
{
GList *next;
end = g_list_nth (list, limit-1);
next = end->next;
end->next = NULL;
GIMP_RECENT_ITEM_LIST_UNREF (next);
}
}
static GList *
gimp_recent_list_read (gint fd)
{
GimpXmlParser *parser;
GList *list;
ParseInfo info;
GError *error = NULL;
lseek (fd, 0, SEEK_SET);
parse_info_init (&info);
parser = gimp_xml_parser_new (&markup_parser, &info);
if (! gimp_xml_parser_parse_fd (parser, fd, &error))
{
g_printerr ("%s", error->message);
g_error_free (error);
}
gimp_xml_parser_free (parser);
list = info.items;
parse_info_free (&info);
return g_list_reverse (list);
}
static gboolean
gimp_recent_list_write_raw (gint fd,
const gchar *content,
gssize len)
{
struct stat sbuf;
gssize remaining = len;
lseek (fd, 0, SEEK_SET);
if (fstat (fd, &sbuf) < 0)
{
g_warning ("Couldn't stat XML document.");
}
else
{
if ((off_t) len < sbuf.st_size)
ftruncate (fd, len);
}
while (remaining > 0)
{
gssize written = write (fd, content, remaining);
if (written < 0 && errno != EINTR)
return FALSE;
remaining -= written;
}
fsync (fd);
return TRUE;
}
static gboolean
gimp_recent_list_write (gint fd,
GList *list)
{
GString *string;
gboolean success;
string = g_string_new ("<?xml version=\"1.0\"?>\n");
string = g_string_append (string, "<" TAG_RECENT_FILES ">\n");
while (list)
{
GimpRecentItem *item = list->data;
const GList *groups;
gchar *uri;
const gchar *mime_type;
gchar *escaped_uri;
time_t timestamp;
uri = gimp_recent_item_get_uri_utf8 (item);
escaped_uri = g_markup_escape_text (uri, strlen (uri));
g_free (uri);
mime_type = gimp_recent_item_get_mime_type (item);
timestamp = gimp_recent_item_get_timestamp (item);
string = g_string_append (string, " <" TAG_RECENT_ITEM ">\n");
g_string_append_printf (string,
" <" TAG_URI ">%s</" TAG_URI ">\n", escaped_uri);
if (mime_type)
g_string_append_printf (string,
" <" TAG_MIME_TYPE ">%s</" TAG_MIME_TYPE ">\n", mime_type);
else
g_string_append_printf (string,
" <" TAG_MIME_TYPE "></" TAG_MIME_TYPE ">\n");
g_string_append_printf (string,
" <" TAG_TIMESTAMP ">%d</" TAG_TIMESTAMP ">\n", (gint) timestamp);
if (gimp_recent_item_get_private (item))
string = g_string_append (string,
" <" TAG_PRIVATE "/>\n");
groups = gimp_recent_item_get_groups (item);
if (groups)
{
/* write the groups */
string = g_string_append (string,
" <" TAG_GROUPS ">\n");
if (groups == NULL && gimp_recent_item_get_private (item))
g_warning ("Item with URI \"%s\" marked as private, but"
" does not belong to any groups.\n", uri);
while (groups)
{
const gchar *group = groups->data;
gchar *escaped_group;
escaped_group = g_markup_escape_text (group, strlen(group));
g_string_append_printf (string,
" <" TAG_GROUP ">%s</" TAG_GROUP ">\n",
escaped_group);
g_free (escaped_group);
groups = groups->next;
}
string = g_string_append (string, " </" TAG_GROUPS ">\n");
}
string = g_string_append (string,
" </" TAG_RECENT_ITEM ">\n");
g_free (escaped_uri);
list = list->next;
}
string = g_string_append (string, "</" TAG_RECENT_FILES ">");
success = gimp_recent_list_write_raw (fd, string->str, string->len);
g_string_free (string, TRUE);
return success;
}
static gboolean
gimp_recent_list_lock_file (gint fd)
{
gint i;
/* Attempt to lock the file 5 times,
* waiting a random interval (< 1 second)
* in between attempts.
* We should really be doing asynchronous
* locking, but requires substantially larger
* changes.
*/
lseek (fd, 0, SEEK_SET);
for (i = 0; i < 5; i++)
{
gint rand_interval;
if (lockf (fd, F_TLOCK, 0) == 0)
return TRUE;
rand_interval = 1 + (gint) (10.0 * rand () / (RAND_MAX + 1.0));
g_usleep (100000 * rand_interval);
}
return FALSE;
}
static gboolean
gimp_recent_list_unlock_file (gint fd)
{
lseek (fd, 0, SEEK_SET);
return (lockf (fd, F_ULOCK, 0) == 0) ? TRUE : FALSE;
}
static gboolean
gimp_recent_list_add_item (GimpRecentItem *item)
{
const gchar *home;
gchar *filename;
gint fd;
gboolean success = FALSE;
gboolean created = FALSE;
gboolean updated = FALSE;
home = g_get_home_dir ();
if (! home)
return FALSE;
filename = g_build_filename (home, GIMP_RECENT_LIST_FILE_NAME, NULL);
fd = g_open (filename, O_RDWR, 0);
if (fd < 0)
{
fd = g_creat (filename, S_IRUSR | S_IWUSR);
created = TRUE;
}
g_free (filename);
if (fd < 0)
return FALSE;
if (gimp_recent_list_lock_file (fd))
{
GList *list = NULL;
if (! created)
list = gimp_recent_list_read (fd);
/* if it's already there, we just update it */
updated = gimp_recent_list_update_item (list, item);
if (!updated)
{
list = g_list_prepend (list, item);
gimp_recent_list_enforce_limit (list, GIMP_RECENT_LIST_MAX_ITEMS);
}
/* write new stuff */
if (!gimp_recent_list_write (fd, list))
g_warning ("Write failed: %s", g_strerror (errno));
if (!updated)
list = g_list_remove (list, item);
GIMP_RECENT_ITEM_LIST_UNREF (list);
success = TRUE;
}
else
{
g_warning ("Failed to lock: %s", g_strerror (errno));
close (fd);
return FALSE;
}
if (! gimp_recent_list_unlock_file (fd))
g_warning ("Failed to unlock: %s", strerror (errno));
close (fd);
return success;
}
/**
* gimp_recent_list_add_uri:
* @uri: an URI
* @mime_type: a MIME type
*
* This function adds an item to the list of recently used URIs.
* See http://freedesktop.org/Standards/recent-file-spec/.
*
* On the Win32 platform, this call is unimplemented and will always
* fail.
*
* Returns: %TRUE on success, %FALSE otherwise
*/
gboolean
gimp_recent_list_add_uri (const gchar *uri,
const gchar *mime_type)
{
GimpRecentItem *item;
gboolean success;
g_return_val_if_fail (uri != NULL, FALSE);
if (! mime_type ||
! strlen (mime_type) ||
! g_utf8_validate (mime_type, -1, NULL))
return FALSE;
item = gimp_recent_item_new_from_uri (uri);
if (! item)
return FALSE;
gimp_recent_item_set_mime_type (item, mime_type);
gimp_recent_item_set_timestamp (item, -1);
gimp_recent_item_add_group (item, GIMP_RECENT_LIST_GROUP_GIMP);
success = gimp_recent_list_add_item (item);
gimp_recent_item_unref (item);
return success;
}
#else /* G_OS_WIN32 */
gboolean
gimp_recent_list_add_uri (const gchar *uri,
const gchar *mime_type)
{
return FALSE;
}
#endif

View File

@ -1,34 +0,0 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Recent File Storage,
* see http://freedesktop.org/Standards/recent-file-spec/
*
* This code is taken from libegg and has been adapted to the GIMP needs.
* The original author is James Willcox <jwillcox@cs.indiana.edu>,
* responsible for bugs in this version is 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_RECENT_LIST_H__
#define __GIMP_RECENT_LIST_H__
gboolean gimp_recent_list_add_uri (const gchar *uri,
const gchar *mime_type);
#endif /* __GIMP_RECENT_LIST_H__ */

View File

@ -116,7 +116,9 @@ static gboolean gui_pdb_dialog_set (Gimp *gimp,
static gboolean gui_pdb_dialog_close (Gimp *gimp,
GimpContainer *container,
const gchar *callback_name);
static gboolean gui_recent_list_add_uri (Gimp *gimp,
const gchar *uri,
const gchar *mime_type);
/* public functions */
@ -146,6 +148,7 @@ gui_vtable_init (Gimp *gimp)
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_uri = gui_recent_list_add_uri;
}
@ -540,3 +543,33 @@ gui_pdb_dialog_close (Gimp *gimp,
return FALSE;
}
static gboolean
gui_recent_list_add_uri (Gimp *gimp,
const gchar *uri,
const gchar *mime_type)
{
GtkRecentManager *mgr;
GtkRecentData recent;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
g_return_val_if_fail (mime_type != NULL, FALSE);
g_return_val_if_fail (strlen (mime_type) != 0, FALSE);
g_return_val_if_fail (g_utf8_validate (mime_type, -1, NULL), FALSE);
mgr = gtk_recent_manager_get_default ();
g_return_val_if_fail (mgr != NULL, FALSE);
/* use last part of the URI */
recent.display_name = NULL;
/* no special description */
recent.description = NULL;
recent.mime_type = mime_type;
recent.app_name = "gimp";
recent.app_exec = "gimp %u";
recent.groups = NULL;
recent.is_private = FALSE;
return gtk_recent_manager_add_full (mgr, uri, &recent);
}

View File

@ -158,7 +158,8 @@ gimp_dnd_xds_save_image (GdkDragContext *context,
! g_file_test (filename, G_FILE_TEST_EXISTS) ||
gimp_file_overwrite_dialog (NULL, uri))
{
if (file_save (image, gimp_get_user_context (image->gimp), NULL,
if (file_save (image->gimp, image,
gimp_get_user_context (image->gimp), NULL,
uri, proc, GIMP_RUN_INTERACTIVE, FALSE,
&error) == GIMP_PDB_SUCCESS)
{