
type and a name too. The name will allow renaming shortcuts (thus decoupling the name of the folder the shortcuts points to from the name of the shortcut); the type member is used to cache the type of the folder we point to so that we can still display the right icon even if the folder is currently not in the storage (e.g. this happens for IMAP folders when you haven't opened the corresponding IMAP node yet). I don't like the way this is designed at all (mainly, the responsibility for saving the values should be moved elsewhere), but I'll fix it later. Also, I added an "Open in New Window" right-click menu item for shortcuts. svn path=/trunk/; revision=10649
2340 lines
61 KiB
C
2340 lines
61 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
||
/* e-shell-view.c
|
||
*
|
||
* Copyright (C) 2000, 2001 Ximian, 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.
|
||
*
|
||
* Authors:
|
||
* Ettore Perazzoli <ettore@ximian.com>
|
||
* Miguel de Icaza <miguel@ximian.com>
|
||
* Matt Loper <matt@ximian.com>
|
||
*/
|
||
|
||
#ifdef HAVE_CONFIG_H
|
||
#include <config.h>
|
||
#endif
|
||
|
||
#include <glib.h>
|
||
#include <libgnome/gnome-defs.h>
|
||
#include <libgnome/gnome-config.h>
|
||
#include <libgnome/gnome-i18n.h>
|
||
#include <libgnomeui/gnome-window.h>
|
||
#include <libgnomeui/gnome-window-icon.h>
|
||
#include <libgnomeui/gnome-app.h>
|
||
#include <bonobo/bonobo-socket.h>
|
||
#include <bonobo/bonobo-ui-util.h>
|
||
#include <bonobo/bonobo-widget.h>
|
||
|
||
#include <gal/e-paned/e-hpaned.h>
|
||
#include <gal/util/e-util.h>
|
||
#include <gal/widgets/e-gui-utils.h>
|
||
#include <gal/widgets/e-unicode.h>
|
||
#include <gal/widgets/e-scroll-frame.h>
|
||
|
||
#include "widgets/misc/e-clipped-label.h"
|
||
|
||
#include "evolution-shell-view.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-shell-view.h"
|
||
#include "e-shell-view-menu.h"
|
||
|
||
|
||
static BonoboWindowClass *parent_class = NULL;
|
||
|
||
struct _EShellViewPrivate {
|
||
/* The shell. */
|
||
EShell *shell;
|
||
|
||
/* EvolutionShellView Bonobo object for implementing the
|
||
Evolution::ShellView interface. */
|
||
EvolutionShellView *corba_interface;
|
||
|
||
/* The UI handler & container. */
|
||
BonoboUIComponent *ui_component;
|
||
BonoboUIContainer *ui_container;
|
||
|
||
/* Currently displayed URI. */
|
||
char *uri;
|
||
|
||
/* delayed selection, used when a path doesn't exist in an
|
||
EStorage. cleared when we're signaled with
|
||
"folder_selected" */
|
||
char *delayed_selection;
|
||
|
||
/* uri to go to at timeout */
|
||
unsigned int set_folder_timeout;
|
||
char *set_folder_uri;
|
||
|
||
/* Tooltips. */
|
||
GtkTooltips *tooltips;
|
||
|
||
/* The widgetry. */
|
||
GtkWidget *appbar;
|
||
GtkWidget *hpaned;
|
||
GtkWidget *view_vbox;
|
||
GtkWidget *view_title_bar;
|
||
GtkWidget *view_hpaned;
|
||
GtkWidget *contents;
|
||
GtkWidget *notebook;
|
||
GtkWidget *shortcut_frame;
|
||
GtkWidget *shortcut_bar;
|
||
GtkWidget *storage_set_title_bar;
|
||
GtkWidget *storage_set_view;
|
||
GtkWidget *storage_set_view_box;
|
||
|
||
/* The status bar widgetry. */
|
||
GtkWidget *status_bar;
|
||
GtkWidget *offline_toggle;
|
||
GtkWidget *offline_toggle_pixmap;
|
||
GtkWidget *menu_hint_label;
|
||
GtkWidget *task_bar;
|
||
|
||
/* The view we have already open. */
|
||
GHashTable *uri_to_control;
|
||
|
||
/* Position of the handles in the paneds, to be restored when we show elements
|
||
after hiding them. */
|
||
unsigned int hpaned_position;
|
||
unsigned int view_hpaned_position;
|
||
|
||
/* Status of the shortcut and folder bars. */
|
||
EShellViewSubwindowMode shortcut_bar_mode;
|
||
EShellViewSubwindowMode folder_bar_mode;
|
||
|
||
/* List of sockets we created. */
|
||
GList *sockets;
|
||
};
|
||
|
||
enum {
|
||
SHORTCUT_BAR_MODE_CHANGED,
|
||
FOLDER_BAR_MODE_CHANGED,
|
||
LAST_SIGNAL
|
||
};
|
||
|
||
static guint signals[LAST_SIGNAL] = { 0 };
|
||
|
||
#define DEFAULT_SHORTCUT_BAR_WIDTH 100
|
||
#define DEFAULT_TREE_WIDTH 130
|
||
|
||
#define DEFAULT_WIDTH 705
|
||
#define DEFAULT_HEIGHT 550
|
||
|
||
#define DEFAULT_URI "evolution:/local/Inbox"
|
||
|
||
#define SET_FOLDER_DELAY 250
|
||
|
||
|
||
/* The icons for the offline/online status. */
|
||
|
||
static GdkPixmap *offline_pixmap = NULL;
|
||
static GdkBitmap *offline_mask = NULL;
|
||
|
||
static GdkPixmap *online_pixmap = NULL;
|
||
static GdkBitmap *online_mask = NULL;
|
||
|
||
|
||
static void update_for_current_uri (EShellView *shell_view);
|
||
static void update_offline_toggle_status (EShellView *shell_view);
|
||
static const char *get_storage_set_path_from_uri (const char *uri);
|
||
|
||
|
||
/* Utility functions. */
|
||
|
||
static GtkWidget *
|
||
create_label_for_empty_page (void)
|
||
{
|
||
GtkWidget *label;
|
||
|
||
label = e_clipped_label_new (_("(No folder displayed)"));
|
||
gtk_widget_show (label);
|
||
|
||
return label;
|
||
}
|
||
|
||
/* Initialize the icons. */
|
||
static void
|
||
load_images (void)
|
||
{
|
||
GdkPixbuf *pixbuf;
|
||
|
||
pixbuf = gdk_pixbuf_new_from_file (EVOLUTION_IMAGES "/offline.png");
|
||
if (pixbuf == NULL) {
|
||
g_warning ("Cannot load `%s'", EVOLUTION_IMAGES "/offline.png");
|
||
} else {
|
||
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &offline_pixmap, &offline_mask, 128);
|
||
gdk_pixbuf_unref (pixbuf);
|
||
}
|
||
|
||
pixbuf = gdk_pixbuf_new_from_file (EVOLUTION_IMAGES "/online.png");
|
||
if (pixbuf == NULL) {
|
||
g_warning ("Cannot load `%s'", EVOLUTION_IMAGES "/online.png");
|
||
} else {
|
||
gdk_pixbuf_render_pixmap_and_mask (pixbuf, &online_pixmap, &online_mask, 128);
|
||
gdk_pixbuf_unref (pixbuf);
|
||
}
|
||
}
|
||
|
||
/* FIXME this is broken. */
|
||
static gboolean
|
||
bonobo_widget_is_dead (BonoboWidget *bonobo_widget)
|
||
{
|
||
BonoboControlFrame *control_frame;
|
||
CORBA_Object corba_object;
|
||
CORBA_Environment ev;
|
||
gboolean is_dead;
|
||
|
||
control_frame = bonobo_widget_get_control_frame (bonobo_widget);
|
||
corba_object = bonobo_control_frame_get_control (control_frame);
|
||
|
||
CORBA_exception_init (&ev);
|
||
is_dead = CORBA_Object_non_existent (corba_object, &ev);
|
||
CORBA_exception_free (&ev);
|
||
|
||
return is_dead;
|
||
}
|
||
|
||
|
||
/* Folder bar pop-up handling. */
|
||
|
||
static void disconnect_popup_signals (EShellView *shell_view);
|
||
|
||
static void
|
||
popdown_transient_folder_bar (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
gdk_pointer_ungrab (GDK_CURRENT_TIME);
|
||
gtk_grab_remove (priv->storage_set_view_box);
|
||
|
||
e_shell_view_set_folder_bar_mode (shell_view, E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
|
||
disconnect_popup_signals (shell_view);
|
||
|
||
e_shell_folder_title_bar_set_toggle_state (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar), FALSE);
|
||
}
|
||
|
||
static int
|
||
storage_set_view_box_button_release_event_cb (GtkWidget *widget,
|
||
GdkEventButton *button_event,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
if (button_event->window == E_PANED (priv->view_hpaned)->handle)
|
||
return FALSE;
|
||
|
||
popdown_transient_folder_bar (shell_view);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static int
|
||
storage_set_view_box_event_cb (GtkWidget *widget,
|
||
GdkEvent *event,
|
||
void *data)
|
||
{
|
||
GtkWidget *event_widget;
|
||
GtkWidget *tooltip;
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
event_widget = gtk_get_event_widget (event);
|
||
|
||
if (!event_widget)
|
||
return FALSE;
|
||
|
||
tooltip = e_tree_get_tooltip (E_TREE(priv->storage_set_view));
|
||
if (! (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
|
||
tooltip &&
|
||
gtk_widget_is_ancestor (event_widget, tooltip)))
|
||
return FALSE;
|
||
|
||
switch (event->type) {
|
||
case GDK_BUTTON_PRESS:
|
||
case GDK_2BUTTON_PRESS:
|
||
case GDK_3BUTTON_PRESS:
|
||
case GDK_KEY_PRESS:
|
||
case GDK_KEY_RELEASE:
|
||
case GDK_MOTION_NOTIFY:
|
||
case GDK_BUTTON_RELEASE:
|
||
case GDK_PROXIMITY_IN:
|
||
case GDK_PROXIMITY_OUT:
|
||
gtk_propagate_event (event_widget, event);
|
||
return TRUE;
|
||
break;
|
||
case GDK_ENTER_NOTIFY:
|
||
case GDK_LEAVE_NOTIFY:
|
||
gtk_widget_event (event_widget, event);
|
||
return TRUE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
static void
|
||
popup_storage_set_view_button_clicked (ETitleBar *title_bar,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
gdk_pointer_ungrab (GDK_CURRENT_TIME);
|
||
gtk_grab_remove (priv->storage_set_view_box);
|
||
|
||
disconnect_popup_signals (shell_view);
|
||
|
||
e_shell_view_set_folder_bar_mode (shell_view, E_SHELL_VIEW_SUBWINDOW_STICKY);
|
||
e_shell_folder_title_bar_set_toggle_state (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar), FALSE);
|
||
}
|
||
|
||
static void
|
||
storage_set_view_box_map_cb (GtkWidget *widget,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
if (gdk_pointer_grab (widget->window, TRUE,
|
||
(GDK_BUTTON_PRESS_MASK
|
||
| GDK_BUTTON_RELEASE_MASK
|
||
| GDK_ENTER_NOTIFY_MASK
|
||
| GDK_LEAVE_NOTIFY_MASK
|
||
| GDK_POINTER_MOTION_MASK),
|
||
NULL, NULL, GDK_CURRENT_TIME) != 0) {
|
||
g_warning ("e-shell-view.c:storage_set_view_box_map_cb() -- pointer grab failed.");
|
||
e_shell_view_set_folder_bar_mode (shell_view, E_SHELL_VIEW_SUBWINDOW_STICKY);
|
||
return;
|
||
}
|
||
|
||
gtk_grab_add (widget);
|
||
gtk_signal_connect (GTK_OBJECT (widget), "event",
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_event_cb), shell_view);
|
||
gtk_signal_connect (GTK_OBJECT (widget), "button_release_event",
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_button_release_event_cb), shell_view);
|
||
gtk_signal_connect (GTK_OBJECT (priv->storage_set_view), "button_release_event",
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_button_release_event_cb), shell_view);
|
||
gtk_signal_connect (GTK_OBJECT (priv->storage_set_title_bar), "button_clicked",
|
||
GTK_SIGNAL_FUNC (popup_storage_set_view_button_clicked), shell_view);
|
||
}
|
||
|
||
static void
|
||
disconnect_popup_signals (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
gtk_signal_disconnect_by_func (GTK_OBJECT (priv->storage_set_view_box),
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_button_release_event_cb),
|
||
shell_view);
|
||
gtk_signal_disconnect_by_func (GTK_OBJECT (priv->storage_set_view),
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_button_release_event_cb),
|
||
shell_view);
|
||
gtk_signal_disconnect_by_func (GTK_OBJECT (priv->storage_set_title_bar),
|
||
GTK_SIGNAL_FUNC (popup_storage_set_view_button_clicked),
|
||
shell_view);
|
||
gtk_signal_disconnect_by_func (GTK_OBJECT (priv->storage_set_view_box),
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_map_cb),
|
||
shell_view);
|
||
}
|
||
|
||
static void
|
||
pop_up_folder_bar (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
priv->folder_bar_mode = E_SHELL_VIEW_SUBWINDOW_TRANSIENT;
|
||
|
||
/* We need to show the storage set view box and do a pointer grab to catch the
|
||
mouse clicks. But until the box is shown, we cannot grab. So we connect to
|
||
the "map" signal; `storage_set_view_box_map_cb()' will do the grab. */
|
||
|
||
gtk_signal_connect (GTK_OBJECT (priv->storage_set_view_box), "map",
|
||
GTK_SIGNAL_FUNC (storage_set_view_box_map_cb), shell_view);
|
||
gtk_widget_show (priv->storage_set_view_box);
|
||
|
||
e_paned_set_position (E_PANED (priv->view_hpaned), priv->view_hpaned_position);
|
||
}
|
||
|
||
|
||
/* Switching views on a tree view click. */
|
||
|
||
static void new_folder_cb (EStorageSet *storage_set, const char *path, void *data);
|
||
|
||
static int
|
||
set_folder_timeout (gpointer data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
/* set to 0 so we don't remove it in _display_uri() */
|
||
priv->set_folder_timeout = 0;
|
||
e_shell_view_display_uri (shell_view, priv->set_folder_uri);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static void
|
||
switch_on_folder_tree_click (EShellView *shell_view,
|
||
const char *path)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
char *uri;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
uri = g_strconcat (E_SHELL_URI_PREFIX, path, NULL);
|
||
if (priv->uri != NULL && !strcmp (uri, priv->uri)) {
|
||
g_free (uri);
|
||
return;
|
||
}
|
||
|
||
if (priv->set_folder_timeout != 0)
|
||
gtk_timeout_remove (priv->set_folder_timeout);
|
||
g_free (priv->set_folder_uri);
|
||
|
||
if (priv->delayed_selection) {
|
||
g_free (priv->delayed_selection);
|
||
priv->delayed_selection = NULL;
|
||
gtk_signal_disconnect_by_func (GTK_OBJECT (e_shell_get_storage_set (priv->shell)),
|
||
GTK_SIGNAL_FUNC (new_folder_cb),
|
||
shell_view);
|
||
}
|
||
|
||
if (priv->folder_bar_mode == E_SHELL_VIEW_SUBWINDOW_TRANSIENT) {
|
||
e_shell_view_display_uri (shell_view, uri);
|
||
popdown_transient_folder_bar (shell_view);
|
||
g_free (uri);
|
||
return;
|
||
}
|
||
|
||
priv->set_folder_uri = uri;
|
||
|
||
priv->set_folder_timeout = gtk_timeout_add (SET_FOLDER_DELAY, set_folder_timeout, shell_view);
|
||
}
|
||
|
||
|
||
/* Callbacks. */
|
||
|
||
/* Callback when a new folder is added. removed when we clear the
|
||
delayed_selection */
|
||
static void
|
||
new_folder_cb (EStorageSet *storage_set,
|
||
const char *path,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
char *delayed_path;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
delayed_path = strchr (priv->delayed_selection, ':');
|
||
if (delayed_path) {
|
||
delayed_path ++;
|
||
if (!strcmp(path, delayed_path)) {
|
||
gtk_signal_disconnect_by_func (GTK_OBJECT (e_shell_get_storage_set(priv->shell)),
|
||
GTK_SIGNAL_FUNC (new_folder_cb),
|
||
shell_view);
|
||
g_free (priv->uri);
|
||
priv->uri = priv->delayed_selection;
|
||
priv->delayed_selection = NULL;
|
||
e_shell_view_display_uri (shell_view, priv->uri);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Callback called when an icon on the shortcut bar gets clicked. */
|
||
static void
|
||
activate_shortcut_cb (EShortcutsView *shortcut_view,
|
||
EShortcuts *shortcuts,
|
||
const char *uri,
|
||
gboolean in_new_window,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
|
||
if (in_new_window)
|
||
e_shell_create_view (e_shell_view_get_shell (shell_view), uri);
|
||
else
|
||
e_shell_view_display_uri (shell_view, uri);
|
||
}
|
||
|
||
/* Callback when user chooses "Hide shortcut bar" via a right click */
|
||
static void
|
||
hide_requested_cb (EShortcutsView *shortcut_view,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
|
||
e_shell_view_set_shortcut_bar_mode (shell_view,
|
||
E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
}
|
||
|
||
/* Callback called when a folder on the tree view gets clicked. */
|
||
static void
|
||
folder_selected_cb (EStorageSetView *storage_set_view,
|
||
const char *path,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
|
||
switch_on_folder_tree_click (shell_view, path);
|
||
}
|
||
|
||
/* Callback called when a storage in the tree view is clicked. */
|
||
static void
|
||
storage_selected_cb (EStorageSetView *storage_set_view,
|
||
const char *name,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
char *path;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
|
||
path = g_strconcat (G_DIR_SEPARATOR_S, name, NULL);
|
||
switch_on_folder_tree_click (shell_view, path);
|
||
|
||
g_free (path);
|
||
}
|
||
|
||
/* Callback called when the button on the tree's title bar is clicked. */
|
||
static void
|
||
storage_set_view_button_clicked_cb (ETitleBar *title_bar,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
|
||
e_shell_view_set_folder_bar_mode (shell_view, E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
}
|
||
|
||
/* Callback called when the title bar button is clicked. */
|
||
static void
|
||
title_bar_toggled_cb (EShellFolderTitleBar *title_bar,
|
||
gboolean state,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
|
||
if (! state)
|
||
return;
|
||
|
||
if (e_shell_view_get_folder_bar_mode (shell_view) != E_SHELL_VIEW_SUBWINDOW_TRANSIENT)
|
||
pop_up_folder_bar (shell_view);
|
||
}
|
||
|
||
/* Callback called when the offline toggle button is clicked. */
|
||
static void
|
||
offline_toggle_clicked_cb (GtkButton *button,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
switch (e_shell_get_line_status (priv->shell)) {
|
||
case E_SHELL_LINE_STATUS_ONLINE:
|
||
e_shell_go_offline (priv->shell, shell_view);
|
||
break;
|
||
case E_SHELL_LINE_STATUS_OFFLINE:
|
||
e_shell_go_online (priv->shell, shell_view);
|
||
break;
|
||
default:
|
||
g_assert_not_reached ();
|
||
}
|
||
}
|
||
|
||
|
||
/* Widget setup. */
|
||
|
||
static void
|
||
setup_storage_set_subwindow (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GtkWidget *storage_set_view;
|
||
GtkWidget *vbox;
|
||
GtkWidget *scroll_frame;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
storage_set_view = e_storage_set_view_new (e_shell_get_storage_set (priv->shell), priv->ui_container);
|
||
gtk_signal_connect (GTK_OBJECT (storage_set_view), "folder_selected",
|
||
GTK_SIGNAL_FUNC (folder_selected_cb), shell_view);
|
||
gtk_signal_connect (GTK_OBJECT (storage_set_view), "storage_selected",
|
||
GTK_SIGNAL_FUNC (storage_selected_cb), shell_view);
|
||
|
||
scroll_frame = e_scroll_frame_new (NULL, NULL);
|
||
e_scroll_frame_set_policy (E_SCROLL_FRAME (scroll_frame), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||
e_scroll_frame_set_shadow_type (E_SCROLL_FRAME (scroll_frame), GTK_SHADOW_IN);
|
||
|
||
gtk_container_add (GTK_CONTAINER (scroll_frame), storage_set_view);
|
||
|
||
vbox = gtk_vbox_new (FALSE, 0);
|
||
priv->storage_set_title_bar = e_title_bar_new (_("Folders"));
|
||
|
||
gtk_box_pack_start (GTK_BOX (vbox), priv->storage_set_title_bar, FALSE, FALSE, 0);
|
||
gtk_box_pack_start (GTK_BOX (vbox), scroll_frame, TRUE, TRUE, 0);
|
||
|
||
gtk_signal_connect (GTK_OBJECT (priv->storage_set_title_bar), "button_clicked",
|
||
GTK_SIGNAL_FUNC (storage_set_view_button_clicked_cb), shell_view);
|
||
|
||
gtk_widget_show (vbox);
|
||
gtk_widget_show (storage_set_view);
|
||
gtk_widget_show (priv->storage_set_title_bar);
|
||
gtk_widget_show (scroll_frame);
|
||
|
||
priv->storage_set_view_box = vbox;
|
||
priv->storage_set_view = storage_set_view;
|
||
}
|
||
|
||
static void
|
||
setup_offline_toggle (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GtkWidget *toggle;
|
||
GtkWidget *pixmap;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
toggle = gtk_button_new ();
|
||
GTK_WIDGET_UNSET_FLAGS (toggle, GTK_CAN_FOCUS);
|
||
gtk_button_set_relief (GTK_BUTTON (toggle), GTK_RELIEF_NONE);
|
||
|
||
gtk_signal_connect (GTK_OBJECT (toggle), "clicked",
|
||
GTK_SIGNAL_FUNC (offline_toggle_clicked_cb), shell_view);
|
||
|
||
pixmap = gtk_pixmap_new (offline_pixmap, offline_mask);
|
||
|
||
gtk_container_add (GTK_CONTAINER (toggle), pixmap);
|
||
|
||
gtk_widget_show (toggle);
|
||
gtk_widget_show (pixmap);
|
||
|
||
priv->offline_toggle = toggle;
|
||
priv->offline_toggle_pixmap = pixmap;
|
||
|
||
update_offline_toggle_status (shell_view);
|
||
|
||
g_assert (priv->status_bar != NULL);
|
||
|
||
gtk_box_pack_start (GTK_BOX (priv->status_bar), priv->offline_toggle, FALSE, TRUE, 0);
|
||
}
|
||
|
||
static void
|
||
setup_menu_hint_label (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
priv->menu_hint_label = gtk_label_new ("");
|
||
gtk_misc_set_alignment (GTK_MISC (priv->menu_hint_label), 0.0, 0.5);
|
||
|
||
gtk_box_pack_start (GTK_BOX (priv->status_bar), priv->menu_hint_label, TRUE, TRUE, 0);
|
||
}
|
||
|
||
static void
|
||
setup_task_bar (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
priv->task_bar = e_task_bar_new ();
|
||
|
||
g_assert (priv->status_bar != NULL);
|
||
|
||
gtk_box_pack_start (GTK_BOX (priv->status_bar), priv->task_bar, TRUE, TRUE, 0);
|
||
gtk_widget_show (priv->task_bar);
|
||
}
|
||
|
||
static void
|
||
create_status_bar (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
priv->status_bar = gtk_hbox_new (FALSE, 2);
|
||
gtk_widget_show (priv->status_bar);
|
||
|
||
setup_offline_toggle (shell_view);
|
||
setup_menu_hint_label (shell_view);
|
||
setup_task_bar (shell_view);
|
||
}
|
||
|
||
|
||
/* Menu hints for the status bar. */
|
||
|
||
static void
|
||
ui_engine_add_hint_callback (BonoboUIEngine *engine,
|
||
const char *hint,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
gtk_label_set (GTK_LABEL (priv->menu_hint_label), hint);
|
||
gtk_widget_show (priv->menu_hint_label);
|
||
gtk_widget_hide (priv->task_bar);
|
||
}
|
||
|
||
static void
|
||
ui_engine_remove_hint_callback (BonoboUIEngine *engine,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
gtk_widget_hide (priv->menu_hint_label);
|
||
gtk_widget_show (priv->task_bar);
|
||
}
|
||
|
||
static void
|
||
setup_statusbar_hints (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
BonoboUIEngine *ui_engine;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
g_assert (priv->status_bar != NULL);
|
||
|
||
ui_engine = bonobo_window_get_ui_engine (BONOBO_WINDOW (shell_view));
|
||
|
||
gtk_signal_connect (GTK_OBJECT (ui_engine), "add_hint",
|
||
GTK_SIGNAL_FUNC (ui_engine_add_hint_callback), shell_view);
|
||
gtk_signal_connect (GTK_OBJECT (ui_engine), "remove_hint",
|
||
GTK_SIGNAL_FUNC (ui_engine_remove_hint_callback), shell_view);
|
||
}
|
||
|
||
|
||
static void
|
||
setup_widgets (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GtkWidget *contents_vbox;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
/* The shortcut bar. */
|
||
|
||
priv->shortcut_bar = e_shortcuts_new_view (e_shell_get_shortcuts (priv->shell));
|
||
gtk_signal_connect (GTK_OBJECT (priv->shortcut_bar), "activate_shortcut",
|
||
GTK_SIGNAL_FUNC (activate_shortcut_cb), shell_view);
|
||
|
||
gtk_signal_connect (GTK_OBJECT (priv->shortcut_bar), "hide_requested",
|
||
GTK_SIGNAL_FUNC (hide_requested_cb), shell_view);
|
||
|
||
priv->shortcut_frame = gtk_frame_new (NULL);
|
||
gtk_frame_set_shadow_type (GTK_FRAME (priv->shortcut_frame), GTK_SHADOW_IN);
|
||
|
||
/* The storage set view. */
|
||
|
||
setup_storage_set_subwindow (shell_view);
|
||
|
||
/* The tabless notebook which we used to contain the views. */
|
||
|
||
priv->notebook = gtk_notebook_new ();
|
||
gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE);
|
||
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
|
||
|
||
/* Page for "No URL displayed" message. */
|
||
|
||
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), create_label_for_empty_page (), NULL);
|
||
|
||
/* Put things into a paned and the paned into the GnomeApp. */
|
||
|
||
priv->view_vbox = gtk_vbox_new (FALSE, 0);
|
||
gtk_container_set_border_width (GTK_CONTAINER (priv->view_vbox), 2);
|
||
|
||
priv->view_title_bar = e_shell_folder_title_bar_new ();
|
||
gtk_signal_connect (GTK_OBJECT (priv->view_title_bar), "title_toggled",
|
||
GTK_SIGNAL_FUNC (title_bar_toggled_cb), shell_view);
|
||
|
||
priv->view_hpaned = e_hpaned_new ();
|
||
e_paned_pack1 (E_PANED (priv->view_hpaned), priv->storage_set_view_box, FALSE, FALSE);
|
||
e_paned_pack2 (E_PANED (priv->view_hpaned), priv->notebook, TRUE, FALSE);
|
||
e_paned_set_position (E_PANED (priv->view_hpaned), DEFAULT_TREE_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);
|
||
|
||
priv->hpaned = e_hpaned_new ();
|
||
gtk_container_add (GTK_CONTAINER (priv->shortcut_frame), priv->shortcut_bar);
|
||
e_paned_pack1 (E_PANED (priv->hpaned), priv->shortcut_frame, FALSE, FALSE);
|
||
e_paned_pack2 (E_PANED (priv->hpaned), priv->view_vbox, TRUE, FALSE);
|
||
e_paned_set_position (E_PANED (priv->hpaned), DEFAULT_SHORTCUT_BAR_WIDTH);
|
||
|
||
/* The status bar. */
|
||
|
||
create_status_bar (shell_view);
|
||
setup_statusbar_hints (shell_view);
|
||
|
||
/* The contents. */
|
||
|
||
contents_vbox = gtk_vbox_new (FALSE, 0);
|
||
gtk_box_pack_start (GTK_BOX (contents_vbox), priv->hpaned, TRUE, TRUE, 0);
|
||
gtk_box_pack_start (GTK_BOX (contents_vbox), priv->status_bar, FALSE, TRUE, 0);
|
||
gtk_widget_show (contents_vbox);
|
||
|
||
bonobo_window_set_contents (BONOBO_WINDOW (shell_view), contents_vbox);
|
||
|
||
/* Show stuff. */
|
||
|
||
gtk_widget_show (priv->shortcut_frame);
|
||
gtk_widget_show (priv->shortcut_bar);
|
||
gtk_widget_show (priv->storage_set_view);
|
||
gtk_widget_show (priv->storage_set_view_box);
|
||
gtk_widget_show (priv->notebook);
|
||
gtk_widget_show (priv->hpaned);
|
||
gtk_widget_show (priv->view_hpaned);
|
||
gtk_widget_show (priv->view_vbox);
|
||
gtk_widget_show (priv->view_title_bar);
|
||
gtk_widget_show (priv->status_bar);
|
||
|
||
/* By default, both the folder bar and shortcut bar are visible. */
|
||
priv->shortcut_bar_mode = E_SHELL_VIEW_SUBWINDOW_STICKY;
|
||
priv->folder_bar_mode = E_SHELL_VIEW_SUBWINDOW_STICKY;
|
||
|
||
/* FIXME: Session management and stuff? */
|
||
gtk_window_set_default_size (GTK_WINDOW (shell_view), DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||
}
|
||
|
||
|
||
/* GtkObject methods. */
|
||
|
||
static void
|
||
hash_forall_destroy_control (void *name,
|
||
void *value,
|
||
void *data)
|
||
{
|
||
BonoboWidget *bonobo_widget;
|
||
|
||
bonobo_widget = BONOBO_WIDGET (value);
|
||
gtk_widget_destroy (GTK_WIDGET (bonobo_widget));
|
||
|
||
g_free (name);
|
||
}
|
||
|
||
static void
|
||
destroy (GtkObject *object)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
GList *p;
|
||
|
||
shell_view = E_SHELL_VIEW (object);
|
||
priv = shell_view->priv;
|
||
|
||
gtk_object_unref (GTK_OBJECT (priv->tooltips));
|
||
|
||
if (priv->corba_interface != NULL)
|
||
bonobo_object_unref (BONOBO_OBJECT (priv->corba_interface));
|
||
|
||
for (p = priv->sockets; p != NULL; p = p->next) {
|
||
GtkWidget *socket_widget;
|
||
int destroy_connection_id;
|
||
|
||
socket_widget = GTK_WIDGET (p->data);
|
||
destroy_connection_id = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (socket_widget),
|
||
"e_shell_view_destroy_connection_id"));
|
||
gtk_signal_disconnect (GTK_OBJECT (socket_widget), destroy_connection_id);
|
||
}
|
||
|
||
g_hash_table_foreach (priv->uri_to_control, hash_forall_destroy_control, NULL);
|
||
g_hash_table_destroy (priv->uri_to_control);
|
||
|
||
bonobo_object_unref (BONOBO_OBJECT (priv->ui_component));
|
||
|
||
g_free (priv->uri);
|
||
|
||
if (priv->set_folder_timeout != 0)
|
||
gtk_timeout_remove (priv->set_folder_timeout);
|
||
|
||
g_free (priv->set_folder_uri);
|
||
|
||
g_free (priv);
|
||
|
||
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
||
}
|
||
|
||
static int
|
||
delete_event (GtkWidget *widget,
|
||
GdkEventAny *event)
|
||
{
|
||
EShell *shell;
|
||
|
||
shell = e_shell_view_get_shell (E_SHELL_VIEW (widget));
|
||
|
||
/* FIXME: Is this right, or should it be FALSE? */
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
/* Initialization. */
|
||
|
||
static void
|
||
class_init (EShellViewClass *klass)
|
||
{
|
||
GtkObjectClass *object_class;
|
||
|
||
object_class = (GtkObjectClass *) klass;
|
||
|
||
object_class->destroy = destroy;
|
||
|
||
parent_class = gtk_type_class (BONOBO_TYPE_WINDOW);
|
||
|
||
signals[SHORTCUT_BAR_MODE_CHANGED]
|
||
= gtk_signal_new ("shortcut_bar_mode_changed",
|
||
GTK_RUN_FIRST,
|
||
object_class->type,
|
||
GTK_SIGNAL_OFFSET (EShellViewClass, shortcut_bar_mode_changed),
|
||
gtk_marshal_NONE__INT,
|
||
GTK_TYPE_NONE, 1,
|
||
GTK_TYPE_INT);
|
||
|
||
signals[FOLDER_BAR_MODE_CHANGED]
|
||
= gtk_signal_new ("folder_bar_mode_changed",
|
||
GTK_RUN_FIRST,
|
||
object_class->type,
|
||
GTK_SIGNAL_OFFSET (EShellViewClass, folder_bar_mode_changed),
|
||
gtk_marshal_NONE__INT,
|
||
GTK_TYPE_NONE, 1,
|
||
GTK_TYPE_INT);
|
||
|
||
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
|
||
|
||
load_images ();
|
||
}
|
||
|
||
static void
|
||
init (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
priv = g_new (EShellViewPrivate, 1);
|
||
|
||
priv->shell = NULL;
|
||
priv->corba_interface = NULL;
|
||
priv->ui_component = NULL;
|
||
priv->uri = NULL;
|
||
priv->delayed_selection = NULL;
|
||
|
||
priv->tooltips = gtk_tooltips_new ();
|
||
|
||
priv->appbar = NULL;
|
||
priv->hpaned = NULL;
|
||
priv->view_hpaned = NULL;
|
||
priv->contents = NULL;
|
||
priv->notebook = NULL;
|
||
|
||
priv->storage_set_title_bar = NULL;
|
||
priv->storage_set_view = NULL;
|
||
priv->storage_set_view_box = NULL;
|
||
priv->shortcut_bar = NULL;
|
||
|
||
priv->status_bar = NULL;
|
||
priv->offline_toggle = NULL;
|
||
priv->offline_toggle_pixmap = NULL;
|
||
priv->menu_hint_label = NULL;
|
||
priv->task_bar = NULL;
|
||
|
||
priv->shortcut_bar_mode = E_SHELL_VIEW_SUBWINDOW_HIDDEN;
|
||
priv->folder_bar_mode = E_SHELL_VIEW_SUBWINDOW_HIDDEN;
|
||
|
||
priv->hpaned_position = 0;
|
||
priv->view_hpaned_position = 0;
|
||
|
||
priv->uri_to_control = g_hash_table_new (g_str_hash, g_str_equal);
|
||
|
||
priv->sockets = NULL;
|
||
|
||
priv->set_folder_timeout = 0;
|
||
priv->set_folder_uri = NULL;
|
||
|
||
shell_view->priv = priv;
|
||
}
|
||
|
||
|
||
/* EvolutionShellView interface callbacks. */
|
||
|
||
static void
|
||
corba_interface_set_message_cb (EvolutionShellView *shell_view,
|
||
const char *message,
|
||
gboolean busy,
|
||
void *data)
|
||
{
|
||
/* Don't do anything here anymore. The interface is going to be
|
||
deprecated soon. */
|
||
}
|
||
|
||
static void
|
||
corba_interface_unset_message_cb (EvolutionShellView *shell_view,
|
||
void *data)
|
||
{
|
||
/* Don't do anything here anymore. The interface is going to be
|
||
deprecated soon. */
|
||
}
|
||
|
||
static void
|
||
corba_interface_change_current_view_cb (EvolutionShellView *shell_view,
|
||
const char *uri,
|
||
void *data)
|
||
{
|
||
EShellView *view;
|
||
|
||
view = E_SHELL_VIEW (data);
|
||
|
||
g_return_if_fail (view != NULL);
|
||
|
||
e_shell_view_display_uri (view, uri);
|
||
}
|
||
|
||
static void
|
||
corba_interface_set_title (EvolutionShellView *shell_view,
|
||
const char *title,
|
||
void *data)
|
||
{
|
||
EShellView *view;
|
||
|
||
view = E_SHELL_VIEW (data);
|
||
|
||
g_return_if_fail (view != NULL);
|
||
|
||
gtk_window_set_title (GTK_WINDOW (view), title);
|
||
}
|
||
|
||
static void
|
||
corba_interface_set_folder_bar_label (EvolutionShellView *evolution_shell_view,
|
||
const char *text,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
g_return_if_fail (data != NULL);
|
||
g_return_if_fail (E_IS_SHELL_VIEW (data));
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
e_shell_folder_title_bar_set_folder_bar_label (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar),
|
||
text);
|
||
}
|
||
|
||
static void
|
||
unmerge_on_error (BonoboObject *object,
|
||
CORBA_Object cobject,
|
||
CORBA_Environment *ev)
|
||
{
|
||
BonoboWindow *win;
|
||
|
||
win = bonobo_ui_container_get_win (BONOBO_UI_CONTAINER (object));
|
||
|
||
if (win)
|
||
bonobo_window_deregister_component_by_ref (win, cobject);
|
||
}
|
||
|
||
static void
|
||
updated_folder_cb (EStorageSet *storage_set,
|
||
const char *path,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
#if 0
|
||
char *uri = g_strconcat (E_SHELL_URI_PREFIX, path, NULL);
|
||
|
||
/* Update the shortcut bar */
|
||
e_shortcuts_update_shortcut_by_uri (e_shell_get_shortcuts (priv->shell), uri);
|
||
g_free (uri);
|
||
#endif
|
||
|
||
/* Update the folder title bar and the window title bar */
|
||
update_for_current_uri (shell_view);
|
||
}
|
||
|
||
|
||
/* Shell callbacks. */
|
||
|
||
static void
|
||
shell_line_status_changed_cb (EShell *shell,
|
||
EShellLineStatus new_status,
|
||
void *data)
|
||
{
|
||
EShellView *shell_view;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
update_offline_toggle_status (shell_view);
|
||
}
|
||
|
||
|
||
EShellView *
|
||
e_shell_view_construct (EShellView *shell_view,
|
||
EShell *shell)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EShellView *view;
|
||
GtkObject *window;
|
||
|
||
g_return_val_if_fail (shell != NULL, NULL);
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL (shell), NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
view = E_SHELL_VIEW (bonobo_window_construct (BONOBO_WINDOW (shell_view), "evolution", "Evolution"));
|
||
|
||
if (!view) {
|
||
gtk_object_unref (GTK_OBJECT (shell_view));
|
||
return NULL;
|
||
}
|
||
|
||
window = GTK_OBJECT (view);
|
||
|
||
gtk_signal_connect (window, "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL);
|
||
|
||
priv->shell = shell;
|
||
|
||
gtk_signal_connect_while_alive (GTK_OBJECT (e_shell_get_storage_set (priv->shell)), "updated_folder",
|
||
updated_folder_cb, shell_view, GTK_OBJECT (shell_view));
|
||
|
||
priv->ui_container = bonobo_ui_container_new ();
|
||
bonobo_ui_container_set_win (priv->ui_container, BONOBO_WINDOW (shell_view));
|
||
gtk_signal_connect (GTK_OBJECT (priv->ui_container),
|
||
"system_exception", GTK_SIGNAL_FUNC (unmerge_on_error), NULL);
|
||
|
||
priv->ui_component = bonobo_ui_component_new ("evolution");
|
||
bonobo_ui_component_set_container (priv->ui_component,
|
||
bonobo_object_corba_objref (BONOBO_OBJECT (priv->ui_container)));
|
||
|
||
bonobo_ui_component_freeze (priv->ui_component, NULL);
|
||
|
||
bonobo_ui_util_set_ui (priv->ui_component, EVOLUTION_DATADIR, "evolution.xml", "evolution");
|
||
|
||
setup_widgets (shell_view);
|
||
|
||
bonobo_ui_engine_config_set_path (bonobo_window_get_ui_engine (BONOBO_WINDOW (shell_view)),
|
||
"/evolution/UIConf/kvps");
|
||
e_shell_view_menu_setup (shell_view);
|
||
|
||
e_shell_view_set_folder_bar_mode (shell_view, E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
|
||
bonobo_ui_component_thaw (priv->ui_component, NULL);
|
||
|
||
gtk_signal_connect (GTK_OBJECT (shell), "line_status_changed",
|
||
GTK_SIGNAL_FUNC (shell_line_status_changed_cb), view);
|
||
|
||
return view;
|
||
}
|
||
|
||
/* WARNING: Don't use `e_shell_view_new()' to create new views for the shell
|
||
unless you know what you are doing; this is just the standard GTK+
|
||
constructor thing and it won't allow the shell to do the required
|
||
bookkeeping for the created views. Instead, the right way to create a new
|
||
view is calling `e_shell_create_view()'. */
|
||
EShellView *
|
||
e_shell_view_new (EShell *shell)
|
||
{
|
||
GtkWidget *new;
|
||
|
||
g_return_val_if_fail (shell != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL (shell), NULL);
|
||
|
||
new = gtk_type_new (e_shell_view_get_type ());
|
||
|
||
return e_shell_view_construct (E_SHELL_VIEW (new), shell);
|
||
}
|
||
|
||
const GNOME_Evolution_ShellView
|
||
e_shell_view_get_corba_interface (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
g_return_val_if_fail (shell_view != NULL, CORBA_OBJECT_NIL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), CORBA_OBJECT_NIL);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
return bonobo_object_corba_objref (BONOBO_OBJECT (priv->corba_interface));
|
||
}
|
||
|
||
|
||
static const char *
|
||
get_storage_set_path_from_uri (const char *uri)
|
||
{
|
||
const char *colon;
|
||
|
||
if (uri == NULL)
|
||
return NULL;
|
||
|
||
if (g_path_is_absolute (uri))
|
||
return NULL;
|
||
|
||
colon = strchr (uri, ':');
|
||
if (colon == NULL || colon == uri || colon[1] == '\0')
|
||
return NULL;
|
||
|
||
if (! g_path_is_absolute (colon + 1))
|
||
return NULL;
|
||
|
||
if (g_strncasecmp (uri, E_SHELL_URI_PREFIX, colon - uri) != 0)
|
||
return NULL;
|
||
|
||
return colon + 1;
|
||
}
|
||
|
||
static void
|
||
update_window_icon (EShellView *shell_view,
|
||
EFolder *folder,
|
||
gboolean is_my_evolution)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
const char *type;
|
||
const char *icon_name;
|
||
char *icon_path;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
if (folder == NULL) {
|
||
if (is_my_evolution) {
|
||
type = "My Evolution";
|
||
} else {
|
||
type = NULL;
|
||
}
|
||
} else {
|
||
type = e_folder_get_type_string (folder);
|
||
}
|
||
|
||
if (type == NULL) {
|
||
icon_path = NULL;
|
||
} else {
|
||
EFolderTypeRegistry *folder_type_registry;
|
||
|
||
folder_type_registry = e_shell_get_folder_type_registry (priv->shell);
|
||
icon_name = e_folder_type_registry_get_icon_name_for_type (folder_type_registry, type);
|
||
if (icon_name == NULL)
|
||
icon_path = NULL;
|
||
else
|
||
icon_path = e_shell_get_icon_path (icon_name, TRUE);
|
||
}
|
||
|
||
if (icon_path == NULL) {
|
||
gnome_window_icon_set_from_default (GTK_WINDOW (shell_view));
|
||
} else {
|
||
gnome_window_icon_set_from_file (GTK_WINDOW (shell_view), icon_path);
|
||
g_free (icon_path);
|
||
}
|
||
}
|
||
|
||
static void
|
||
update_folder_title_bar (EShellView *shell_view,
|
||
EFolder *folder,
|
||
gboolean is_my_evolution)
|
||
{
|
||
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) {
|
||
if (is_my_evolution) {
|
||
folder_type_name = "My Evolution";
|
||
} else {
|
||
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);
|
||
if (is_my_evolution) {
|
||
folder_name = "My Evolution";
|
||
} else {
|
||
folder_name = e_folder_get_name (folder);
|
||
}
|
||
}
|
||
|
||
if (folder_icon)
|
||
e_shell_folder_title_bar_set_icon (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar), folder_icon);
|
||
if (folder_name) {
|
||
gchar * utf;
|
||
utf = e_utf8_to_gtk_string (GTK_WIDGET (priv->view_title_bar), folder_name);
|
||
e_shell_folder_title_bar_set_title (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar), utf);
|
||
g_free (utf);
|
||
}
|
||
}
|
||
|
||
static void
|
||
update_for_current_uri (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EFolder *folder;
|
||
char *folder_name;
|
||
const char *path;
|
||
char *window_title;
|
||
gboolean is_my_evolution = FALSE;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
/* if we update when there is a timeout set, the selection
|
||
* will jump around against the user's wishes. so we just
|
||
* return.
|
||
*/
|
||
if (priv->set_folder_timeout != 0)
|
||
return;
|
||
|
||
path = get_storage_set_path_from_uri (priv->uri);
|
||
|
||
if (priv->uri != NULL && strcmp (priv->uri, "evolution:/My Evolution") == 0) {
|
||
/* Special case for My Evolution */
|
||
folder_name = g_strdup (_("My Evolution"));
|
||
is_my_evolution = TRUE;
|
||
folder = NULL;
|
||
} else {
|
||
if (path == NULL)
|
||
folder = NULL;
|
||
else
|
||
folder = e_storage_set_get_folder (e_shell_get_storage_set (priv->shell),
|
||
path);
|
||
|
||
if (folder == NULL)
|
||
folder_name = g_strdup (_("None"));
|
||
else
|
||
folder_name = e_utf8_to_gtk_string ((GtkWidget *) shell_view, e_folder_get_name (folder));
|
||
}
|
||
|
||
if (SUB_VERSION[0] == '\0')
|
||
window_title = g_strdup_printf (_("%s - Evolution %s"), folder_name, VERSION);
|
||
else
|
||
window_title = g_strdup_printf (_("%s - Evolution %s [%s]"), folder_name, VERSION, SUB_VERSION);
|
||
|
||
gtk_window_set_title (GTK_WINDOW (shell_view), window_title);
|
||
g_free (window_title);
|
||
g_free (folder_name);
|
||
|
||
update_folder_title_bar (shell_view, folder, is_my_evolution);
|
||
|
||
update_window_icon (shell_view, folder, is_my_evolution);
|
||
|
||
gtk_signal_handler_block_by_func (GTK_OBJECT (priv->storage_set_view),
|
||
GTK_SIGNAL_FUNC (folder_selected_cb),
|
||
shell_view);
|
||
|
||
if (path != NULL)
|
||
e_storage_set_view_set_current_folder (E_STORAGE_SET_VIEW (priv->storage_set_view), path);
|
||
|
||
gtk_signal_handler_unblock_by_func (GTK_OBJECT (priv->storage_set_view),
|
||
GTK_SIGNAL_FUNC (folder_selected_cb),
|
||
shell_view);
|
||
}
|
||
|
||
static void
|
||
update_offline_toggle_status (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GdkPixmap *icon_pixmap;
|
||
GdkBitmap *icon_mask;
|
||
const char *tooltip;
|
||
gboolean sensitive;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
switch (e_shell_get_line_status (priv->shell)) {
|
||
case E_SHELL_LINE_STATUS_ONLINE:
|
||
icon_pixmap = online_pixmap;
|
||
icon_mask = online_mask;
|
||
sensitive = TRUE;
|
||
tooltip = _("Evolution is currently online. "
|
||
"Click on this button to work offline.");
|
||
break;
|
||
case E_SHELL_LINE_STATUS_GOING_OFFLINE:
|
||
icon_pixmap = online_pixmap;
|
||
icon_mask = online_mask;
|
||
sensitive = FALSE;
|
||
tooltip = _("Evolution is in the process of going offline.");
|
||
break;
|
||
case E_SHELL_LINE_STATUS_OFFLINE:
|
||
icon_pixmap = offline_pixmap;
|
||
icon_mask = offline_mask;
|
||
sensitive = TRUE;
|
||
tooltip = _("Evolution is currently offline. "
|
||
"Click on this button to work online.");
|
||
break;
|
||
default:
|
||
g_assert_not_reached ();
|
||
return;
|
||
}
|
||
|
||
gtk_pixmap_set (GTK_PIXMAP (priv->offline_toggle_pixmap), icon_pixmap, icon_mask);
|
||
gtk_widget_set_sensitive (priv->offline_toggle, sensitive);
|
||
gtk_tooltips_set_tip (priv->tooltips, priv->offline_toggle, tooltip, NULL);
|
||
}
|
||
|
||
/* This displays the specified page, doing the appropriate Bonobo activation/deactivation
|
||
magic to make sure things work nicely. FIXME: Crappy way to solve the issue. */
|
||
static void
|
||
set_current_notebook_page (EShellView *shell_view,
|
||
int page_num)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GtkNotebook *notebook;
|
||
GtkWidget *current;
|
||
BonoboControlFrame *control_frame;
|
||
int current_page;
|
||
|
||
priv = shell_view->priv;
|
||
notebook = GTK_NOTEBOOK (priv->notebook);
|
||
|
||
current_page = gtk_notebook_get_current_page (notebook);
|
||
if (current_page == page_num)
|
||
return;
|
||
|
||
if (current_page != -1 && current_page != 0) {
|
||
current = gtk_notebook_get_nth_page (notebook, current_page);
|
||
control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (current));
|
||
|
||
bonobo_control_frame_set_autoactivate (control_frame, FALSE);
|
||
bonobo_control_frame_control_deactivate (control_frame);
|
||
}
|
||
|
||
gtk_notebook_set_page (notebook, page_num);
|
||
|
||
if (page_num == -1 || page_num == 0)
|
||
return;
|
||
|
||
current = gtk_notebook_get_nth_page (notebook, page_num);
|
||
control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (current));
|
||
|
||
bonobo_control_frame_set_autoactivate (control_frame, FALSE);
|
||
bonobo_control_frame_control_activate (control_frame);
|
||
}
|
||
|
||
static void
|
||
setup_corba_interface (EShellView *shell_view,
|
||
GtkWidget *control)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
BonoboControlFrame *control_frame;
|
||
EvolutionShellView *corba_interface;
|
||
|
||
g_return_if_fail (control != NULL);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (control));
|
||
corba_interface = evolution_shell_view_new ();
|
||
|
||
gtk_signal_connect_while_alive (GTK_OBJECT (corba_interface), "set_message",
|
||
GTK_SIGNAL_FUNC (corba_interface_set_message_cb),
|
||
shell_view, GTK_OBJECT (shell_view));
|
||
gtk_signal_connect_while_alive (GTK_OBJECT (corba_interface), "unset_message",
|
||
GTK_SIGNAL_FUNC (corba_interface_unset_message_cb),
|
||
shell_view, GTK_OBJECT (shell_view));
|
||
gtk_signal_connect_while_alive (GTK_OBJECT (corba_interface), "change_current_view",
|
||
GTK_SIGNAL_FUNC (corba_interface_change_current_view_cb),
|
||
shell_view, GTK_OBJECT (shell_view));
|
||
gtk_signal_connect_while_alive (GTK_OBJECT (corba_interface), "set_title",
|
||
GTK_SIGNAL_FUNC (corba_interface_set_title),
|
||
shell_view, GTK_OBJECT (shell_view));
|
||
gtk_signal_connect_while_alive (GTK_OBJECT (corba_interface), "set_folder_bar_label",
|
||
GTK_SIGNAL_FUNC (corba_interface_set_folder_bar_label),
|
||
shell_view, GTK_OBJECT (shell_view));
|
||
|
||
bonobo_object_add_interface (BONOBO_OBJECT (control_frame),
|
||
BONOBO_OBJECT (corba_interface));
|
||
|
||
bonobo_object_ref (BONOBO_OBJECT (corba_interface));
|
||
priv->corba_interface = corba_interface;
|
||
}
|
||
|
||
|
||
/* Socket destruction handling. */
|
||
|
||
static GtkWidget *
|
||
find_socket (GtkContainer *container)
|
||
{
|
||
GList *children, *tmp;
|
||
|
||
children = gtk_container_children (container);
|
||
while (children) {
|
||
if (BONOBO_IS_SOCKET (children->data))
|
||
return children->data;
|
||
else if (GTK_IS_CONTAINER (children->data)) {
|
||
GtkWidget *socket = find_socket (children->data);
|
||
if (socket)
|
||
return socket;
|
||
}
|
||
tmp = children->next;
|
||
g_list_free_1 (children);
|
||
children = tmp;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
static void
|
||
socket_destroy_cb (GtkWidget *socket_widget, gpointer data)
|
||
{
|
||
EShellView *shell_view;
|
||
EShellViewPrivate *priv;
|
||
EFolder *folder;
|
||
GtkWidget *control;
|
||
const char *uri;
|
||
gboolean viewing_closed_uri;
|
||
char *copy_of_uri;
|
||
|
||
shell_view = E_SHELL_VIEW (data);
|
||
priv = shell_view->priv;
|
||
|
||
uri = (const char *) gtk_object_get_data (GTK_OBJECT (socket_widget), "e_shell_view_folder_uri");
|
||
|
||
/* Strdup here as the string will be freed when the socket is destroyed. */
|
||
copy_of_uri = g_strdup (uri);
|
||
|
||
control = g_hash_table_lookup (priv->uri_to_control, uri);
|
||
if (control == NULL) {
|
||
g_warning ("What?! Destroyed socket for non-existing URI? -- %s", uri);
|
||
return;
|
||
}
|
||
|
||
priv->sockets = g_list_remove (priv->sockets, socket_widget);
|
||
|
||
gtk_widget_destroy (control);
|
||
g_hash_table_remove (priv->uri_to_control, uri);
|
||
|
||
folder = e_storage_set_get_folder (e_shell_get_storage_set (priv->shell),
|
||
get_storage_set_path_from_uri (uri));
|
||
|
||
/* See if we were actively viewing the uri for the socket that's being closed */
|
||
viewing_closed_uri = !strcmp (uri, e_shell_view_get_current_uri (shell_view));
|
||
|
||
if (viewing_closed_uri)
|
||
e_shell_view_display_uri (shell_view, NULL);
|
||
|
||
e_shell_component_maybe_crashed (priv->shell,
|
||
uri,
|
||
e_folder_get_type_string (folder),
|
||
shell_view);
|
||
|
||
/* We were actively viewing the component that just crashed, so flip to the Inbox */
|
||
if (viewing_closed_uri)
|
||
e_shell_view_display_uri (shell_view, DEFAULT_URI);
|
||
|
||
g_free (copy_of_uri);
|
||
}
|
||
|
||
|
||
static const char *
|
||
get_type_for_storage (EShellView *shell_view,
|
||
const char *name,
|
||
const char **physical_uri_return)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EStorageSet *storage_set;
|
||
EStorage *storage;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
storage_set = e_shell_get_storage_set (priv->shell);
|
||
storage = e_storage_set_get_storage (storage_set, name);
|
||
if (!storage)
|
||
return NULL;
|
||
|
||
*physical_uri_return = e_storage_get_toplevel_node_uri (storage);
|
||
|
||
return e_storage_get_toplevel_node_type (storage);
|
||
}
|
||
|
||
static const char *
|
||
get_type_for_folder (EShellView *shell_view,
|
||
const char *path,
|
||
const char **physical_uri_return)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EStorageSet *storage_set;
|
||
EFolder *folder;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
storage_set = e_shell_get_storage_set (priv->shell);
|
||
folder = e_storage_set_get_folder (storage_set, path);
|
||
if (!folder)
|
||
return NULL;
|
||
|
||
*physical_uri_return = e_folder_get_physical_uri (folder);
|
||
|
||
return e_folder_get_type_string (folder);
|
||
}
|
||
|
||
/* Create a new view for @uri with @control. It assumes a view for @uri does not exist yet. */
|
||
static GtkWidget *
|
||
get_control_for_uri (EShellView *shell_view,
|
||
const char *uri)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
CORBA_Environment ev;
|
||
EvolutionShellComponentClient *handler_client;
|
||
EFolderTypeRegistry *folder_type_registry;
|
||
GNOME_Evolution_ShellComponent handler;
|
||
Bonobo_UIContainer container;
|
||
GtkWidget *control;
|
||
GtkWidget *socket;
|
||
Bonobo_Control corba_control;
|
||
const char *path;
|
||
const char *slash;
|
||
const char *physical_uri;
|
||
const char *folder_type;
|
||
int destroy_connection_id;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
path = strchr (uri, ':');
|
||
if (path == NULL)
|
||
return NULL;
|
||
|
||
path++;
|
||
if (*path == '\0')
|
||
return NULL;
|
||
|
||
/* Hack for My Evolution */
|
||
if (strcmp (path, "/My Evolution") == 0) {
|
||
folder_type = "My Evolution";
|
||
physical_uri = "";
|
||
} else {
|
||
/* FIXME: This code needs to be made more robust. */
|
||
|
||
slash = strchr (path + 1, G_DIR_SEPARATOR);
|
||
if (slash == NULL || slash[1] == '\0')
|
||
folder_type = get_type_for_storage (shell_view, path + 1, &physical_uri);
|
||
else
|
||
folder_type = get_type_for_folder (shell_view, path, &physical_uri);
|
||
if (folder_type == NULL)
|
||
return NULL;
|
||
}
|
||
|
||
folder_type_registry = e_shell_get_folder_type_registry (e_shell_view_get_shell (shell_view));
|
||
|
||
handler_client = e_folder_type_registry_get_handler_for_type (folder_type_registry, folder_type);
|
||
if (handler_client == CORBA_OBJECT_NIL)
|
||
return NULL;
|
||
|
||
handler = bonobo_object_corba_objref (BONOBO_OBJECT (handler_client));
|
||
|
||
CORBA_exception_init (&ev);
|
||
|
||
corba_control = GNOME_Evolution_ShellComponent_createView (handler, physical_uri, folder_type, &ev);
|
||
|
||
if (ev._major != CORBA_NO_EXCEPTION) {
|
||
CORBA_exception_free (&ev);
|
||
return NULL;
|
||
}
|
||
|
||
CORBA_exception_free (&ev);
|
||
|
||
if (corba_control == CORBA_OBJECT_NIL)
|
||
return NULL;
|
||
|
||
container = bonobo_ui_component_get_container (priv->ui_component);
|
||
control = bonobo_widget_new_control_from_objref (corba_control, container);
|
||
|
||
socket = find_socket (GTK_CONTAINER (control));
|
||
destroy_connection_id = gtk_signal_connect (GTK_OBJECT (socket), "destroy",
|
||
GTK_SIGNAL_FUNC (socket_destroy_cb),
|
||
shell_view);
|
||
gtk_object_set_data (GTK_OBJECT (socket),
|
||
"e_shell_view_destroy_connection_id",
|
||
GINT_TO_POINTER (destroy_connection_id));
|
||
gtk_object_set_data_full (GTK_OBJECT (socket), "e_shell_view_folder_uri", g_strdup (uri), g_free);
|
||
|
||
priv->sockets = g_list_prepend (priv->sockets, socket);
|
||
|
||
setup_corba_interface (shell_view, control);
|
||
|
||
return control;
|
||
}
|
||
|
||
static gboolean
|
||
show_existing_view (EShellView *shell_view,
|
||
const char *uri,
|
||
GtkWidget *control)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
int notebook_page;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
notebook_page = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), control);
|
||
g_assert (notebook_page != -1);
|
||
|
||
/* A BonoboWidget can be a "zombie" in the sense that its actual
|
||
control is dead; if it's zombie, we have to recreate it. */
|
||
if (bonobo_widget_is_dead (BONOBO_WIDGET (control))) {
|
||
GtkWidget *parent;
|
||
|
||
parent = control->parent;
|
||
|
||
/* Out with the old. */
|
||
gtk_container_remove (GTK_CONTAINER (parent), control);
|
||
g_hash_table_remove (priv->uri_to_control, uri);
|
||
|
||
/* In with the new. */
|
||
control = get_control_for_uri (shell_view, uri);
|
||
if (control == NULL)
|
||
return FALSE;
|
||
|
||
gtk_container_add (GTK_CONTAINER (parent), control);
|
||
g_hash_table_insert (priv->uri_to_control, g_strdup (uri), control);
|
||
|
||
/* Show. */
|
||
gtk_widget_show (control);
|
||
}
|
||
|
||
g_free (priv->uri);
|
||
priv->uri = g_strdup (uri);
|
||
|
||
set_current_notebook_page (shell_view, notebook_page);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
create_new_view_for_uri (EShellView *shell_view,
|
||
const char *uri)
|
||
{
|
||
GtkWidget *control;
|
||
EShellViewPrivate *priv;
|
||
int page_num;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
control = get_control_for_uri (shell_view, uri);
|
||
if (control == NULL)
|
||
return FALSE;
|
||
|
||
g_free (priv->uri);
|
||
priv->uri = g_strdup (uri);
|
||
|
||
gtk_widget_show (control);
|
||
|
||
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), control, NULL);
|
||
|
||
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), control);
|
||
g_assert (page_num != -1);
|
||
set_current_notebook_page (shell_view, page_num);
|
||
|
||
g_hash_table_insert (priv->uri_to_control, g_strdup (uri), control);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
gboolean
|
||
e_shell_view_display_uri (EShellView *shell_view,
|
||
const char *uri)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GtkWidget *control;
|
||
gboolean retval;
|
||
|
||
g_return_val_if_fail (shell_view != NULL, FALSE);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
bonobo_window_freeze (BONOBO_WINDOW (shell_view));
|
||
|
||
if (uri == NULL) {
|
||
gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), 0);
|
||
gtk_notebook_prepend_page (GTK_NOTEBOOK (priv->notebook), create_label_for_empty_page (), NULL);
|
||
|
||
set_current_notebook_page (shell_view, 0);
|
||
|
||
g_free (priv->uri);
|
||
priv->uri = NULL;
|
||
|
||
retval = TRUE;
|
||
goto end;
|
||
}
|
||
|
||
if (strncmp (uri, E_SHELL_URI_PREFIX, E_SHELL_URI_PREFIX_LEN) != 0) {
|
||
retval = FALSE;
|
||
goto end;
|
||
}
|
||
|
||
control = g_hash_table_lookup (priv->uri_to_control, uri);
|
||
if (control != NULL) {
|
||
g_assert (GTK_IS_WIDGET (control));
|
||
show_existing_view (shell_view, uri, control);
|
||
} else if (create_new_view_for_uri (shell_view, uri)) {
|
||
priv->delayed_selection = g_strdup (uri);
|
||
gtk_signal_connect_after (GTK_OBJECT (e_shell_get_storage_set (priv->shell)), "new_folder",
|
||
GTK_SIGNAL_FUNC (new_folder_cb), shell_view);
|
||
retval = FALSE;
|
||
goto end;
|
||
}
|
||
|
||
retval = TRUE;
|
||
|
||
end:
|
||
g_free (priv->set_folder_uri);
|
||
priv->set_folder_uri = NULL;
|
||
|
||
if (priv->set_folder_timeout != 0) {
|
||
gtk_timeout_remove (priv->set_folder_timeout);
|
||
priv->set_folder_timeout = 0;
|
||
}
|
||
|
||
update_for_current_uri (shell_view);
|
||
|
||
bonobo_window_thaw (BONOBO_WINDOW (shell_view));
|
||
|
||
return retval;
|
||
}
|
||
|
||
gboolean
|
||
e_shell_view_remove_control_for_uri (EShellView *shell_view,
|
||
const char *uri)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
GtkWidget *control;
|
||
GtkWidget *socket;
|
||
int page_num;
|
||
|
||
g_return_val_if_fail (shell_view != NULL, FALSE);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
/* Get the control, remove it from our hash of controls */
|
||
control = g_hash_table_lookup (priv->uri_to_control, uri);
|
||
if (control != NULL)
|
||
g_hash_table_remove (priv->uri_to_control, uri);
|
||
else
|
||
return FALSE;
|
||
|
||
/* Get the socket, remove it from our list of sockets */
|
||
socket = find_socket (GTK_CONTAINER (control));
|
||
priv->sockets = g_list_remove (priv->sockets, socket);
|
||
|
||
/* Remove the notebook page */
|
||
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
|
||
control);
|
||
gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook),
|
||
page_num);
|
||
|
||
/* Destroy things, socket first because otherwise shell will
|
||
think the control crashed */
|
||
gtk_widget_destroy (socket);
|
||
gtk_widget_destroy (control);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void
|
||
e_shell_view_set_shortcut_bar_mode (EShellView *shell_view,
|
||
EShellViewSubwindowMode mode)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
g_return_if_fail (shell_view != NULL);
|
||
g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
|
||
g_return_if_fail (mode == E_SHELL_VIEW_SUBWINDOW_STICKY
|
||
|| mode == E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
if (priv->shortcut_bar_mode == mode)
|
||
return;
|
||
|
||
if (mode == E_SHELL_VIEW_SUBWINDOW_STICKY) {
|
||
if (! GTK_WIDGET_VISIBLE (priv->shortcut_frame)) {
|
||
gtk_widget_show (priv->shortcut_frame);
|
||
e_paned_set_position (E_PANED (priv->hpaned), priv->hpaned_position);
|
||
}
|
||
} else {
|
||
if (GTK_WIDGET_VISIBLE (priv->shortcut_frame)) {
|
||
gtk_widget_hide (priv->shortcut_frame);
|
||
/* FIXME this is a private field! */
|
||
priv->hpaned_position = E_PANED (priv->hpaned)->child1_size;
|
||
e_paned_set_position (E_PANED (priv->hpaned), 0);
|
||
}
|
||
}
|
||
|
||
priv->shortcut_bar_mode = mode;
|
||
|
||
gtk_signal_emit (GTK_OBJECT (shell_view), signals[SHORTCUT_BAR_MODE_CHANGED], mode);
|
||
}
|
||
|
||
/**
|
||
* e_shell_view_set_folder_bar_mode:
|
||
* @shell_view:
|
||
* @mode:
|
||
*
|
||
* Set the visualization mode for the folder bar's subwindow.
|
||
**/
|
||
void
|
||
e_shell_view_set_folder_bar_mode (EShellView *shell_view,
|
||
EShellViewSubwindowMode mode)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
|
||
g_return_if_fail (shell_view != NULL);
|
||
g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
|
||
g_return_if_fail (mode == E_SHELL_VIEW_SUBWINDOW_STICKY
|
||
|| mode == E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
if (priv->folder_bar_mode == mode)
|
||
return;
|
||
|
||
if (mode == E_SHELL_VIEW_SUBWINDOW_STICKY) {
|
||
if (! GTK_WIDGET_VISIBLE (priv->storage_set_view_box)) {
|
||
gtk_widget_show (priv->storage_set_view_box);
|
||
e_paned_set_position (E_PANED (priv->view_hpaned), priv->view_hpaned_position);
|
||
}
|
||
|
||
e_title_bar_set_button_mode (E_TITLE_BAR (priv->storage_set_title_bar),
|
||
E_TITLE_BAR_BUTTON_MODE_CLOSE);
|
||
|
||
e_shell_folder_title_bar_set_clickable (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar),
|
||
FALSE);
|
||
} 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->view_hpaned_position = E_PANED (priv->view_hpaned)->child1_size;
|
||
e_paned_set_position (E_PANED (priv->view_hpaned), 0);
|
||
}
|
||
|
||
e_title_bar_set_button_mode (E_TITLE_BAR (priv->storage_set_title_bar),
|
||
E_TITLE_BAR_BUTTON_MODE_PIN);
|
||
|
||
e_shell_folder_title_bar_set_clickable (E_SHELL_FOLDER_TITLE_BAR (priv->view_title_bar),
|
||
TRUE);
|
||
}
|
||
|
||
priv->folder_bar_mode = mode;
|
||
|
||
gtk_signal_emit (GTK_OBJECT (shell_view), signals[FOLDER_BAR_MODE_CHANGED], mode);
|
||
}
|
||
|
||
EShellViewSubwindowMode
|
||
e_shell_view_get_shortcut_bar_mode (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
|
||
return shell_view->priv->shortcut_bar_mode;
|
||
}
|
||
|
||
EShellViewSubwindowMode
|
||
e_shell_view_get_folder_bar_mode (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), E_SHELL_VIEW_SUBWINDOW_HIDDEN);
|
||
|
||
return shell_view->priv->folder_bar_mode;
|
||
}
|
||
|
||
|
||
ETaskBar *
|
||
e_shell_view_get_task_bar (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
return E_TASK_BAR (shell_view->priv->task_bar);
|
||
}
|
||
|
||
EShell *
|
||
e_shell_view_get_shell (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
return shell_view->priv->shell;
|
||
}
|
||
|
||
BonoboUIComponent *
|
||
e_shell_view_get_bonobo_ui_component (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
return shell_view->priv->ui_component;
|
||
}
|
||
|
||
BonoboUIContainer *
|
||
e_shell_view_get_bonobo_ui_container (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
return shell_view->priv->ui_container;
|
||
}
|
||
|
||
GtkWidget *
|
||
e_shell_view_get_appbar (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
return shell_view->priv->appbar;
|
||
}
|
||
|
||
/**
|
||
* e_shell_view_get_current_uri:
|
||
* @shell_view: A pointer to an EShellView object
|
||
*
|
||
* Get the URI currently displayed by this shell view.
|
||
*
|
||
* Return value:
|
||
**/
|
||
const char *
|
||
e_shell_view_get_current_uri (EShellView *shell_view)
|
||
{
|
||
g_return_val_if_fail (shell_view != NULL, NULL);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
|
||
|
||
return shell_view->priv->uri;
|
||
}
|
||
|
||
/**
|
||
* e_shell_view_get_current_path:
|
||
* @shell_view: A pointer to an EShellView object
|
||
*
|
||
* Get the path of the current displayed folder.
|
||
*
|
||
* Return value:
|
||
**/
|
||
const char *
|
||
e_shell_view_get_current_path (EShellView *shell_view)
|
||
{
|
||
const char *current_uri;
|
||
const char *current_path;
|
||
|
||
current_uri = e_shell_view_get_current_uri (shell_view);
|
||
if (current_uri == NULL)
|
||
return NULL;
|
||
|
||
if (strncmp (current_uri, E_SHELL_URI_PREFIX, E_SHELL_URI_PREFIX_LEN) == 0)
|
||
current_path = current_uri + E_SHELL_URI_PREFIX_LEN;
|
||
else
|
||
current_path = NULL;
|
||
|
||
return current_path;
|
||
}
|
||
|
||
static void
|
||
save_shortcut_bar_icon_modes (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EShortcutBar *shortcut_bar;
|
||
int num_groups;
|
||
int group;
|
||
|
||
priv = shell_view->priv;
|
||
shortcut_bar = E_SHORTCUT_BAR (priv->shortcut_bar);
|
||
|
||
num_groups = e_shortcut_model_get_num_groups (shortcut_bar->model);
|
||
|
||
for (group = 0; group < num_groups; group++) {
|
||
char *tmp;
|
||
|
||
tmp = g_strdup_printf ("ShortcutBarGroup%dIconMode", group);
|
||
gnome_config_set_int (tmp, e_shortcut_bar_get_view_type (shortcut_bar, group));
|
||
g_free (tmp);
|
||
}
|
||
}
|
||
|
||
static void
|
||
load_shortcut_bar_icon_modes (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EShortcutBar *shortcut_bar;
|
||
int num_groups;
|
||
int group;
|
||
|
||
priv = shell_view->priv;
|
||
shortcut_bar = E_SHORTCUT_BAR (priv->shortcut_bar);
|
||
|
||
num_groups = e_shortcut_model_get_num_groups (shortcut_bar->model);
|
||
|
||
for (group = 0; group < num_groups; group++) {
|
||
char *tmp;
|
||
int iconmode;
|
||
|
||
tmp = g_strdup_printf ("ShortcutBarGroup%dIconMode", group);
|
||
iconmode = gnome_config_get_int (tmp);
|
||
g_free (tmp);
|
||
|
||
e_shortcut_bar_set_view_type (shortcut_bar, group, iconmode);
|
||
}
|
||
}
|
||
|
||
static char *
|
||
get_local_prefix_for_view (EShellView *shell_view,
|
||
int view_num)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
char *prefix;
|
||
const char *local_directory;
|
||
|
||
priv = shell_view->priv;
|
||
|
||
local_directory = e_shell_get_local_directory (priv->shell);
|
||
|
||
prefix = g_strdup_printf ("=%s/config/Shell=/Views/%d/",
|
||
local_directory, view_num);
|
||
|
||
return prefix;
|
||
}
|
||
|
||
|
||
/**
|
||
* e_shell_view_save_settings:
|
||
* @shell_view:
|
||
* @prefix:
|
||
*
|
||
* Save settings for @shell_view at the specified gnome config @prefix
|
||
*
|
||
* Return value: TRUE if successful, FALSE if not.
|
||
**/
|
||
gboolean
|
||
e_shell_view_save_settings (EShellView *shell_view,
|
||
int view_num)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
const char *uri;
|
||
char *prefix;
|
||
char *filename;
|
||
|
||
g_return_val_if_fail (shell_view != NULL, FALSE);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
prefix = get_local_prefix_for_view (shell_view, view_num);
|
||
g_return_val_if_fail (prefix != NULL, FALSE);
|
||
|
||
gnome_config_push_prefix (prefix);
|
||
|
||
gnome_config_set_int ("CurrentShortcutsGroupNum", e_shell_view_get_current_shortcuts_group_num (shell_view));
|
||
gnome_config_set_int ("FolderBarMode", e_shell_view_get_folder_bar_mode (shell_view));
|
||
gnome_config_set_int ("ShortcutBarMode", e_shell_view_get_shortcut_bar_mode (shell_view));
|
||
gnome_config_set_int ("HPanedPosition", e_paned_get_position (E_PANED (priv->hpaned)));
|
||
gnome_config_set_int ("ViewHPanedPosition", e_paned_get_position (E_PANED (priv->view_hpaned)));
|
||
|
||
uri = e_shell_view_get_current_uri (shell_view);
|
||
if (uri != NULL)
|
||
gnome_config_set_string ("DisplayedURI", uri);
|
||
else
|
||
gnome_config_set_string ("DisplayedURI", DEFAULT_URI);
|
||
|
||
save_shortcut_bar_icon_modes (shell_view);
|
||
|
||
gnome_config_pop_prefix ();
|
||
|
||
/* Save the expanded state for this ShellViews StorageSetView */
|
||
filename = g_strdup_printf ("%s/config/storage-set-view-expanded:view_%d",
|
||
e_shell_get_local_directory (priv->shell),
|
||
view_num);
|
||
e_tree_save_expanded_state (E_TREE (priv->storage_set_view),
|
||
filename);
|
||
|
||
g_free (filename);
|
||
g_free (prefix);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* e_shell_view_load_settings:
|
||
* @shell_view:
|
||
* @prefix:
|
||
*
|
||
* Load settings for @shell_view at the specified gnome config @prefix
|
||
*
|
||
* Return value:
|
||
**/
|
||
gboolean
|
||
e_shell_view_load_settings (EShellView *shell_view,
|
||
int view_num)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
int val;
|
||
char *stringval;
|
||
char *prefix;
|
||
char *filename;
|
||
|
||
g_return_val_if_fail (shell_view != NULL, FALSE);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
prefix = get_local_prefix_for_view (shell_view, view_num);
|
||
g_return_val_if_fail (prefix != NULL, FALSE);
|
||
|
||
gnome_config_push_prefix (prefix);
|
||
|
||
val = gnome_config_get_int ("CurrentShortcutsGroupNum");
|
||
e_shell_view_set_current_shortcuts_group_num (shell_view, val);
|
||
|
||
val = gnome_config_get_int ("FolderBarMode");
|
||
e_shell_view_set_folder_bar_mode (shell_view, val);
|
||
|
||
val = gnome_config_get_int ("ShortcutBarMode");
|
||
e_shell_view_set_shortcut_bar_mode (shell_view, val);
|
||
|
||
val = gnome_config_get_int ("HPanedPosition");
|
||
e_paned_set_position (E_PANED (priv->hpaned), val);
|
||
|
||
val = gnome_config_get_int ("ViewHPanedPosition");
|
||
e_paned_set_position (E_PANED (priv->view_hpaned), val);
|
||
|
||
stringval = gnome_config_get_string ("DisplayedURI");
|
||
if (! e_shell_view_display_uri (shell_view, stringval))
|
||
e_shell_view_display_uri (shell_view, DEFAULT_URI);
|
||
g_free (stringval);
|
||
|
||
load_shortcut_bar_icon_modes (shell_view);
|
||
|
||
gnome_config_pop_prefix ();
|
||
|
||
/* Load the expanded state for the ShellView's StorageSetView */
|
||
filename = g_strdup_printf ("%s/config/storage-set-view-expanded:view_%d",
|
||
e_shell_get_local_directory (priv->shell),
|
||
view_num);
|
||
|
||
e_tree_load_expanded_state (E_TREE (priv->storage_set_view),
|
||
filename);
|
||
|
||
g_free (filename);
|
||
g_free (prefix);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/* FIXME: This function could become static */
|
||
void
|
||
e_shell_view_set_current_shortcuts_group_num (EShellView *shell_view, int group_num)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EShortcutsView *shortcuts_view;
|
||
|
||
g_return_if_fail (shell_view != NULL);
|
||
g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
|
||
|
||
priv = shell_view->priv;
|
||
|
||
shortcuts_view = E_SHORTCUTS_VIEW (priv->shortcut_bar);
|
||
|
||
e_group_bar_set_current_group_num (E_GROUP_BAR (E_SHORTCUT_BAR (shortcuts_view)), group_num, FALSE);
|
||
}
|
||
|
||
int
|
||
e_shell_view_get_current_shortcuts_group_num (EShellView *shell_view)
|
||
{
|
||
EShellViewPrivate *priv;
|
||
EShortcutsView *shortcuts_view;
|
||
int group;
|
||
|
||
g_return_val_if_fail (shell_view != NULL, -1);
|
||
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), -1);
|
||
|
||
priv = shell_view->priv;
|
||
|
||
shortcuts_view = E_SHORTCUTS_VIEW (priv->shortcut_bar);
|
||
|
||
group = e_group_bar_get_current_group_num (E_GROUP_BAR (E_SHORTCUT_BAR (shortcuts_view)));
|
||
|
||
return group;
|
||
}
|
||
|
||
|
||
E_MAKE_TYPE (e_shell_view, "EShellView", EShellView, class_init, init, BONOBO_TYPE_WINDOW)
|