gimp/app/docindex.c

764 lines
16 KiB
C
Raw Normal View History

/* docindex.c - Creates the window used by the document index in go and gimp.
1998-07-08 17:04:33 +08:00
*
* Copyright (C) 1998 Chris Lahey.
*
* 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, 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.
*/
#include "config.h"
#include <ctype.h>
1998-07-08 17:04:33 +08:00
#include <string.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include "dialog_handler.h"
#include "docindex.h"
#include "fileops.h"
#include "gimpdnd.h"
#include "session.h"
1999-03-07 21:23:06 +08:00
#include "libgimp/gimpenv.h"
#include "libgimp/gimpintl.h"
1999-03-07 21:23:06 +08:00
typedef struct
{
GtkWidget *window;
GtkWidget *list;
} IdeaManager;
typedef struct
{
gboolean boole;
gchar *string;
gpointer data;
} BoolCharPair;
static IdeaManager *ideas = NULL;
static GList *idea_list = NULL;
/* dnd stuff */
1998-07-08 17:04:33 +08:00
static GtkTargetEntry drag_types[] =
{
GIMP_TARGET_URI_LIST
};
static gint n_drag_types = sizeof (drag_types) / sizeof (drag_types[0]);
1998-07-08 17:04:33 +08:00
/* forward declarations */
1998-07-08 17:04:33 +08:00
static void create_idea_list (void);
static void idea_add_in_position (gchar *label,
gint position);
static void open_idea_window (void);
static void open_or_raise (gchar *file_name);
static void idea_up_callback (GtkWidget *widget,
gpointer data);
static void idea_down_callback (GtkWidget *widget,
gpointer data);
static void idea_remove_callback (GtkWidget *widget,
gpointer data);
static void idea_hide_callback (GtkWidget *widget,
gpointer data);
static gboolean idea_window_delete_event_callback (GtkWidget *widget,
GdkEvent *event,
gpointer data);
static void load_idea_manager (IdeaManager *ideas);
static void save_idea_manager (IdeaManager *ideas);
static void clear_white (FILE *fp);
static gint getinteger (FILE *fp);
/* public functions */
void
document_index_create (void)
1998-07-08 17:04:33 +08:00
{
if (ideas)
gdk_window_raise (ideas->window->window);
else
open_idea_window ();
}
void
document_index_free (void)
{
idea_hide_callback (NULL, NULL);
}
void
idea_add (gchar *title)
{
idea_add_in_position (title, 0);
}
FILE *
idea_manager_parse_init (void)
{
FILE *fp;
gchar *desktopfile;
desktopfile = gimp_personal_rc_file ("ideas");
fp = fopen (desktopfile, "r");
g_free (desktopfile);
return fp;
1998-07-08 17:04:33 +08:00
}
gchar *
idea_manager_parse_line (FILE * fp)
{
gint length;
gchar *filename;
length = getinteger (fp);
if (!feof (fp) && !ferror (fp))
{
filename = g_malloc0 (length + 1);
filename[fread (filename, 1, length, fp)] = 0;
clear_white (fp);
return filename;
}
return NULL;
}
/* local functions */
1998-07-08 17:04:33 +08:00
static void
docindex_dnd_filenames_dropped (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time)
{
gint len;
gchar *data;
gchar *end;
switch (info)
1998-07-08 17:04:33 +08:00
{
case GIMP_DND_TYPE_URI_LIST:
1998-10-20 06:36:01 +08:00
data = (gchar *) selection_data->data;
len = selection_data->length;
while (len > 0)
1998-07-08 17:04:33 +08:00
{
end = strstr (data, "\x0D\x0A");
if (end != NULL)
*end = 0;
if (*data != '#')
1998-10-20 06:36:01 +08:00
{
gchar *filename = strchr (data, ':');
if (filename != NULL)
1998-10-20 06:36:01 +08:00
filename ++;
else
filename = data;
file_open (filename, filename);
1998-10-20 06:36:01 +08:00
}
if (end)
{
len -= end - data + 2;
data = end + 2;
}
else
len = 0;
1998-07-08 17:04:33 +08:00
}
break;
1998-07-08 17:04:33 +08:00
}
return;
}
static void
load_from_list (gpointer data,
gpointer data_null)
{
idea_add_in_position ((gchar *) data, -1);
}
static void
load_idea_manager (IdeaManager *ideas)
{
FILE *fp = NULL;
if (! idea_list)
fp = idea_manager_parse_init ();
if (idea_list || fp)
{
gtk_widget_show (ideas->window);
if (fp)
1998-07-08 17:04:33 +08:00
{
gchar *title;
clear_white (fp);
while ((title = idea_manager_parse_line (fp)))
{
idea_add_in_position (title, -1);
g_free (title);
}
fclose (fp);
}
else
{
g_list_foreach (idea_list, load_from_list, NULL);
g_list_foreach (idea_list, (GFunc) g_free, NULL);
g_list_free (idea_list);
idea_list = 0;
1998-07-08 17:04:33 +08:00
}
}
else
{
gtk_widget_show (ideas->window);
}
1998-07-08 17:04:33 +08:00
}
static void
save_to_ideas (gpointer data,
gpointer user_data)
1998-07-08 17:04:33 +08:00
{
gchar *title;
title = GTK_LABEL (GTK_BIN (data)->child)->label;
fprintf ((FILE *) user_data, "%d %s\n", strlen (title), title);
1998-07-08 17:04:33 +08:00
}
static void
save_list_to_ideas (gpointer data,
gpointer user_data)
{
gchar *title;
title = (gchar *) data;
fprintf ((FILE *) user_data, "%d %s\n", strlen (title), title);
}
static void
save_idea_manager (IdeaManager *ideas)
1998-07-08 17:04:33 +08:00
{
FILE *fp;
1998-07-08 17:04:33 +08:00
gchar *desktopfile;
/* open persistant desktop file. */
1999-03-07 20:56:03 +08:00
desktopfile = gimp_personal_rc_file ("ideas");
fp = fopen (desktopfile, "w");
g_free (desktopfile);
1998-07-08 17:04:33 +08:00
if (fp)
{
if (ideas)
{
g_list_foreach (GTK_LIST (ideas->list)->children, save_to_ideas, fp);
}
else if (idea_list)
{
g_list_foreach (idea_list, save_list_to_ideas, fp);
}
fclose (fp);
}
1998-07-08 17:04:33 +08:00
}
static void
save_to_list (gpointer data,
gpointer null_data)
1998-07-08 17:04:33 +08:00
{
gchar *title;
title = g_strdup (GTK_LABEL (GTK_BIN (data)->child)->label);
idea_list = g_list_append (idea_list, title);
1998-07-08 17:04:33 +08:00
}
static void
create_idea_list (void)
1998-07-08 17:04:33 +08:00
{
if (idea_list)
1998-07-08 17:04:33 +08:00
{
g_list_foreach (idea_list, (GFunc) g_free, NULL);
g_list_free (idea_list);
idea_list = 0;
1998-07-08 17:04:33 +08:00
}
g_list_foreach (GTK_LIST (ideas->list)->children, save_to_list, NULL);
1998-07-08 17:04:33 +08:00
}
static gint
open_or_raise_callback (GtkWidget *widget,
GdkEventButton *event,
gpointer func_data)
1998-07-08 17:04:33 +08:00
{
if (GTK_IS_LIST_ITEM (widget) &&
event->type == GDK_2BUTTON_PRESS)
1998-07-08 17:04:33 +08:00
{
open_or_raise (GTK_LABEL (GTK_BIN (widget)->child)->label);
1998-07-08 17:04:33 +08:00
}
return FALSE;
}
static void
check_needed (gpointer data,
gpointer user_data)
1998-07-08 17:04:33 +08:00
{
BoolCharPair *pair;
pair = (BoolCharPair *) user_data;
if (strcmp (pair->string, GTK_LABEL (GTK_BIN (data)->child)->label) == 0)
1998-07-08 17:04:33 +08:00
{
pair->boole = TRUE;
pair->data = data;
1998-07-08 17:04:33 +08:00
}
}
static void
check_needed_list (gpointer data,
gpointer user_data)
{
BoolCharPair *pair;
pair = (BoolCharPair *) user_data;
if (strcmp (pair->string, (gchar *) data) == 0)
{
pair->boole = TRUE;
pair->data = data;
}
}
static void
idea_add_in_position_with_select (gchar *title,
gint position,
gboolean select)
1998-07-08 17:04:33 +08:00
{
BoolCharPair pair;
1998-07-08 17:04:33 +08:00
pair.boole = FALSE;
pair.string = title;
pair.data = NULL;
if (ideas)
1998-07-08 17:04:33 +08:00
{
g_list_foreach (GTK_LIST (ideas->list)->children, check_needed, &pair);
if (! pair.boole)
1998-07-08 17:04:33 +08:00
{
GtkWidget *listitem;
GList *list = NULL;
listitem = gtk_list_item_new_with_label (title);
list = g_list_append (list, listitem);
if (position < 0)
gtk_list_append_items (GTK_LIST (ideas->list), list);
1998-07-08 17:04:33 +08:00
else
gtk_list_insert_items (GTK_LIST (ideas->list), list, position);
gtk_signal_connect (GTK_OBJECT (listitem), "button_press_event",
GTK_SIGNAL_FUNC (open_or_raise_callback),
NULL);
gtk_widget_show (listitem);
if (select)
gtk_list_item_select (GTK_LIST_ITEM (listitem));
}
else /* move entry to top */
{
gchar *title;
title = g_strdup (GTK_LABEL (GTK_BIN (pair.data)->child)->label);
gtk_container_remove (GTK_CONTAINER (ideas->list),
GTK_WIDGET (pair.data));
idea_add_in_position_with_select (title, 0, TRUE);
g_free (title);
1998-07-08 17:04:33 +08:00
}
}
else
{
if (! idea_list)
{
FILE *fp;
fp = idea_manager_parse_init ();
if (fp)
{
gchar *filename;
while ((filename = idea_manager_parse_line (fp)))
{
idea_list = g_list_append (idea_list, g_strdup (filename));
g_free (filename);
}
fclose (fp);
}
}
g_list_foreach (idea_list, check_needed_list, &pair);
if (! pair.boole)
{
if (position < 0)
idea_list = g_list_prepend (idea_list, g_strdup (title));
else
idea_list = g_list_insert (idea_list, g_strdup (title), position);
}
else /* move entry to top */
{
idea_list = g_list_remove (idea_list, pair.data);
g_free (pair.data);
idea_list = g_list_prepend (idea_list, g_strdup (title));
}
}
1998-07-08 17:04:33 +08:00
}
static void
idea_add_in_position (gchar *title,
gint position)
1998-07-08 17:04:33 +08:00
{
idea_add_in_position_with_select (title, position, TRUE);
1998-07-08 17:04:33 +08:00
}
static void
raise_if_match (gpointer data,
gpointer user_data)
{
GDisplay *gdisp;
BoolCharPair *pair;
gdisp = (GDisplay *) data;
pair = (BoolCharPair *) user_data;
if (gdisp->gimage->has_filename &&
strcmp (pair->string, gdisp->gimage->filename) == 0)
{
pair->boole = TRUE;
gdk_window_raise (gdisp->shell->window);
}
}
static void
open_or_raise (gchar *file_name)
{
BoolCharPair pair;
pair.boole = FALSE;
pair.string = file_name;
pair.data = NULL;
gdisplays_foreach (raise_if_match, &pair);
if (! pair.boole)
{
file_open (file_name, file_name);
}
}
/* file parsing functions */
static gint
getinteger (FILE *fp)
{
gchar nextchar;
gint response = 0;
gboolean negative = FALSE;
while (isspace (nextchar = fgetc (fp)))
/* empty statement */ ;
if (nextchar == '-')
{
negative = TRUE;
while (isspace (nextchar = fgetc (fp)))
/* empty statement */ ;
}
for (; '0' <= nextchar && '9' >= nextchar; nextchar = fgetc (fp))
{
response *= 10;
response += nextchar - '0';
}
for (; isspace (nextchar); nextchar = fgetc (fp))
/* empty statement */ ;
ungetc (nextchar, fp);
if (negative)
response = -response;
return response;
}
static void
clear_white (FILE *fp)
{
gint nextchar;
while (isspace (nextchar = fgetc (fp)))
/* empty statement */ ;
if (nextchar != EOF)
ungetc (nextchar, fp);
}
/* toolbar / dialog callbacks */
static gint
idea_move (GtkWidget *widget,
gint distance,
gboolean select)
1998-07-08 17:04:33 +08:00
{
gint orig_position;
gint position;
1998-07-08 17:04:33 +08:00
gchar *title;
orig_position = g_list_index (GTK_LIST (ideas->list)->children, widget);
position = orig_position + distance;
if (position < 0)
1998-07-08 17:04:33 +08:00
position = 0;
if (position >= g_list_length (GTK_LIST (ideas->list)->children))
position = g_list_length (GTK_LIST (ideas->list)->children) - 1;
if (position != orig_position)
1998-07-08 17:04:33 +08:00
{
title = g_strdup (GTK_LABEL (GTK_BIN (widget)->child)->label);
gtk_container_remove (GTK_CONTAINER (ideas->list), widget);
idea_add_in_position_with_select (title, position, select);
g_free (title);
1998-07-08 17:04:33 +08:00
}
1998-07-08 17:04:33 +08:00
return position - orig_position;
}
static void
idea_up_callback (GtkWidget *widget,
gpointer data)
1998-07-08 17:04:33 +08:00
{
GtkWidget *selected;
if (GTK_LIST (ideas->list)->selection)
1998-07-08 17:04:33 +08:00
{
selected = GTK_LIST (ideas->list)->selection->data;
idea_move (selected, -1, TRUE);
1998-07-08 17:04:33 +08:00
}
}
static void
idea_down_callback (GtkWidget *widget,
gpointer data)
1998-07-08 17:04:33 +08:00
{
GtkWidget *selected;
if (GTK_LIST (ideas->list)->selection)
1998-07-08 17:04:33 +08:00
{
selected = GTK_LIST (ideas->list)->selection->data;
idea_move (selected, 1, TRUE);
1998-07-08 17:04:33 +08:00
}
}
static void
idea_remove (GtkWidget *widget)
{
gint position;
position = g_list_index (GTK_LIST (ideas->list)->children, widget);
gtk_container_remove (GTK_CONTAINER (ideas->list), widget);
if (g_list_length (GTK_LIST (ideas->list)->children) - 1 < position)
position = g_list_length (GTK_LIST (ideas->list)->children) - 1;
gtk_list_select_item (GTK_LIST (ideas->list), position);
}
static void
idea_remove_callback (GtkWidget *widget,
gpointer data)
1998-07-08 17:04:33 +08:00
{
GtkWidget *selected;
if (GTK_LIST (ideas->list)->selection)
1998-07-08 17:04:33 +08:00
{
selected = GTK_LIST (ideas->list)->selection->data;
idea_remove (selected);
1998-07-08 17:04:33 +08:00
}
}
static void
idea_hide_callback (GtkWidget *widget,
gpointer data)
{
if (ideas || idea_list)
save_idea_manager (ideas);
/* False if exitting */
if (ideas)
{
create_idea_list ();
dialog_unregister (ideas->window);
session_get_window_info (ideas->window, &document_index_session_info);
gtk_widget_destroy (ideas->window);
g_free (ideas);
ideas = 0;
}
}
static gboolean
idea_window_delete_event_callback (GtkWidget *widget,
GdkEvent *event,
gpointer data)
{
idea_hide_callback (NULL, NULL);
return TRUE;
}
static GtkWidget *
create_idea_toolbar (void)
{
GtkWidget *toolbar;
toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NONE);
gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
_("Open"),
_("Open a file"),
"Toolbar/Open",
NULL,
GTK_SIGNAL_FUNC (file_open_callback),
NULL);
gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
_("Up"),
_("Move the selected entry up in the index"),
"Toolbar/Up",
NULL,
GTK_SIGNAL_FUNC (idea_up_callback),
NULL);
gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
_("Down"),
_("Move the selected entry down in the index"),
"Toolbar/Down",
NULL,
GTK_SIGNAL_FUNC (idea_down_callback),
NULL);
gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
_("Remove"),
_("Remove the selected entry from the index"),
"Toolbar/Remove",
NULL,
GTK_SIGNAL_FUNC (idea_remove_callback),
NULL);
gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
_("Close"),
_("Close the Document Index"),
"Toolbar/Hide",
NULL,
GTK_SIGNAL_FUNC (idea_hide_callback),
NULL);
return toolbar;
}
static void
open_idea_window (void)
{
GtkWidget *main_vbox;
GtkWidget *scrolled_win;
GtkWidget *toolbar;
/* alloc idea_manager */
ideas = g_new0 (IdeaManager, 1);
ideas->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (ideas->window), 0);
gtk_window_set_title (GTK_WINDOW (ideas->window), _("Document Index"));
/* Connect the signals */
gtk_signal_connect (GTK_OBJECT (ideas->window), "delete_event",
GTK_SIGNAL_FUNC (idea_window_delete_event_callback),
NULL);
main_vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (ideas->window), main_vbox);
gtk_widget_show (main_vbox);
/* Toolbar */
toolbar = create_idea_toolbar ();
gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
gtk_widget_show (toolbar);
/* Scrolled window */
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS );
gtk_box_pack_start (GTK_BOX (main_vbox), scrolled_win, TRUE, TRUE, 0);
gtk_widget_show (scrolled_win);
/* Setup list */
ideas->list = gtk_list_new ();
gtk_list_set_selection_mode (GTK_LIST (ideas->list), GTK_SELECTION_BROWSE);
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
ideas->list);
gtk_widget_show (ideas->list);
gtk_drag_dest_set (ideas->window,
GTK_DEST_DEFAULT_MOTION |
GTK_DEST_DEFAULT_HIGHLIGHT |
GTK_DEST_DEFAULT_DROP,
drag_types, n_drag_types,
GDK_ACTION_COPY);
gtk_signal_connect (GTK_OBJECT (ideas->window), "drag_data_received",
GTK_SIGNAL_FUNC (docindex_dnd_filenames_dropped),
NULL);
dialog_register (ideas->window);
session_set_window_geometry (ideas->window, &document_index_session_info,
TRUE);
/* Connect the "F1" help key */
gimp_help_connect_help_accel (ideas->window,
gimp_standard_help_func,
"dialogs/document_index.html");
/* Load and Show window */
load_idea_manager (ideas);
}