From bdf6f37a8afa9988de108ac207b48de01fee6141 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Tue, 30 May 2000 06:32:14 +0000 Subject: Added a title bar for the folder view. Removed title bar from the shortcut view. Made shortcuts behave correctly when moved around. Also, implemented automatic re-saving of the shortcuts when they change. svn path=/trunk/; revision=3276 --- shell/ChangeLog | 56 ++++++ shell/Makefile.am | 2 + shell/e-shell-folder-title-bar.c | 378 +++++++++++++++++++++++++++++++++++++++ shell/e-shell-folder-title-bar.h | 77 ++++++++ shell/e-shell-view.c | 241 ++++++++++++++----------- shell/e-shell-view.h | 8 + shell/e-shell.c | 7 +- shell/e-shortcuts-view.c | 109 +++++++++-- shell/e-shortcuts.c | 245 +++++++++++++++++++++++-- shell/e-shortcuts.h | 17 +- 10 files changed, 1011 insertions(+), 129 deletions(-) create mode 100644 shell/e-shell-folder-title-bar.c create mode 100644 shell/e-shell-folder-title-bar.h (limited to 'shell') diff --git a/shell/ChangeLog b/shell/ChangeLog index 9fbd1f18b4..1a527fb022 100644 --- a/shell/ChangeLog +++ b/shell/ChangeLog @@ -1,5 +1,61 @@ 2000-05-30 Ettore Perazzoli + * e-shortcuts.c: New members `dirty', `save_idle_id' in + `EShortcutsPrivate'. + (init): Initialize. + (destroy): If the idle ID is nonzero, remove the idle. If `dirty' + is true, save. + (idle_cb): New. + (schedule_idle): New. + (make_dirty): New. + (e_shortcuts_remove_shortcut): Call it. + (e_shortcuts_add_shortcut): Likewise. + (e_shortcuts_remove_group): Likewise. + (e_shortcuts_add_group): Likewise. + + * e-shell.c (e_shell_construct): Updated to match the `EShortcuts' + API changes. + + * e-shortcuts.c: New member `file_name' in `EShortcutsPrivate'. + (init): Init to NULL. + (destroy): Free it. + (e_shortcuts_load): Removed. + (e_shortcuts_save): Removed. + (e_shortcuts_new): New arg @file_name. Load from the specified + file name. + + * e-shortcuts-view.c (added_item): New method implementation. + (removed_item): New method implementation. + (added_group): New method implementation. + (removed_group): New method implementation. + (class_init): Install these. + + * e-shortcuts.c (e_shortcuts_remove_shortcut): New function. + (e_shortcuts_add_shortcut): New function. + (e_shortcuts_remove_group): New function. + (e_shortcuts_add_group): New function. + + * e-shell-view.c: New member `view_title_bar' in + `EShellViewPrivate'. + (setup_widgets): Put an EShellFolderTitleBar on top of the tree + view and the content view. + (update_window_icon): Renamed from `set_icon'. + (update_folder_title_bar): New. + (popup_tree): New function to pop up the tree view when the title + button in the title bar is clicked. + (folder_title_clicked_cb): New callback for the "clicked" signal + of EShellFolderTitleBar. + (setup_widgets): Don't add a title bar to the shortcut bar. + (create_storage_set_subwindow): New helper function. + (setup_widgets): Use it. + (show_error): Use an EClippedLabel instead of a GtkLabel. + + * e-shell-view.c: Replaced all the occurences of `gpointer' with + `void *' for consistency. + + * e-shell-folder-title-bar.c: New file. + * e-shell-folder-title-bar.h: New file. + * e-storage-set-view.c (e_storage_set_view_construct): Ooops. Fix inverted key/value pair in the call to `g_hash_table_insert()'. diff --git a/shell/Makefile.am b/shell/Makefile.am index 19134e59b8..6141f9ce69 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -46,6 +46,8 @@ evolution_SOURCES = \ e-component-registry.h \ e-component-registry.c \ e-shell-constants.h \ + e-shell-folder-title-bar.c \ + e-shell-folder-title-bar.h \ e-shell-utils.c \ e-shell-utils.h \ e-shell-view-menu.c \ diff --git a/shell/e-shell-folder-title-bar.c b/shell/e-shell-folder-title-bar.c new file mode 100644 index 0000000000..0f38faccf1 --- /dev/null +++ b/shell/e-shell-folder-title-bar.c @@ -0,0 +1,378 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-folder-title-bar.c + * + * Copyright (C) 2000 Helix Code, Inc. + * + * 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. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "widgets/misc/e-clipped-label.h" +#include "e-util/e-util.h" + +#include "e-shell-constants.h" +#include "e-shell-folder-title-bar.h" + + +#define PARENT_TYPE GTK_TYPE_EVENT_BOX +static GtkEventBox *parent_class = NULL; + +struct _EShellFolderTitleBarPrivate { + GdkPixbuf *icon; + GtkWidget *icon_widget; + + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *button_hbox; + GtkWidget *button; +}; + +enum { + TITLE_CLICKED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +/* Icon handling. */ + +static unsigned int +rgb_from_gdk_color (GdkColor *color) +{ + return (((color->red >> 8) << 16) | + ((color->green >> 8) << 8) | + ((color->blue >> 8))); +} + +static GdkPixmap * +make_icon_pixmap (EShellFolderTitleBar *folder_title_bar, + const GdkPixbuf *pixbuf) +{ + GdkPixmap *pixmap; + GtkWidget *widget; + unsigned int depth; + unsigned int rgb; + + widget = GTK_WIDGET (folder_title_bar); + + rgb = rgb_from_gdk_color (&widget->style->bg[GTK_STATE_NORMAL]); + + depth = gtk_widget_get_visual (widget)->depth; + + pixmap = gdk_pixmap_new (GTK_WIDGET (folder_title_bar)->window, + E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, + depth); + + if (pixbuf == NULL) { + gdk_draw_rectangle (pixmap, widget->style->bg_gc[GTK_STATE_NORMAL], TRUE, + 0, 0, E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE); + } else { + GdkPixbuf *composited_pixbuf; + + composited_pixbuf = gdk_pixbuf_composite_color_simple + (pixbuf, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), + GDK_INTERP_NEAREST, 255, 32, rgb, rgb); + + gdk_pixbuf_render_to_drawable (composited_pixbuf, + pixmap, widget->style->fg_gc[GTK_STATE_NORMAL], + 0, 0, 0, 0, + E_SHELL_MINI_ICON_SIZE, E_SHELL_MINI_ICON_SIZE, + GDK_RGB_DITHER_MAX, 0, 0); + + gdk_pixbuf_unref (composited_pixbuf); + } + + return pixmap; +} + + +/* Style handling. */ + +static void +endarken_style (GtkWidget *widget) +{ + GtkStyle *style; + GtkRcStyle *new_rc_style; + int i; + + style = widget->style; + + new_rc_style = gtk_rc_style_new (); + + for (i = 0; i < 5; i++) { + new_rc_style->bg[i].red = style->bg[i].red * .8; + new_rc_style->bg[i].green = style->bg[i].green * .8; + new_rc_style->bg[i].blue = style->bg[i].blue * .8; + new_rc_style->fg[i].red = 0xffff; + new_rc_style->fg[i].green = 0xffff; + new_rc_style->fg[i].blue = 0xffff; + new_rc_style->color_flags[i] = GTK_RC_BG | GTK_RC_FG; + } + + gtk_widget_modify_style (widget, new_rc_style); + + gtk_rc_style_unref (new_rc_style); +} + +static void +style_set_cb (GtkWidget *widget, + GtkStyle *previous_style, + void *data) +{ + /* This will cause a style_set signal to be emitted again, so we need to do this to prevent infinite recursion. */ + gtk_signal_handler_block_by_func (GTK_OBJECT (widget), GTK_SIGNAL_FUNC (style_set_cb), data); + + endarken_style (widget); + + gtk_signal_handler_unblock_by_func (GTK_OBJECT (widget), GTK_SIGNAL_FUNC (style_set_cb), data); +} + +static void +endarken_and_connect_style_set_signal (GtkWidget *widget) +{ + endarken_style (widget); + gtk_signal_connect (GTK_OBJECT (widget), "style_set", + GTK_SIGNAL_FUNC (style_set_cb), NULL); +} + +static void +setup_style (EShellFolderTitleBar *folder_title_bar) +{ + EShellFolderTitleBarPrivate *priv; + + priv = folder_title_bar->priv; + + /* endarken_and_connect_style_set_signal (priv->button); */ + endarken_and_connect_style_set_signal (priv->label); + endarken_and_connect_style_set_signal (GTK_WIDGET (folder_title_bar)); +} + + +/* Button signals. */ + +static void +title_button_clicked_cb (GtkButton *button, + void *data) +{ + EShellFolderTitleBar *folder_title_bar; + + folder_title_bar = E_SHELL_FOLDER_TITLE_BAR (data); + + gtk_signal_emit (GTK_OBJECT (folder_title_bar), signals[TITLE_CLICKED]); +} + + +/* GTkWidget methods. */ + +static void +realize (GtkWidget *widget) +{ + EShellFolderTitleBar *folder_title_bar; + EShellFolderTitleBarPrivate *priv; + GdkPixmap *pixmap; + + (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); + + folder_title_bar = E_SHELL_FOLDER_TITLE_BAR (widget); + priv = folder_title_bar->priv; + + pixmap = make_icon_pixmap (folder_title_bar, priv->icon); + priv->icon_widget = gtk_pixmap_new (pixmap, NULL); + gdk_pixmap_unref (pixmap); + gtk_widget_show (priv->icon_widget); + + gtk_misc_set_alignment (GTK_MISC (priv->icon_widget), 1.0, .5); + gtk_misc_set_padding (GTK_MISC (priv->icon_widget), 5, 0); + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->icon_widget, TRUE, TRUE, 2); +} + +static void +unrealize (GtkWidget *widget) +{ + EShellFolderTitleBar *folder_title_bar; + EShellFolderTitleBarPrivate *priv; + + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); + + folder_title_bar = E_SHELL_FOLDER_TITLE_BAR (widget); + priv = folder_title_bar->priv; + + gtk_widget_destroy (priv->icon_widget); + priv->icon_widget = NULL; +} + + +/* GtkObject methods. */ + +static void +destroy (GtkObject *object) +{ + EShellFolderTitleBar *folder_title_bar; + EShellFolderTitleBarPrivate *priv; + + folder_title_bar = E_SHELL_FOLDER_TITLE_BAR (object); + priv = folder_title_bar->priv; + + g_free (priv); + + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + +static void +class_init (EShellFolderTitleBarClass *klass) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = GTK_OBJECT_CLASS (klass); + object_class->destroy = destroy; + + widget_class = GTK_WIDGET_CLASS (klass); + widget_class->realize = realize; + widget_class->unrealize = unrealize; + + parent_class = gtk_type_class (PARENT_TYPE); + + signals[TITLE_CLICKED] = gtk_signal_new ("title_clicked", + GTK_RUN_FIRST, + object_class->type, + GTK_SIGNAL_OFFSET (EShellFolderTitleBarClass, title_clicked), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); + + gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); +} + +static void +init (EShellFolderTitleBar *shell_folder_title_bar) +{ + EShellFolderTitleBarPrivate *priv; + + priv = g_new (EShellFolderTitleBarPrivate, 1); + priv->icon = NULL; + priv->icon_widget = NULL; + priv->hbox = NULL; + priv->label = NULL; + priv->button_hbox = NULL; + priv->button = NULL; + + shell_folder_title_bar->priv = priv; +} + + +void +e_shell_folder_title_bar_construct (EShellFolderTitleBar *folder_title_bar) +{ + EShellFolderTitleBarPrivate *priv; + GtkWidget *widget; + + g_return_if_fail (folder_title_bar != NULL); + g_return_if_fail (E_IS_SHELL_FOLDER_TITLE_BAR (folder_title_bar)); + + priv = folder_title_bar->priv; + widget = GTK_WIDGET (folder_title_bar); + + priv->label = e_clipped_label_new (""); + gtk_misc_set_padding (GTK_MISC (priv->label), 5, 0); + gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5); + gtk_widget_show (priv->label); + +#if 0 + priv->button = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (priv->button), GTK_RELIEF_NONE); + gtk_container_add (GTK_CONTAINER (priv->button), priv->label); + GTK_WIDGET_UNSET_FLAGS (priv->button, GTK_CAN_FOCUS); + gtk_widget_show (priv->button); +#endif + + priv->hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->label, TRUE, TRUE, 0); + + gtk_widget_show (priv->hbox); + +#if 0 + gtk_signal_connect (GTK_OBJECT (priv->button), "clicked", + GTK_SIGNAL_FUNC (title_button_clicked_cb), folder_title_bar); +#endif + + gtk_container_add (GTK_CONTAINER (folder_title_bar), priv->hbox); + + setup_style (folder_title_bar); + + e_shell_folder_title_bar_set_title (folder_title_bar, NULL); +} + +GtkWidget * +e_shell_folder_title_bar_new (void) +{ + EShellFolderTitleBar *new; + + new = gtk_type_new (e_shell_folder_title_bar_get_type ()); + + e_shell_folder_title_bar_construct (new); + + return GTK_WIDGET (new); +} + +void +e_shell_folder_title_bar_set_title (EShellFolderTitleBar *folder_title_bar, + const char *title) +{ + EShellFolderTitleBarPrivate *priv; + + g_return_if_fail (folder_title_bar != NULL); + g_return_if_fail (E_IS_SHELL_FOLDER_TITLE_BAR (folder_title_bar)); + + priv = folder_title_bar->priv; + + if (title == NULL) + e_clipped_label_set_text (E_CLIPPED_LABEL (priv->label), _("(Untitled)")); + else + e_clipped_label_set_text (E_CLIPPED_LABEL (priv->label), title); + + /* FIXME: There seems to be a bug in EClippedLabel, this is just a workaround. */ + gtk_widget_queue_draw (GTK_WIDGET (folder_title_bar)); +} + +void +e_shell_folder_title_bar_set_icon (EShellFolderTitleBar *folder_title_bar, + const GdkPixbuf *icon) +{ + EShellFolderTitleBarPrivate *priv; + GdkPixmap *pixmap; + + g_return_if_fail (folder_title_bar != NULL); + g_return_if_fail (E_IS_SHELL_FOLDER_TITLE_BAR (folder_title_bar)); + + priv = folder_title_bar->priv; + + pixmap = make_icon_pixmap (folder_title_bar, icon); + + gtk_pixmap_set (GTK_PIXMAP (priv->icon_widget), pixmap, NULL); +} + + +E_MAKE_TYPE (e_shell_folder_title_bar, "EShellFolderTitleBar", EShellFolderTitleBar, class_init, init, PARENT_TYPE) diff --git a/shell/e-shell-folder-title-bar.h b/shell/e-shell-folder-title-bar.h new file mode 100644 index 0000000000..80258ad336 --- /dev/null +++ b/shell/e-shell-folder-title-bar.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-folder-title-bar.h + * + * Copyright (C) 2000 Helix Code, Inc. + * + * 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. + * + * Author: Ettore Perazzoli + */ + +#ifndef __E_SHELL_FOLDER_TITLE_BAR_H__ +#define __E_SHELL_FOLDER_TITLE_BAR_H__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_SHELL_FOLDER_TITLE_BAR (e_shell_folder_title_bar_get_type ()) +#define E_SHELL_FOLDER_TITLE_BAR(obj) (GTK_CHECK_CAST ((obj), E_TYPE_SHELL_FOLDER_TITLE_BAR, EShellFolderTitleBar)) +#define E_SHELL_FOLDER_TITLE_BAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_FOLDER_TITLE_BAR, EShellFolderTitleBarClass)) +#define E_IS_SHELL_FOLDER_TITLE_BAR(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_SHELL_FOLDER_TITLE_BAR)) +#define E_IS_SHELL_FOLDER_TITLE_BAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_FOLDER_TITLE_BAR)) + + +typedef struct _EShellFolderTitleBar EShellFolderTitleBar; +typedef struct _EShellFolderTitleBarPrivate EShellFolderTitleBarPrivate; +typedef struct _EShellFolderTitleBarClass EShellFolderTitleBarClass; + +struct _EShellFolderTitleBar { + GtkEventBox parent; + + EShellFolderTitleBarPrivate *priv; +}; + +struct _EShellFolderTitleBarClass { + GtkEventBoxClass parent_class; + + /* Signals. */ + void (* title_clicked) (EShellFolderTitleBar *folder_title_bar); +}; + + +GtkType e_shell_folder_title_bar_get_type (void); +void e_shell_folder_title_bar_construct (EShellFolderTitleBar *folder_title_bar); +GtkWidget *e_shell_folder_title_bar_new (void); + +void e_shell_folder_title_bar_set_title (EShellFolderTitleBar *folder_title_bar, + const char *title); +void e_shell_folder_title_bar_set_icon (EShellFolderTitleBar *folder_title_bar, + const GdkPixbuf *icon); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __E_SHELL_FOLDER_TITLE_BAR_H__ */ diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index c2b6816a25..f1774640ac 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -32,12 +32,16 @@ #include #include +#include "widgets/misc/e-clipped-label.h" +#include "e-util/e-util.h" + +#include "e-shell-constants.h" +#include "e-shell-folder-title-bar.h" #include "e-shell-utils.h" #include "e-shell.h" #include "e-shortcuts-view.h" #include "e-storage-set-view.h" #include "e-title-bar.h" -#include "e-util/e-util.h" #include "e-shell-view.h" #include "e-shell-view-menu.h" @@ -59,12 +63,13 @@ struct _EShellViewPrivate { char *uri; /* The widgetry. */ - GtkWidget *hpaned1; - GtkWidget *hpaned2; + GtkWidget *hpaned; + GtkWidget *view_vbox; + GtkWidget *view_title_bar; + GtkWidget *view_hpaned; GtkWidget *contents; GtkWidget *notebook; GtkWidget *shortcut_bar; - GtkWidget *shortcut_bar_box; GtkWidget *storage_set_view; GtkWidget *storage_set_view_box; @@ -73,14 +78,10 @@ struct _EShellViewPrivate { /* Position of the handles in the paneds, to be restored when we show elements after hiding them. */ - unsigned int hpaned1_position; - unsigned int hpaned2_position; + unsigned int hpaned_position; + unsigned int view_hpaned_position; }; -/* FIXME this should probably go somewhere else. */ -#define EVOLUTION_URI_PREFIX "evolution:" -#define EVOLUTION_URI_PREFIX_LEN 10 - #define DEFAULT_SHORTCUT_BAR_WIDTH 100 #define DEFAULT_TREE_WIDTH 100 @@ -88,12 +89,14 @@ struct _EShellViewPrivate { #define DEFAULT_HEIGHT 600 +/* Utility functions. */ + static GtkWidget * create_label_for_empty_page (void) { GtkWidget *label; - label = gtk_label_new (_("(No folder displayed)")); + label = e_clipped_label_new (_("(No folder displayed)")); gtk_widget_show (label); return label; @@ -116,6 +119,7 @@ setup_menus (EShellView *shell_view) bonobo_ui_handler_menu_free_list (list); } +/* FIXME this is broken. */ static gboolean bonobo_widget_is_dead (BonoboWidget *bonobo_widget) { @@ -142,7 +146,7 @@ static void activate_shortcut_cb (EShortcutsView *shortcut_view, EShortcuts *shortcuts, const char *uri, - gpointer data) + void *data) { EShellView *shell_view; @@ -155,14 +159,14 @@ activate_shortcut_cb (EShortcutsView *shortcut_view, static void folder_selected_cb (EStorageSetView *storage_set_view, const char *path, - gpointer data) + void *data) { EShellView *shell_view; char *uri; shell_view = E_SHELL_VIEW (data); - uri = g_strconcat (EVOLUTION_URI_PREFIX, path, NULL); + uri = g_strconcat (E_SHELL_URI_PREFIX, path, NULL); e_shell_view_display_uri (shell_view, uri); g_free (uri); } @@ -170,7 +174,7 @@ folder_selected_cb (EStorageSetView *storage_set_view, /* Callback called when the close button on the tree's title bar is clicked. */ static void storage_set_view_close_button_clicked_cb (ETitleBar *title_bar, - gpointer data) + void *data) { EShellView *shell_view; @@ -179,26 +183,52 @@ storage_set_view_close_button_clicked_cb (ETitleBar *title_bar, e_shell_view_show_folders (shell_view, FALSE); } -/* Callback called when the close button on the shorcut bar's title bar is clicked. */ + +/* Widget setup. */ + static void -shortcut_bar_close_button_clicked_cb (ETitleBar *title_bar, - gpointer data) +setup_storage_set_subwindow (EShellView *shell_view) { - EShellView *shell_view; + EShellViewPrivate *priv; + GtkWidget *storage_set_view; + GtkWidget *title_bar; + GtkWidget *vbox; + GtkWidget *scrolled_window; - shell_view = E_SHELL_VIEW (data); + priv = shell_view->priv; + + storage_set_view = e_storage_set_view_new (e_shell_get_storage_set (priv->shell)); + gtk_signal_connect (GTK_OBJECT (storage_set_view), "folder_selected", + GTK_SIGNAL_FUNC (folder_selected_cb), shell_view); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - e_shell_view_show_shortcuts (shell_view, FALSE); + gtk_container_add (GTK_CONTAINER (scrolled_window), storage_set_view); + + vbox = gtk_vbox_new (FALSE, 0); + title_bar = e_title_bar_new (_("Folders")); + + gtk_box_pack_start (GTK_BOX (vbox), title_bar, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0); + + gtk_signal_connect (GTK_OBJECT (title_bar), "close_button_clicked", + GTK_SIGNAL_FUNC (storage_set_view_close_button_clicked_cb), shell_view); + + gtk_widget_show (vbox); + gtk_widget_show (storage_set_view); + gtk_widget_show (title_bar); + gtk_widget_show (scrolled_window); + + priv->storage_set_view_box = vbox; + priv->storage_set_view = storage_set_view; } - static void setup_widgets (EShellView *shell_view) { EShellViewPrivate *priv; - GtkWidget *shortcut_bar_title_bar; - GtkWidget *storage_set_view_title_bar; - GtkWidget *storage_set_view_scrolled_window; priv = shell_view->priv; @@ -208,42 +238,9 @@ setup_widgets (EShellView *shell_view) gtk_signal_connect (GTK_OBJECT (priv->shortcut_bar), "activate_shortcut", GTK_SIGNAL_FUNC (activate_shortcut_cb), shell_view); - priv->shortcut_bar_box = gtk_vbox_new (FALSE, 0); - - shortcut_bar_title_bar = e_title_bar_new (_("Shortcuts")); - gtk_widget_show (shortcut_bar_title_bar); - - gtk_box_pack_start (GTK_BOX (priv->shortcut_bar_box), shortcut_bar_title_bar, - FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (priv->shortcut_bar_box), priv->shortcut_bar, - TRUE, TRUE, 0); - - gtk_signal_connect (GTK_OBJECT (shortcut_bar_title_bar), "close_button_clicked", - GTK_SIGNAL_FUNC (shortcut_bar_close_button_clicked_cb), shell_view); - /* The storage set view. */ - priv->storage_set_view = e_storage_set_view_new (e_shell_get_storage_set (priv->shell)); - gtk_signal_connect (GTK_OBJECT (priv->storage_set_view), "folder_selected", - GTK_SIGNAL_FUNC (folder_selected_cb), shell_view); - - storage_set_view_scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (storage_set_view_scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - - gtk_container_add (GTK_CONTAINER (storage_set_view_scrolled_window), - priv->storage_set_view); - - priv->storage_set_view_box = gtk_vbox_new (FALSE, 0); - storage_set_view_title_bar = e_title_bar_new (_("Folders")); - - gtk_box_pack_start (GTK_BOX (priv->storage_set_view_box), storage_set_view_title_bar, - FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (priv->storage_set_view_box), storage_set_view_scrolled_window, - TRUE, TRUE, 0); - - gtk_signal_connect (GTK_OBJECT (storage_set_view_title_bar), "close_button_clicked", - GTK_SIGNAL_FUNC (storage_set_view_close_button_clicked_cb), shell_view); + setup_storage_set_subwindow (shell_view); /* The tabless notebook which we used to contain the views. */ @@ -257,32 +254,37 @@ setup_widgets (EShellView *shell_view) /* Put things into a paned and the paned into the GnomeApp. */ - priv->hpaned2 = e_hpaned_new (); - e_paned_add1 (E_PANED (priv->hpaned2), priv->storage_set_view_box); - e_paned_add2 (E_PANED (priv->hpaned2), priv->notebook); - e_paned_set_position (E_PANED (priv->hpaned2), DEFAULT_SHORTCUT_BAR_WIDTH); + priv->view_vbox = gtk_vbox_new (FALSE, 0); + + priv->view_title_bar = e_shell_folder_title_bar_new (); + + priv->view_hpaned = e_hpaned_new (); + e_paned_add1 (E_PANED (priv->view_hpaned), priv->storage_set_view_box); + e_paned_add2 (E_PANED (priv->view_hpaned), priv->notebook); + e_paned_set_position (E_PANED (priv->view_hpaned), DEFAULT_SHORTCUT_BAR_WIDTH); - priv->hpaned1 = e_hpaned_new (); - e_paned_add1 (E_PANED (priv->hpaned1), priv->shortcut_bar_box); - e_paned_add2 (E_PANED (priv->hpaned1), priv->hpaned2); - e_paned_set_position (E_PANED (priv->hpaned1), DEFAULT_SHORTCUT_BAR_WIDTH); + gtk_box_pack_start (GTK_BOX (priv->view_vbox), priv->view_title_bar, + FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->view_vbox), priv->view_hpaned, + TRUE, TRUE, 2); - gtk_container_set_border_width (GTK_CONTAINER (priv->hpaned1), 0); - gtk_container_set_border_width (GTK_CONTAINER (priv->hpaned2), 0); + priv->hpaned = e_hpaned_new (); + e_paned_add1 (E_PANED (priv->hpaned), priv->shortcut_bar); + e_paned_add2 (E_PANED (priv->hpaned), priv->view_vbox); + e_paned_set_position (E_PANED (priv->hpaned), DEFAULT_SHORTCUT_BAR_WIDTH); - gnome_app_set_contents (GNOME_APP (shell_view), priv->hpaned1); + gnome_app_set_contents (GNOME_APP (shell_view), priv->hpaned); /* Show stuff. */ gtk_widget_show (priv->shortcut_bar); - gtk_widget_show (priv->shortcut_bar_box); gtk_widget_show (priv->storage_set_view); gtk_widget_show (priv->storage_set_view_box); - gtk_widget_show (storage_set_view_scrolled_window); - gtk_widget_show (storage_set_view_title_bar); gtk_widget_show (priv->notebook); - gtk_widget_show (priv->hpaned1); - gtk_widget_show (priv->hpaned2); + gtk_widget_show (priv->hpaned); + gtk_widget_show (priv->view_hpaned); + gtk_widget_show (priv->view_vbox); + gtk_widget_show (priv->view_title_bar); /* FIXME: Session management and stuff? */ gtk_window_set_default_size (GTK_WINDOW (shell_view), DEFAULT_WIDTH, DEFAULT_HEIGHT); @@ -292,9 +294,9 @@ setup_widgets (EShellView *shell_view) /* GtkObject methods. */ static void -hash_forall_destroy_control (gpointer name, - gpointer value, - gpointer data) +hash_forall_destroy_control (void *name, + void *value, + void *data) { CORBA_Object corba_control; CORBA_Environment ev; @@ -355,17 +357,16 @@ init (EShellView *shell_view) priv->shell = NULL; priv->uih = NULL; priv->uri = NULL; - priv->hpaned1 = NULL; - priv->hpaned2 = NULL; + priv->hpaned = NULL; + priv->view_hpaned = NULL; priv->contents = NULL; priv->notebook = NULL; priv->storage_set_view = NULL; priv->storage_set_view_box = NULL; priv->shortcut_bar = NULL; - priv->shortcut_bar_box = NULL; - priv->hpaned1_position = 0; - priv->hpaned2_position = 0; + priv->hpaned_position = 0; + priv->view_hpaned_position = 0; priv->uri_to_control = g_hash_table_new (g_str_hash, g_str_equal); @@ -425,15 +426,15 @@ get_storage_set_path_from_uri (const char *uri) if (! g_path_is_absolute (colon + 1)) return NULL; - if (g_strncasecmp (uri, EVOLUTION_URI_PREFIX, colon - uri) != 0) + if (g_strncasecmp (uri, E_SHELL_URI_PREFIX, colon - uri) != 0) return NULL; return colon + 1; } static void -set_icon (EShellView *shell_view, - EFolder *folder) +update_window_icon (EShellView *shell_view, + EFolder *folder) { EShellViewPrivate *priv; const char *type; @@ -442,7 +443,11 @@ set_icon (EShellView *shell_view, priv = shell_view->priv; - type = e_folder_get_type_string (folder); + if (folder == NULL) + type = NULL; + else + type = e_folder_get_type_string (folder); + if (type == NULL) { icon_path = NULL; } else { @@ -464,6 +469,38 @@ set_icon (EShellView *shell_view, } } +static void +update_folder_title_bar (EShellView *shell_view, + EFolder *folder) +{ + EShellViewPrivate *priv; + EFolderTypeRegistry *folder_type_registry; + GdkPixbuf *folder_icon; + const char *folder_name; + const char *folder_type_name; + + priv = shell_view->priv; + + if (folder == NULL) + folder_type_name = NULL; + else + folder_type_name = e_folder_get_type_string (folder); + + if (folder_type_name == NULL) { + folder_name = NULL; + folder_icon = NULL; + } else { + folder_type_registry = e_shell_get_folder_type_registry (priv->shell); + folder_icon = e_folder_type_registry_get_icon_for_type (folder_type_registry, + folder_type_name, + TRUE); + folder_name = e_folder_get_name (folder); + } + + e_shell_folder_title_bar_set_icon (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar), folder_icon); + e_shell_folder_title_bar_set_title (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar), folder_name); +} + static void update_for_current_uri (EShellView *shell_view) { @@ -492,7 +529,9 @@ update_for_current_uri (EShellView *shell_view) gtk_window_set_title (GTK_WINDOW (shell_view), window_title); g_free (window_title); - set_icon (shell_view, folder); + update_folder_title_bar (shell_view, folder); + + update_window_icon (shell_view, folder); gtk_signal_handler_block_by_func (GTK_OBJECT (priv->storage_set_view), GTK_SIGNAL_FUNC (folder_selected_cb), @@ -554,8 +593,8 @@ show_error (EShellView *shell_view, priv = shell_view->priv; - s = g_strdup_printf (_("Cannot open location: %s\n"), uri); - label = gtk_label_new (s); + s = g_strdup_printf (_("Cannot open location: %s"), uri); + label = e_clipped_label_new (s); g_free (s); gtk_widget_show (label); @@ -736,7 +775,7 @@ e_shell_view_display_uri (EShellView *shell_view, g_free (priv->uri); priv->uri = g_strdup (uri); - if (strncmp (uri, EVOLUTION_URI_PREFIX, EVOLUTION_URI_PREFIX_LEN) != 0) { + if (strncmp (uri, E_SHELL_URI_PREFIX, E_SHELL_URI_PREFIX_LEN) != 0) { show_error (shell_view, uri); return FALSE; } @@ -775,16 +814,16 @@ e_shell_view_show_shortcuts (EShellView *shell_view, priv = shell_view->priv; if (show) { - if (! GTK_WIDGET_VISIBLE (priv->shortcut_bar_box)) { - gtk_widget_show (priv->shortcut_bar_box); - e_paned_set_position (E_PANED (priv->hpaned1), priv->hpaned1_position); + if (! GTK_WIDGET_VISIBLE (priv->shortcut_bar)) { + gtk_widget_show (priv->shortcut_bar); + e_paned_set_position (E_PANED (priv->hpaned), priv->hpaned_position); } } else { - if (GTK_WIDGET_VISIBLE (priv->shortcut_bar_box)) { - gtk_widget_hide (priv->shortcut_bar_box); + if (GTK_WIDGET_VISIBLE (priv->shortcut_bar)) { + gtk_widget_hide (priv->shortcut_bar); /* FIXME this is a private field! */ - priv->hpaned1_position = E_PANED (priv->hpaned1)->child1_size; - e_paned_set_position (E_PANED (priv->hpaned1), 0); + priv->hpaned_position = E_PANED (priv->hpaned)->child1_size; + e_paned_set_position (E_PANED (priv->hpaned), 0); } } } @@ -803,14 +842,14 @@ e_shell_view_show_folders (EShellView *shell_view, if (show) { if (! GTK_WIDGET_VISIBLE (priv->storage_set_view_box)) { gtk_widget_show (priv->storage_set_view_box); - e_paned_set_position (E_PANED (priv->hpaned2), priv->hpaned2_position); + e_paned_set_position (E_PANED (priv->view_hpaned), priv->view_hpaned_position); } } else { if (GTK_WIDGET_VISIBLE (priv->storage_set_view_box)) { gtk_widget_hide (priv->storage_set_view_box); /* FIXME this is a private field! */ - priv->hpaned2_position = E_PANED (priv->hpaned2)->child1_size; - e_paned_set_position (E_PANED (priv->hpaned2), 0); + priv->view_hpaned_position = E_PANED (priv->view_hpaned)->child1_size; + e_paned_set_position (E_PANED (priv->view_hpaned), 0); } } } diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index 10745b5c62..d0ac824a96 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -48,6 +48,14 @@ typedef struct _EShellView EShellView; typedef struct _EShellViewPrivate EShellViewPrivate; typedef struct _EShellViewClass EShellViewClass; +enum _EShellViewShowFoldersMode { + E_SHELL_VIEW_SHOW_FOLDERS_HIDDEN, + E_SHELL_VIEW_SHOW_FOLDERS_TRANSIENT, + E_SHELL_VIEW_SHOW_FOLDERS_STICKY +}; +typedef enum _EShellViewShowFoldersMode EShellViewShowFoldersMode; + + struct _EShellView { GnomeApp parent; diff --git a/shell/e-shell.c b/shell/e-shell.c index ec61116534..4378343973 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -351,11 +351,12 @@ e_shell_construct (EShell *shell, setup_components (shell); - priv->shortcuts = e_shortcuts_new (priv->storage_set, priv->folder_type_registry); - shortcut_path = g_concat_dir_and_file (local_directory, "shortcuts.xml"); + priv->shortcuts = e_shortcuts_new (priv->storage_set, + priv->folder_type_registry, + shortcut_path); - if (! e_shortcuts_load (priv->shortcuts, shortcut_path)) { + if (priv->shortcuts == NULL) { gtk_object_unref (GTK_OBJECT (priv->shortcuts)); priv->shortcuts = NULL; diff --git a/shell/e-shortcuts-view.c b/shell/e-shortcuts-view.c index c9fa17653c..8e4bbea50c 100644 --- a/shell/e-shortcuts-view.c +++ b/shell/e-shortcuts-view.c @@ -72,17 +72,16 @@ get_storage_set_path_from_uri (const char *uri) static void load_group (EShortcutsView *shortcuts_view, + EShortcuts *shortcuts, const char *group_title, int group_num) { EShortcutsViewPrivate *priv; - EShortcuts *shortcuts; EStorageSet *storage_set; GList *shortcut_list; GList *p; priv = shortcuts_view->priv; - shortcuts = priv->shortcuts; storage_set = e_shortcuts_get_storage_set (shortcuts); g_assert (storage_set != NULL); @@ -117,16 +116,15 @@ load_group (EShortcutsView *shortcuts_view, } static void -load_all_shortcuts (EShortcutsView *shortcuts_view) +load_all_shortcuts (EShortcutsView *shortcuts_view, + EShortcuts *shortcuts) { EShortcutsViewPrivate *priv; - EShortcuts *shortcuts; GList *group_titles; GList *p; int group_num; priv = shortcuts_view->priv; - shortcuts = priv->shortcuts; group_titles = e_shortcuts_get_group_titles (shortcuts); @@ -137,10 +135,13 @@ load_all_shortcuts (EShortcutsView *shortcuts_view) group_num = e_shortcut_bar_add_group (E_SHORTCUT_BAR (shortcuts_view), group_title); - load_group (shortcuts_view, group_title, group_num); + load_group (shortcuts_view, shortcuts, group_title, group_num); } e_free_string_list (group_titles); + + gtk_object_ref (GTK_OBJECT (shortcuts)); + priv->shortcuts = shortcuts; } /* Icon callback for the shortcut bar. */ @@ -180,6 +181,8 @@ icon_callback (EShortcutBar *shortcut_bar, } +/* GtkObject methods. */ + static void destroy (GtkObject *object) { @@ -195,6 +198,8 @@ destroy (GtkObject *object) } +/* EShortcutBar methods. */ + static void selected_item (EShortcutBar *shortcut_bar, GdkEvent *event, @@ -216,6 +221,89 @@ selected_item (EShortcutBar *shortcut_bar, shortcuts, uri); } +static void +added_item (EShortcutBar *shortcut_bar, + int group_num, + int item_num) +{ + EShortcutsViewPrivate *priv; + EShortcutBarGroup *group; + EShortcuts *shortcuts; + const char *url; + + priv = E_SHORTCUTS_VIEW (shortcut_bar)->priv; + shortcuts = priv->shortcuts; + + if (shortcuts == NULL) + return; + + /* FIXME ** NASTY ** */ + + group = &g_array_index (shortcut_bar->groups, EShortcutBarGroup, group_num); + url = e_icon_bar_get_item_data (E_ICON_BAR (group->icon_bar), item_num); + + if (url == NULL) { + g_warning ("NULL URL being added to the shortcut bar!?"); + return; + } + + e_shortcuts_add_shortcut (shortcuts, group_num, item_num, url); +} + +static void +removed_item (EShortcutBar *shortcut_bar, + int group_num, + int item_num) +{ + EShortcutsViewPrivate *priv; + EShortcuts *shortcuts; + + priv = E_SHORTCUTS_VIEW (shortcut_bar)->priv; + shortcuts = priv->shortcuts; + + e_shortcuts_remove_shortcut (shortcuts, group_num, item_num); +} + +static void +added_group (EShortcutBar *shortcut_bar, + int group_num) +{ + EShortcutsViewPrivate *priv; + EShortcuts *shortcuts; + EShortcutBarGroup *group; + const char *group_name; + + priv = E_SHORTCUTS_VIEW (shortcut_bar)->priv; + shortcuts = priv->shortcuts; + + if (shortcuts == NULL) + return; + + group = &g_array_index (shortcut_bar->groups, EShortcutBarGroup, group_num); + + /* FIXME Losing EShortcutBar does not give me a method to retrieve the + group name. */ + group_name = "Foo"; + + e_shortcuts_add_group (shortcuts, group_num, group_name); +} + +static void +removed_group (EShortcutBar *shortcut_bar, + int group_num) +{ + EShortcutsViewPrivate *priv; + EShortcuts *shortcuts; + + priv = E_SHORTCUTS_VIEW (shortcut_bar)->priv; + shortcuts = priv->shortcuts; + + if (shortcuts == NULL) + return; + + e_shortcuts_remove_group (shortcuts, group_num); +} + static void class_init (EShortcutsViewClass *klass) @@ -228,6 +316,10 @@ class_init (EShortcutsViewClass *klass) shortcut_bar_class = E_SHORTCUT_BAR_CLASS (klass); shortcut_bar_class->selected_item = selected_item; + shortcut_bar_class->added_item = added_item; + shortcut_bar_class->removed_item = removed_item; + shortcut_bar_class->added_group = added_group; + shortcut_bar_class->removed_group = removed_group; parent_class = gtk_type_class (e_shortcut_bar_get_type ()); @@ -267,13 +359,10 @@ e_shortcuts_view_construct (EShortcutsView *shortcuts_view, priv = shortcuts_view->priv; - gtk_object_ref (GTK_OBJECT (shortcuts)); - priv->shortcuts = shortcuts; - e_shortcut_bar_set_icon_callback (E_SHORTCUT_BAR (shortcuts_view), icon_callback, shortcuts); - load_all_shortcuts (shortcuts_view); + load_all_shortcuts (shortcuts_view, shortcuts); } GtkWidget * diff --git a/shell/e-shortcuts.c b/shell/e-shortcuts.c index c6d8a77107..414e5d2da9 100644 --- a/shell/e-shortcuts.c +++ b/shell/e-shortcuts.c @@ -73,6 +73,17 @@ struct _ShortcutGroup { typedef struct _ShortcutGroup ShortcutGroup; struct _EShortcutsPrivate { + /* Name of the file associated with these shortcuts. Changes in the shortcuts + will update this file automatically. */ + char *file_name; + + /* ID of the idle function that will be called to save the shortcuts when they are + changed. */ + int save_idle_id; + + /* Whether these shortcuts need to be saved to disk. */ + gboolean dirty; + /* The storage set to which these shortcuts are associated. */ EStorageSet *storage_set; @@ -123,7 +134,7 @@ unload_shortcuts (EShortcuts *shortcuts) static gboolean load_shortcuts (EShortcuts *shortcuts, - const char *path) + const char *file_name) { EShortcutsPrivate *priv; xmlDoc *doc; @@ -132,7 +143,7 @@ load_shortcuts (EShortcuts *shortcuts, priv = shortcuts->priv; - doc = xmlParseFile (path); + doc = xmlParseFile (file_name); if (doc == NULL) return FALSE; @@ -158,7 +169,7 @@ load_shortcuts (EShortcuts *shortcuts, shortcut_group = g_hash_table_lookup (priv->title_to_group, shortcut_group_title); if (shortcut_group != NULL) { - g_warning ("Duplicate shortcut title -- %s", + g_warning ("Duplicate shortcut group title -- %s", shortcut_group_title); xmlFree (shortcut_group_title); continue; @@ -195,7 +206,7 @@ load_shortcuts (EShortcuts *shortcuts, static gboolean save_shortcuts (EShortcuts *shortcuts, - const char *path) + const char *file_name) { EShortcutsPrivate *priv; xmlDoc *doc; @@ -225,7 +236,7 @@ save_shortcuts (EShortcuts *shortcuts, } } - if (xmlSaveFile (path, doc) < 0) { + if (xmlSaveFile (file_name, doc) < 0) { xmlFreeDoc (doc); return FALSE; } @@ -234,6 +245,55 @@ save_shortcuts (EShortcuts *shortcuts, return TRUE; } + +/* Idle function to update the file on disk. */ + +static int +idle_cb (void *data) +{ + EShortcuts *shortcuts; + EShortcutsPrivate *priv; + + shortcuts = E_SHORTCUTS (data); + priv = shortcuts->priv; + + if (priv->dirty) { + g_print ("Saving shortcuts -- %s\n", priv->file_name); + if (! e_shortcuts_save (shortcuts, NULL)) + g_warning ("Saving of shortcuts failed -- %s", priv->file_name); + else + priv->dirty = FALSE; + } + + priv->save_idle_id = 0; + + return FALSE; +} + +static void +schedule_idle (EShortcuts *shortcuts) +{ + EShortcutsPrivate *priv; + + priv = shortcuts->priv; + + if (priv->save_idle_id != 0) + return; + + gtk_idle_add (idle_cb, shortcuts); +} + +static void +make_dirty (EShortcuts *shortcuts) +{ + EShortcutsPrivate *priv; + + priv = shortcuts->priv; + + priv->dirty = TRUE; + schedule_idle (shortcuts); +} + /* Signal handlers for the views. */ @@ -262,6 +322,8 @@ destroy (GtkObject *object) shortcuts = E_SHORTCUTS (object); priv = shortcuts->priv; + g_free (priv->file_name); + if (priv->storage_set != NULL) gtk_object_unref (GTK_OBJECT (priv->storage_set)); @@ -270,6 +332,14 @@ destroy (GtkObject *object) unload_shortcuts (shortcuts); + if (priv->save_idle_id != 0) + gtk_idle_remove (priv->save_idle_id); + + if (priv->dirty) { + if (! e_shortcuts_save (shortcuts, NULL)) + g_warning (_("Error saving shortcuts.")); /* FIXME */ + } + g_hash_table_destroy (priv->title_to_group); (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); @@ -295,10 +365,13 @@ init (EShortcuts *shortcuts) priv = g_new (EShortcutsPrivate, 1); + priv->file_name = NULL; priv->storage_set = NULL; priv->groups = NULL; priv->views = NULL; priv->title_to_group = g_hash_table_new (g_str_hash, g_str_equal); + priv->dirty = 0; + priv->save_idle_id = 0; shortcuts->priv = priv; } @@ -329,7 +402,8 @@ e_shortcuts_construct (EShortcuts *shortcuts, EShortcuts * e_shortcuts_new (EStorageSet *storage_set, - EFolderTypeRegistry *folder_type_registry) + EFolderTypeRegistry *folder_type_registry, + const char *file_name) { EShortcuts *new; @@ -339,6 +413,11 @@ e_shortcuts_new (EStorageSet *storage_set, new = gtk_type_new (e_shortcuts_get_type ()); e_shortcuts_construct (new, storage_set, folder_type_registry); + if (! e_shortcuts_load (new, file_name)) { + gtk_object_unref (GTK_OBJECT (new)); + return NULL; + } + return new; } @@ -426,26 +505,60 @@ e_shortcuts_new_view (EShortcuts *shortcuts) gboolean e_shortcuts_load (EShortcuts *shortcuts, - const char *path) + const char *file_name) { + EShortcutsPrivate *priv; + char *tmp; + g_return_val_if_fail (shortcuts != NULL, FALSE); g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE); - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (g_path_is_absolute (path), FALSE); + g_return_val_if_fail (file_name == NULL || g_path_is_absolute (file_name), FALSE); + + priv = shortcuts->priv; + + if (file_name == NULL) { + if (priv->file_name == NULL) + return FALSE; + file_name = priv->file_name; + } + + if (! load_shortcuts (shortcuts, file_name)) + return FALSE; + + tmp = g_strdup (file_name); + g_free (priv->file_name); + priv->file_name = tmp; - return load_shortcuts (shortcuts, path); + return TRUE; } gboolean e_shortcuts_save (EShortcuts *shortcuts, - const char *path) + const char *file_name) { + EShortcutsPrivate *priv; + char *tmp; + g_return_val_if_fail (shortcuts != NULL, FALSE); g_return_val_if_fail (E_IS_SHORTCUTS (shortcuts), FALSE); - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (g_path_is_absolute (path), FALSE); + g_return_val_if_fail (file_name == NULL || g_path_is_absolute (file_name), FALSE); + + priv = shortcuts->priv; + + if (file_name == NULL) { + if (priv->file_name == NULL) + return FALSE; + file_name = priv->file_name; + } + + if (! save_shortcuts (shortcuts, file_name)) + return FALSE; + + tmp = g_strdup (file_name); + g_free (priv->file_name); + priv->file_name = tmp; - return save_shortcuts (shortcuts, path); + return TRUE; } @@ -472,6 +585,110 @@ e_shortcuts_get_uri (EShortcuts *shortcuts, int group_num, int num) return shortcut_element->data; } + +void +e_shortcuts_remove_shortcut (EShortcuts *shortcuts, + int group_num, + int num) +{ + EShortcutsPrivate *priv; + ShortcutGroup *group; + GList *p; + char *uri; + + g_return_if_fail (shortcuts != NULL); + g_return_if_fail (E_IS_SHORTCUTS (shortcuts)); + + priv = shortcuts->priv; + + p = g_list_nth (priv->groups, group_num); + g_return_if_fail (p != NULL); + + group = (ShortcutGroup *) p->data; + + p = g_list_nth (group->shortcuts, num); + g_return_if_fail (p != NULL); + + uri = (char *) p->data; + g_free (uri); + + group->shortcuts = g_list_remove_link (group->shortcuts, p); + + make_dirty (shortcuts); +} + +void +e_shortcuts_add_shortcut (EShortcuts *shortcuts, + int group_num, + int num, + const char *uri) +{ + EShortcutsPrivate *priv; + ShortcutGroup *group; + GList *p; + + g_return_if_fail (shortcuts != NULL); + g_return_if_fail (E_IS_SHORTCUTS (shortcuts)); + + priv = shortcuts->priv; + + p = g_list_nth (priv->groups, group_num); + g_return_if_fail (p != NULL); + + group = (ShortcutGroup *) p->data; + + group->shortcuts = g_list_insert (group->shortcuts, g_strdup (uri), num); + + make_dirty (shortcuts); +} + +void +e_shortcuts_remove_group (EShortcuts *shortcuts, + int group_num) +{ + EShortcutsPrivate *priv; + ShortcutGroup *group; + GList *p; + + g_return_if_fail (shortcuts != NULL); + g_return_if_fail (E_IS_SHORTCUTS (shortcuts)); + + priv = shortcuts->priv; + + p = g_list_nth (priv->groups, group_num); + g_return_if_fail (p != NULL); + + group = (ShortcutGroup *) p->data; + + e_free_string_list (group->shortcuts); + + priv->groups = g_list_remove_link (priv->groups, p); + + make_dirty (shortcuts); +} + +void +e_shortcuts_add_group (EShortcuts *shortcuts, + int group_num, + const char *group_name) +{ + EShortcutsPrivate *priv; + ShortcutGroup *group; + + g_return_if_fail (shortcuts != NULL); + g_return_if_fail (E_IS_SHORTCUTS (shortcuts)); + + priv = shortcuts->priv; + + group = g_new (ShortcutGroup, 1); + group->title = g_strdup (group_name); + group->shortcuts = NULL; + + priv->groups = g_list_insert (priv->groups, group, group_num); + + make_dirty (shortcuts); +} + E_MAKE_TYPE (e_shortcuts, "EShortcuts", EShortcuts, class_init, init, PARENT_TYPE) diff --git a/shell/e-shortcuts.h b/shell/e-shortcuts.h index 63c897ece0..f450728b51 100644 --- a/shell/e-shortcuts.h +++ b/shell/e-shortcuts.h @@ -65,13 +65,15 @@ void e_shortcuts_construct (EShortcuts *shortcuts EStorageSet *storage_set, EFolderTypeRegistry *folder_type_registry); EShortcuts *e_shortcuts_new (EStorageSet *storage_set, - EFolderTypeRegistry *folder_type_registry); + EFolderTypeRegistry *folder_type_registry, + const char *file_name); GList *e_shortcuts_get_group_titles (EShortcuts *shortcuts); GList *e_shortcuts_get_shortcuts_in_group (EShortcuts *shortcuts, const char *group_title); EStorageSet *e_shortcuts_get_storage_set (EShortcuts *shortcuts); GtkWidget *e_shortcuts_new_view (EShortcuts *shortcuts); + gboolean e_shortcuts_load (EShortcuts *shortcuts, const char *path); gboolean e_shortcuts_save (EShortcuts *shortcuts, @@ -81,6 +83,19 @@ const char *e_shortcuts_get_uri (EShortcuts *shortcuts int group_num, int num); +void e_shortcuts_remove_shortcut (EShortcuts *shortcuts, + int group_num, + int num); +void e_shortcuts_add_shortcut (EShortcuts *shortcuts, + int group_num, + int num, + const char *uri); +void e_shortcuts_remove_group (EShortcuts *shortcuts, + int group_num); +void e_shortcuts_add_group (EShortcuts *shortcuts, + int group_num, + const char *group_name); + #ifdef __cplusplus } #endif /* __cplusplus */ -- cgit v1.2.3