diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2009-08-30 13:37:36 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2009-08-30 13:40:49 +0800 |
commit | cfb9c32b6657165e4d5e11aa7b47804f679a61f8 (patch) | |
tree | 1f9c8954df7a357b5dc20a13ac82bf31c1112083 /shell | |
parent | fefeb30f58447f2fa7bcbee16dbe68a9333ce89d (diff) | |
parent | 0f7f4cfe38b3c4cd83efbe9922ae15c5aee00317 (diff) | |
download | gsoc2013-evolution-cfb9c32b6657165e4d5e11aa7b47804f679a61f8.tar.gz gsoc2013-evolution-cfb9c32b6657165e4d5e11aa7b47804f679a61f8.tar.zst gsoc2013-evolution-cfb9c32b6657165e4d5e11aa7b47804f679a61f8.zip |
Merge commit 'origin/kill-bonobo'
Diffstat (limited to 'shell')
85 files changed, 12914 insertions, 11380 deletions
diff --git a/shell/Evolution-Component.idl b/shell/Evolution-Component.idl deleted file mode 100644 index ccf806ff91..0000000000 --- a/shell/Evolution-Component.idl +++ /dev/null @@ -1,137 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Interface for the Evolution components. - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 2003 Ximian, Inc. - */ - -#ifndef _GNOME_EVOLUTION_COMPONENT_IDL -#define _GNOME_EVOLUTION_COMPONENT_IDL - -#include <Bonobo.idl> - -#ifndef __evolution_shell_COMPILATION -#ifdef __ORBIT_IDL__ -%{ -#pragma include_defs shell/evolution-component.h -%} -#pragma inhibit push -#endif -#endif - -module GNOME { -module Evolution { - enum CreatableItem { - CREATABLE_OBJECT, - CREATABLE_FOLDER - }; - enum ShellState { - USER_OFFLINE, - FORCED_OFFLINE, - USER_ONLINE - }; - - /* A type of item that the component can create when asked by the user, - e.g. a mail message or an appointment. */ - struct CreatableItemType { - string id; - string description; - string menuDescription; - string tooltip; - char menuShortcut; - string iconName; - CreatableItem type; - }; - typedef sequence <CreatableItemType> CreatableItemTypeList; - - interface ComponentView : Bonobo::Unknown { - void getControls (out Bonobo::Control sidebar_control, - out Bonobo::Control view_control, - out Bonobo::Control statusbar_control); - }; - - interface Listener : Bonobo::Unknown { - /* Indicate the change of state is complete */ - void complete(); - }; - - interface Component : Bonobo::Unknown { - exception Failed {}; - exception UnknownType {}; - /* We don't know about the old version we're upgrading from */ - exception UnsupportedVersion {}; - /* We encountered a non-recoverable, fatal error, explain why */ - exception UpgradeFailed { - string what; - string why; - }; - - /*** Upgrade path. ***/ - - void upgradeFromVersion (in short major, in short minor, in short revision) - raises (UnsupportedVersion, UpgradeFailed); - - /*** Basic functionality. ***/ - ComponentView createView(in ShellView parent, - in boolean select_item) - raises (Failed); - - - /* Check if the component can quit. - Do not perform any quit-related tasks however. - May be called multiple times, depending on user interaction. */ - boolean requestQuit (); - - /* Ask the component to quit. Returns TRUE when the - component has completed any closing-down tasks, and - is ready to exit(). This will be called repeatedly - at intervals until it returns TRUE. */ - boolean quit (); - - /* Notify the component of whether the shell is currently - running in interactive mode or not. (I.e. basically, - whether there are any Evolution windows on the screen.) - @new_view_xid is an X Window ID ("None" if @now_interactive - is FALSE) */ - void interactive (in boolean now_interactive, - in unsigned long new_view_xid); - - - /*** The following stuff is needed to build the "New" toolbar - item as well as the "File -> New" submenu. ***/ - - /* List of creatable items. */ - readonly attribute CreatableItemTypeList userCreatableItems; - - /* Pop up a new editing dialog for the item with the specified - @item_type_name. */ - void requestCreateItem (in string item_type_name) - raises (UnknownType, Failed); - - - /*** URI handling (e.g. for the command-line, "evolution - mailto:foo@bar.org") ***/ - void handleURI (in string uri); - - - /*** Send/receive. ***/ - - void sendAndReceive (); - - /* Set the online status of the component asynchronously */ - - void setLineStatus(in ShellState shell_state, in Listener listener); - }; - -}; -}; - -#ifndef __evolution_shell_COMPILATION -#ifdef __ORBIT_IDL__ -#pragma inhibit pop -#endif -#endif -#endif /* _GNOME_EVOLUTION_COMPONENT_IDL */ diff --git a/shell/Evolution-ConfigControl.idl b/shell/Evolution-ConfigControl.idl deleted file mode 100644 index 901932d209..0000000000 --- a/shell/Evolution-ConfigControl.idl +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Additional interfaces for the Controls used in configuration dialogs. - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. - */ - -#ifndef _GNOME_EVOLUTION_CONFIGCONTROL_IDL -#define _GNOME_EVOLUTION_CONFIGCONTROL_IDL - -module GNOME { -module Evolution { - interface ConfigControl : Bonobo::Unknown { - /* The actual Control. */ - readonly attribute Bonobo::Control control; - - /* Get the event source for this control. */ - readonly attribute Bonobo::EventSource eventSource; - }; -}; /* module Evolution */ -}; /* module GNOME */ - -#endif diff --git a/shell/Evolution-Shell.idl b/shell/Evolution-Shell.idl deleted file mode 100644 index d39ec8edeb..0000000000 --- a/shell/Evolution-Shell.idl +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Interface for the Evolution shell. - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 2000, 2001 Ximian, Inc. - */ - -#ifndef _GNOME_EVOLUTION_SHELL_IDL -#define _GNOME_EVOLUTION_SHELL_IDL - -#include <Bonobo.idl> - -#ifndef __evolution_shell_COMPILATION -#ifdef __ORBIT_IDL__ -%{ -#pragma include_defs shell/evolution-component.h -%} -#pragma inhibit push -#endif -#endif - -module GNOME { -module Evolution { - - - interface ShellView : Bonobo::Unknown { - /* Should really use a ComponentView i guess */ - void setTitle(in string component, in string title); - void setComponent(in string component); - void setButtonIcon(in string component, in string iconName); - }; - - interface Shell : Bonobo::Unknown { - exception Busy {}; - exception ComponentNotFound {}; - exception InternalError {}; - exception InvalidURI {}; - exception NotFound {}; - exception NotReady {}; - exception UnsupportedSchema {}; - - /** - * createNewWindow: - * @component_id: id or alias of the component to display in the new window. - * - */ - ShellView createNewWindow (in string component_id) - raises (NotReady, ComponentNotFound, UnsupportedSchema, InternalError); - - /** - * handleURI: - * @uri: URI to handle - * - * This handles the specified URI. It is different from - * `::createNewView' as it doesn't necessarily imply creating a - * new ShellView. (For example, a `mailto:' URI will invoke - * the message composer.) - */ - void handleURI (in string uri) - raises (NotReady, ComponentNotFound, NotFound, UnsupportedSchema, InvalidURI, InternalError); - - /** - * setLineStatus: - * - * Set the shell into on-line or off-line mode. - */ - void setLineStatus (in boolean online) - raises (NotReady); - - /* - * Lookup a component by id. - */ - /*Component findComponent(in string id) - raises (NotReady, ComponentNotFound);*/ - }; -}; -}; - -#ifndef __evolution_shell_COMPILATION -#ifdef __ORBIT_IDL__ -#pragma inhibit pop -#endif -#endif -#endif /* _GNOME_EVOLUTION_SHELL_IDL */ diff --git a/shell/Evolution.idl b/shell/Evolution.idl deleted file mode 100644 index 059d017444..0000000000 --- a/shell/Evolution.idl +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * CORBA interface for the Evolution shell. - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 2000, 2001 Ximian, Inc. - */ - -#ifndef _GNOME_EVOLUTION_IDL -#define _GNOME_EVOLUTION_IDL - -#include <Bonobo.idl> - -#include <Evolution-ConfigControl.idl> -#include <Evolution-Shell.idl> -#include <Evolution-Component.idl> - -#endif diff --git a/shell/GNOME_Evolution_Shell.server.in.in b/shell/GNOME_Evolution_Shell.server.in.in deleted file mode 100644 index b055f3000d..0000000000 --- a/shell/GNOME_Evolution_Shell.server.in.in +++ /dev/null @@ -1,26 +0,0 @@ -<oaf_info> - - <oaf_server iid="OAFIID:GNOME_Evolution_Shell:@VERSION@" - type="exe" - location="@BINDIR_IN_SERVER_FILE@/evolution@EXEEXT@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/Evolution/Shell:@VERSION@"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" - _value="Evolution Shell"/> - </oaf_server> - - <oaf_server iid="OAFIID:GNOME_Evolution_Shell_Config_Factory:@VERSION@" - type="exe" - location="@BINDIR_IN_SERVER_FILE@/evolution-@VERSION@@EXEEXT@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/GenericFactory:1.0"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" _value="Evolution Shell Config factory"/> - </oaf_server> - -</oaf_info> diff --git a/shell/Makefile.am b/shell/Makefile.am index ecf0dc4f47..a17c11a875 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -4,6 +4,7 @@ endif AM_CPPFLAGS = \ -I$(top_srcdir)/widgets \ + -I$(top_srcdir)/widgets/menus \ -I$(top_srcdir)/widgets/misc \ -I$(top_srcdir) \ -I$(top_srcdir)/shell \ @@ -11,8 +12,11 @@ AM_CPPFLAGS = \ -DEVOLUTION_IMAGESDIR=\""$(imagesdir)"\" \ -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \ -DEVOLUTION_DATADIR=\""$(datadir)"\" \ + -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ -DEVOLUTION_HELPDIR=\""$(evolutionhelpdir)"\" \ + -DEVOLUTION_MODULEDIR=\""$(moduledir)"\" \ + -DEVOLUTION_RULEDIR=\""$(privdatadir)"\" \ -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \ -DEVOLUTION_TOOLSDIR=\""$(privlibexecdir)"\" \ -DPREFIX=\""$(prefix)"\" \ @@ -26,62 +30,15 @@ AM_CPPFLAGS = \ if NM_SUPPORT AM_CPPFLAGS += \ $(DBUS_GLIB_CFLAGS) \ - $(NM_FLAGS) + $(NM_CFLAGS) endif bin_PROGRAMS = evolution -# Shell CORBA stuff - -IDLS = \ - Evolution-ConfigControl.idl \ - Evolution-Component.idl \ - Evolution-Shell.idl \ - Evolution.idl - -IDL_GENERATED_H = \ - Evolution.h - -IDL_GENERATED_C = \ - Evolution-common.c \ - Evolution-skels.c \ - Evolution-stubs.c - -idl_defines = \ - -D__evolution_shell_COMPILATION - -IDL_GENERATED = $(IDL_GENERATED_H) $(IDL_GENERATED_C) - -$(IDL_GENERATED_H): $(IDLS) - $(ORBIT_IDL) -I $(srcdir) $(idl_defines) $(IDL_INCLUDES) $(srcdir)/Evolution.idl - -$(IDL_GENERATED_C): $(IDL_GENERATED_H) - if NM_SUPPORT -NM_SUPPORT_FILES = e-shell-nm.c +NM_SUPPORT_FILES = e-shell-nm.c endif -# Data Server CORBA stuff -DATASERVER_IDL_GENERATED_H = \ - Evolution-DataServer.h - -DATASERVER_IDL_GENERATED_C = \ - Evolution-DataServer-common.c \ - Evolution-DataServer-skels.c \ - Evolution-DataServer-stubs.c - -DATASERVER_IDL_GENERATED = $(DATASERVER_IDL_GENERATED_C) $(DATASERVER_IDL_GENERATED_H) - -$(DATASERVER_IDL_GENERATED_H): $(DATASERVER_IDL) - $(ORBIT_IDL) -I $(srcdir) $(IDL_INCLUDES) $(DATASERVER_IDL) - -$(DATASERVER_IDL_GENERATED_C): $(DATASERVER_IDL_GENERATED_H) - - -# IDL install - -idl_DATA = $(IDLS) - # Shell library privsolib_LTLIBRARIES = \ @@ -90,33 +47,55 @@ privsolib_LTLIBRARIES = \ eshellincludedir = $(privincludedir)/shell eshellinclude_HEADERS = \ - Evolution.h \ - e-component-view.h \ - e-user-creatable-items-handler.h \ - evolution-config-control.h \ - evolution-component.h \ - evolution-listener.h \ - evolution-shell-component-utils.h \ - es-event.h \ - es-menu.h + e-shell.h \ + e-shell-backend.h \ + e-shell-common.h \ + e-shell-content.h \ + e-shell-settings.h \ + e-shell-sidebar.h \ + e-shell-switcher.h \ + e-shell-taskbar.h \ + e-shell-view.h \ + e-shell-window.h \ + es-event.h libeshell_la_SOURCES = \ + $(NM_SUPPORT_FILES) \ $(IDL_GENERATED) \ - e-component-view.c \ - evolution-component.c \ - evolution-listener.c \ - e-user-creatable-items-handler.c \ - evolution-config-control.c \ - evolution-shell-component-utils.c \ - $(eshellinclude_HEADERS) + e-shell.c \ + e-shell-backend.c \ + e-shell-content.c \ + e-shell-settings.c \ + e-shell-sidebar.c \ + e-shell-switcher.c \ + e-shell-taskbar.c \ + e-shell-view.c \ + e-shell-window.c \ + e-shell-window-private.c \ + e-shell-window-private.h \ + $(eshellinclude_HEADERS) \ + e-shell-importer.c \ + e-shell-importer.h \ + e-shell-migrate.c \ + e-shell-migrate.h \ + e-shell-window-actions.h \ + e-shell-window-actions.c \ + es-event.c libeshell_la_LDFLAGS = $(NO_UNDEFINED) libeshell_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/filter/libfilter.la \ + $(top_builddir)/smclient/libeggsmclient.la \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/widgets/menus/libmenus.la \ $(SHELL_LIBS) +if NM_SUPPORT +libeshell_la_LIBADD += $(DBUS_GLIB_LIBS) +endif + # Evolution executable if HAVE_WINDRES @@ -124,36 +103,14 @@ EVOLUTIONICONRC = evolution-icon.o endif evolution_SOURCES = \ - $(DATASERVER_IDL_GENERATED) \ - $(NM_SUPPORT_FILES) \ - e-component-registry.c \ - e-component-registry.h \ e-config-upgrade.c \ e-config-upgrade.h \ - e-corba-config-page.c \ - e-corba-config-page.h \ - e-shell.c \ - e-shell.h \ - e-shell-constants.h \ - e-shell-importer.c \ - e-shell-importer.h \ - e-shell-settings-dialog.c \ - e-shell-settings-dialog.h \ - e-shell-window-commands.c \ - e-shell-window-commands.h \ - e-shell-window.c \ - e-shell-window.h \ - e-shell-view.c \ - e-shell-view.h \ - e-sidebar.c \ - e-sidebar.h \ - es-event.c \ - es-menu.c \ main.c evolution_LDADD = \ libeshell.la \ $(top_builddir)/widgets/e-timezone-dialog/libetimezonedialog.la \ + $(top_builddir)/widgets/menus/libmenus.la \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ $(top_builddir)/e-util/libeutil.la \ $(TZDIALOG_LIBS) \ @@ -166,19 +123,10 @@ endif # Misc stuff -server_in_files = GNOME_Evolution_Shell.server.in.in -server_DATA = $(server_in_files:.server.in.in=.server) -@EVO_SERVER_RULE@ -@INTLTOOL_SERVER_RULE@ - error_DATA = shell.error errordir = $(privdatadir)/errors @EVO_PLUGIN_RULE@ -glade_DATA = \ - e-active-connection-dialog.glade \ - import.glade - # GConf schemas schemadir = $(GCONF_SCHEMA_FILE_DIR) @@ -210,10 +158,7 @@ endif # Extra dist stuff EXTRA_DIST = \ - $(IDLS) \ - $(server_in_files) \ shell.error.xml \ - $(glade_DATA) \ $(schema_in_files) \ ChangeLog.pre-1-4 \ evolution-nognome.in \ @@ -237,7 +182,7 @@ evolution.pure: evolution endif -BUILT_SOURCES = $(IDL_GENERATED) $(server_DATA) $(DATASERVER_IDL_GENERATED) $(error_DATA) +BUILT_SOURCES = $(error_DATA) CLEANFILES = $(BUILT_SOURCES) DISTCLEANFILES = $(schema_DATA) diff --git a/shell/apps_evolution_shell.schemas.in b/shell/apps_evolution_shell.schemas.in index c5c6276c25..157df8cb9e 100644 --- a/shell/apps_evolution_shell.schemas.in +++ b/shell/apps_evolution_shell.schemas.in @@ -60,7 +60,7 @@ <schema> <key>/schemas/apps/evolution/shell/current_folder</key> - <applyto>/apps/evolution/shell/current-folder</applyto> + <applyto>/apps/evolution/shell/current_folder</applyto> <owner>evolution</owner> <type>string</type> <locale name="C"> @@ -99,44 +99,54 @@ <!-- View defaults --> <schema> - <key>/schemas/apps/evolution/shell/view_defaults/width</key> - <applyto>/apps/evolution/shell/view_defaults/width</applyto> + <key>/schemas/apps/evolution/shell/view_defaults/window_y</key> + <applyto>/apps/evolution/shell/view_defaults/window_y</applyto> <owner>evolution</owner> <type>int</type> - <default>640</default> <locale name="C"> - <short>Default window width</short> - <long>The default width for the main window, in pixels.</long> + <short>Default window Y coordinate</short> + <long>The default Y coordinate for the main window.</long> </locale> </schema> <schema> - <key>/schemas/apps/evolution/shell/view_defaults/height</key> - <applyto>/apps/evolution/shell/view_defaults/height</applyto> + <key>/schemas/apps/evolution/shell/view_defaults/window_x</key> + <applyto>/apps/evolution/shell/view_defaults/window_x</applyto> <owner>evolution</owner> <type>int</type> - <default>480</default> <locale name="C"> - <short>Default window height</short> - <long>The default height for the main window, in pixels.</long> + <short>Default window X coordinate</short> + <long>The default X coordinate for the main window.</long> </locale> </schema> <schema> - <key>/schemas/apps/evolution/shell/view_defaults/maximized</key> - <applyto>/apps/evolution/shell/view_defaults/maximized</applyto> + <key>/schemas/apps/evolution/shell/view_defaults/window_width</key> + <applyto>/apps/evolution/shell/view_defaults/window_width</applyto> <owner>evolution</owner> - <type>bool</type> - <default>TRUE</default> + <type>int</type> + <default>640</default> <locale name="C"> - <short>Default window state</short> - <long>Whether or not the window should be maximized.</long> + <short>Default window width</short> + <long>The default width for the main window, in pixels.</long> + </locale> + </schema> + + <schema> + <key>/schemas/apps/evolution/shell/view_defaults/window_height</key> + <applyto>/apps/evolution/shell/view_defaults/window_height</applyto> + <owner>evolution</owner> + <type>int</type> + <default>480</default> + <locale name="C"> + <short>Default window height</short> + <long>The default height for the main window, in pixels.</long> </locale> </schema> <schema> - <key>/schemas/apps/evolution/shell/view_defaults/maximized</key> - <applyto>/apps/evolution/shell/view_defaults/maximized</applyto> + <key>/schemas/apps/evolution/shell/view_defaults/window_maximized</key> + <applyto>/apps/evolution/shell/view_defaults/window_maximized</applyto> <owner>evolution</owner> <type>bool</type> <default>TRUE</default> diff --git a/shell/e-active-connection-dialog.glade b/shell/e-active-connection-dialog.glade deleted file mode 100644 index 534a7948f7..0000000000 --- a/shell/e-active-connection-dialog.glade +++ /dev/null @@ -1,193 +0,0 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> -<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> - -<glade-interface> - -<widget class="GtkDialog" id="active_connection_dialog"> - <property name="visible">True</property> - <property name="title" translatable="yes">Active Connections</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="modal">False</property> - <property name="default_width">256</property> - <property name="default_height">192</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="has_separator">False</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox2"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child internal-child="action_area"> - <widget class="GtkHButtonBox" id="dialog-action_area2"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - - <child> - <widget class="GtkButton" id="cancelbutton1"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="response_id">-6</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="okbutton1"> - <property name="visible">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> - <property name="can_focus">True</property> - <property name="label">gtk-ok</property> - <property name="use_stock">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="response_id">-5</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox2"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Active Connections</b></property> - <property name="use_underline">False</property> - <property name="use_markup">True</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox1"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="vbox3"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkScrolledWindow" id="scrolledwindow1"> - <property name="visible">True</property> - <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> - <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> - <property name="shadow_type">GTK_SHADOW_IN</property> - <property name="window_placement">GTK_CORNER_TOP_LEFT</property> - - <child> - <widget class="GtkTreeView" id="active_connection_treeview"> - <property name="visible">True</property> - <property name="headers_visible">True</property> - <property name="rules_hint">False</property> - <property name="reorderable">False</property> - <property name="enable_search">True</property> - </widget> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="instruction_label"> - <property name="visible">True</property> - <property name="label" translatable="yes">Click OK to close these connections and go offline</property> - <property name="use_underline">False</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_CENTER</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - </child> -</widget> - -</glade-interface> diff --git a/shell/e-component-registry.c b/shell/e-component-registry.c deleted file mode 100644 index 1b36d14512..0000000000 --- a/shell/e-component-registry.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-component-registry.h" - -#include <glib/gi18n.h> - -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-exception.h> - -#include <string.h> -#include <stdlib.h> - -struct _EComponentRegistryPrivate { - GSList *infos; - - guint init:1; -}; - -G_DEFINE_TYPE (EComponentRegistry, e_component_registry, G_TYPE_OBJECT) - -/* EComponentInfo handling. */ - -static EComponentInfo * -component_info_new (const gchar *id, - GNOME_Evolution_Component iface, - const gchar *alias, - const gchar *button_label, - const gchar *button_tooltips, - const gchar *menu_label, - const gchar *menu_accelerator, - const gchar *icon_name, - gint sort_order) -{ - EComponentInfo *info = g_new0 (EComponentInfo, 1); - - info->id = g_strdup (id); - info->iface = bonobo_object_dup_ref(iface, NULL); - info->alias = g_strdup (alias); - info->button_label = g_strdup (button_label); - info->button_tooltips = g_strdup (button_tooltips); - info->menu_label = g_strdup (menu_label); - info->menu_accelerator = g_strdup (menu_accelerator); - info->icon_name = g_strdup (icon_name); - info->sort_order = sort_order; - - return info; -} - -static void -component_info_free (EComponentInfo *info) -{ - g_free (info->id); - g_free (info->alias); - g_free (info->button_label); - g_free (info->button_tooltips); - g_free (info->menu_label); - g_free (info->menu_accelerator); - - if (info->iface != NULL) - bonobo_object_release_unref (info->iface, NULL); - - g_slist_foreach (info->uri_schemas, (GFunc) g_free, NULL); - g_slist_free (info->uri_schemas); - - g_free (info); -} - -static gint -component_info_compare_func (EComponentInfo *a, - EComponentInfo *b) -{ - if (a->sort_order != b->sort_order) - return a->sort_order - b->sort_order; - - return strcmp (a->button_label, b->button_label); -} - -/* Utility methods. */ - -static void -set_schemas (EComponentInfo *component_info, - Bonobo_ServerInfo *server_info) -{ - Bonobo_ActivationProperty *property = bonobo_server_info_prop_find (server_info, "evolution:uri_schemas"); - Bonobo_StringList *list; - gint i; - - if (property == NULL) - return; - - if (property->v._d != Bonobo_ACTIVATION_P_STRINGV) { - CORBA_free (property); - return; - } - - list = & property->v._u.value_stringv; - - for (i = 0; i < list->_length; i ++) - component_info->uri_schemas = g_slist_prepend (component_info->uri_schemas, g_strdup (list->_buffer [i])); - - CORBA_free (property); -} - -static void -query_components (EComponentRegistry *registry) -{ - Bonobo_ServerInfoList *info_list; - const gchar * const *language_names; - CORBA_Environment ev; - GSList *languages = NULL; - gchar *query; - gint i; - - if (registry->priv->init) - return; - - registry->priv->init = TRUE; - - CORBA_exception_init (&ev); - query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/Component:%s')", BASE_VERSION); - info_list = bonobo_activation_query (query, NULL, &ev); - g_free (query); - - if (BONOBO_EX (&ev)) { - gchar *ex_text = bonobo_exception_get_text (&ev); - g_warning ("Cannot query for components: %s\n", ex_text); - g_free (ex_text); - CORBA_exception_free (&ev); - return; - } - - language_names = g_get_language_names (); - while (*language_names != NULL) - languages = g_slist_append (languages, (gpointer)(*language_names++)); - - for (i = 0; i < info_list->_length; i++) { - const gchar *id; - const gchar *label; - const gchar *menu_label; - const gchar *menu_accelerator; - const gchar *alias; - const gchar *icon_name; - const gchar *sort_order_string; - const gchar *tooltips; - EComponentInfo *info; - gint sort_order; - GNOME_Evolution_Component iface; - - id = info_list->_buffer[i].iid; - iface = bonobo_activation_activate_from_id ((gchar *)id, 0, NULL, &ev); - if (BONOBO_EX (&ev) || iface == CORBA_OBJECT_NIL) { - gchar *ex_text = bonobo_exception_get_text (&ev); - - g_warning("Cannot activate '%s': %s\n", id, ex_text); - g_free(ex_text); - CORBA_exception_free(&ev); - CORBA_exception_init(&ev); - continue; - } - - label = bonobo_server_info_prop_lookup (& info_list->_buffer[i], "evolution:button_label", languages); - - tooltips = bonobo_server_info_prop_lookup (& info_list->_buffer[i], "evolution:button_tooltips", languages); - - menu_label = bonobo_server_info_prop_lookup (& info_list->_buffer[i], "evolution:menu_label", languages); - - menu_accelerator = bonobo_server_info_prop_lookup (& info_list->_buffer[i], "evolution:menu_accelerator", languages); - - alias = bonobo_server_info_prop_lookup (& info_list->_buffer[i], "evolution:component_alias", NULL); - - icon_name = bonobo_server_info_prop_lookup (& info_list->_buffer[i], "evolution:button_icon", NULL); - - sort_order_string = bonobo_server_info_prop_lookup (& info_list->_buffer[i], - "evolution:button_sort_order", NULL); - if (sort_order_string == NULL) - sort_order = 0; - else - sort_order = atoi (sort_order_string); - - info = component_info_new (id, iface, alias, label, tooltips, menu_label, - menu_accelerator, icon_name, sort_order); - set_schemas (info, & info_list->_buffer [i]); - - registry->priv->infos = g_slist_prepend (registry->priv->infos, info); - - bonobo_object_release_unref(iface, NULL); - } - g_slist_free(languages); - - CORBA_free (info_list); - CORBA_exception_free (&ev); - - registry->priv->infos = g_slist_sort (registry->priv->infos, - (GCompareFunc) component_info_compare_func); -} - -/* GObject methods. */ - -static void -impl_finalize (GObject *object) -{ - EComponentRegistry *component_registry; - EComponentRegistryPrivate *priv; - - component_registry = E_COMPONENT_REGISTRY (object); - priv = component_registry->priv; - - g_slist_foreach (priv->infos, (GFunc) component_info_free, NULL); - g_free (priv); - - (* G_OBJECT_CLASS (e_component_registry_parent_class)->finalize) (object); -} - -static void -e_component_registry_class_init (EComponentRegistryClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = impl_finalize; -} - -static void -e_component_registry_init (EComponentRegistry *registry) -{ - registry->priv = g_new0 (EComponentRegistryPrivate, 1); -} - -EComponentRegistry * -e_component_registry_new (void) -{ - return g_object_new (e_component_registry_get_type (), NULL); -} - -GSList * -e_component_registry_peek_list (EComponentRegistry *registry) -{ - g_return_val_if_fail (E_IS_COMPONENT_REGISTRY (registry), NULL); - - query_components(registry); - - return registry->priv->infos; -} - -EComponentInfo * -e_component_registry_peek_info (EComponentRegistry *registry, - enum _EComponentRegistryField field, - const gchar *key) -{ - GSList *p, *q; - - g_return_val_if_fail (E_IS_COMPONENT_REGISTRY (registry), NULL); - - query_components(registry); - - for (p = registry->priv->infos; p != NULL; p = p->next) { - EComponentInfo *info = p->data; - - switch (field) { - case ECR_FIELD_ID: - if (info->id && (strcmp (info->id, key) == 0)) - return info; - break; - case ECR_FIELD_ALIAS: - if (info->alias && (strcmp (info->alias, key) == 0)) - return info; - break; - case ECR_FIELD_SCHEMA: - for (q = info->uri_schemas; q != NULL; q = q->next) - if (strcmp((gchar *)q->data, key) == 0) - return info; - break; - } - } - - return NULL; -} - -GNOME_Evolution_Component -e_component_registry_activate (EComponentRegistry *registry, - const gchar *id, - CORBA_Environment *ev) -{ - EComponentInfo *info; - - g_return_val_if_fail (E_IS_COMPONENT_REGISTRY (registry), CORBA_OBJECT_NIL); - - info = e_component_registry_peek_info (registry, ECR_FIELD_ID, id); - if (info == NULL) { - g_warning ("%s - Unknown id \"%s\"", G_STRFUNC, id); - return CORBA_OBJECT_NIL; - } - - /* it isn't in the registry unless it is already activated */ - return bonobo_object_dup_ref (info->iface, NULL); -} diff --git a/shell/e-component-registry.h b/shell/e-component-registry.h deleted file mode 100644 index 373912db03..0000000000 --- a/shell/e-component-registry.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __E_COMPONENT_REGISTRY_H__ -#define __E_COMPONENT_REGISTRY_H__ - -#include "Evolution.h" - -#include <glib-object.h> -#include <gdk-pixbuf/gdk-pixbuf.h> - -G_BEGIN_DECLS - -#define E_TYPE_COMPONENT_REGISTRY (e_component_registry_get_type ()) -#define E_COMPONENT_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_COMPONENT_REGISTRY, EComponentRegistry)) -#define E_COMPONENT_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_COMPONENT_REGISTRY, EComponentRegistryClass)) -#define E_IS_COMPONENT_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_COMPONENT_REGISTRY)) -#define E_IS_COMPONENT_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_COMPONENT_REGISTRY)) - -typedef struct _EComponentRegistry EComponentRegistry; -typedef struct _EComponentRegistryPrivate EComponentRegistryPrivate; -typedef struct _EComponentRegistryClass EComponentRegistryClass; - -struct _EComponentRegistry { - GObject parent; - - EComponentRegistryPrivate *priv; -}; - -struct _EComponentRegistryClass { - GObjectClass parent_class; -}; - -enum _EComponentRegistryField { - ECR_FIELD_ID, - ECR_FIELD_ALIAS, - ECR_FIELD_SCHEMA -}; - -struct _EComponentInfo { - gchar *id; - - gchar *alias; - - /* NULL if not activated. */ - GNOME_Evolution_Component iface; - - gchar *button_label; - gchar *button_tooltips; - gchar *menu_label; - gchar *menu_accelerator; - gchar *icon_name; - - gint sort_order; - - /* List of URI schemas that this component supports. */ - GSList *uri_schemas; /* <char *> */ -}; -typedef struct _EComponentInfo EComponentInfo; - -GType e_component_registry_get_type (void); -EComponentRegistry *e_component_registry_new (void); - -GSList *e_component_registry_peek_list (EComponentRegistry *registry); -EComponentInfo *e_component_registry_peek_info (EComponentRegistry *registry, - enum _EComponentRegistryField type, - const gchar *key); - -GNOME_Evolution_Component e_component_registry_activate (EComponentRegistry *registry, - const gchar *id, - CORBA_Environment *ev); - -G_END_DECLS - -#endif /* __E_COMPONENT_REGISTRY_H__ */ diff --git a/shell/e-component-view.c b/shell/e-component-view.c deleted file mode 100644 index 58ea3f9a89..0000000000 --- a/shell/e-component-view.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Helper class for evolution components to setup a view - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib.h> - -#include "e-component-view.h" - -#include "bonobo/bonobo-control.h" - -static BonoboObjectClass *parent_class = NULL; - -static void -impl_ComponentView_getControls(PortableServer_Servant servant, - Bonobo_Control *side_control, - Bonobo_Control *view_control, - Bonobo_Control *statusbar_control, - CORBA_Environment *ev) -{ - EComponentView *ecv = (EComponentView *)bonobo_object_from_servant(servant); - - *side_control = CORBA_Object_duplicate (BONOBO_OBJREF (ecv->side_control), ev); - *view_control = CORBA_Object_duplicate (BONOBO_OBJREF (ecv->view_control), ev); - *statusbar_control = CORBA_Object_duplicate (BONOBO_OBJREF (ecv->statusbar_control), ev); -} - -/* GObject methods. */ - -static void -impl_dispose (GObject *object) -{ - EComponentView *ecv = (EComponentView *)object; - - ecv->side_control = NULL; - ecv->view_control = NULL; - ecv->statusbar_control = NULL; - - ((GObjectClass *)parent_class)->dispose(object); -} - -static void -impl_finalise (GObject *object) -{ - EComponentView *ecv = (EComponentView *)object; - - g_free(ecv->id); - - ((GObjectClass *)parent_class)->finalize(object); -} - -static void -e_component_view_class_init (EComponentViewClass *klass) -{ - GObjectClass *object_class; - POA_GNOME_Evolution_ComponentView__epv *epv; - - parent_class = g_type_class_ref(bonobo_object_get_type()); - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalise; - - epv = & klass->epv; - epv->getControls = impl_ComponentView_getControls; -} - -static void -e_component_view_init (EComponentView *shell) -{ -} - -EComponentView *e_component_view_new(GNOME_Evolution_ShellView parent, const gchar *id, GtkWidget *side, GtkWidget *view, GtkWidget *statusbar) -{ - EComponentView *new = g_object_new (e_component_view_get_type (), NULL); - CORBA_Environment ev = { NULL }; - - new->id = g_strdup(id); - new->shell_view = CORBA_Object_duplicate(parent, &ev); - CORBA_exception_free(&ev); - - /* FIXME: hook onto destroys */ - new->side_control = bonobo_control_new(side); - new->view_control = bonobo_control_new(view); - new->statusbar_control = bonobo_control_new(statusbar); - - return new; -} - -EComponentView *e_component_view_new_controls(GNOME_Evolution_ShellView parent, const gchar *id, BonoboControl *side, BonoboControl *view, BonoboControl *statusbar) -{ - EComponentView *new = g_object_new (e_component_view_get_type (), NULL); - CORBA_Environment ev = { NULL }; - - new->id = g_strdup(id); - new->shell_view = CORBA_Object_duplicate(parent, &ev); - CORBA_exception_free(&ev); - - /* FIXME: hook onto destroys */ - new->side_control = side; - new->view_control = view; - new->statusbar_control = statusbar; - - return new; -} - -void -e_component_view_set_title(EComponentView *ecv, const gchar *title) -{ - CORBA_Environment ev = { NULL }; - - /* save roundtrips, check title is the same */ - GNOME_Evolution_ShellView_setTitle(ecv->shell_view, ecv->id, title, &ev); - CORBA_exception_free(&ev); -} - -void -e_component_view_set_button_icon (EComponentView *ecv, const gchar *iconName) -{ - CORBA_Environment ev = { NULL }; - - /* save roundtrips, check title is the same */ - GNOME_Evolution_ShellView_setButtonIcon(ecv->shell_view, ecv->id, iconName, &ev); - CORBA_exception_free(&ev); -} - -BONOBO_TYPE_FUNC_FULL (EComponentView, GNOME_Evolution_ComponentView, bonobo_object_get_type(), e_component_view) - diff --git a/shell/e-component-view.h b/shell/e-component-view.h deleted file mode 100644 index ca40e3c381..0000000000 --- a/shell/e-component-view.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_COMPONENT_VIEW_H_ -#define _E_COMPONENT_VIEW_H_ - -#include <gtk/gtk.h> -#include <bonobo/bonobo-object.h> - -G_BEGIN_DECLS - -typedef struct _EComponentView EComponentView; -typedef struct _EComponentViewPrivate EComponentViewPrivate; -typedef struct _EComponentViewClass EComponentViewClass; - -#include "Evolution.h" - -#define E_TYPE_COMPONENT_VIEW (e_component_view_get_type ()) -#define E_COMPONENT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_COMPONENT_VIEW, EComponentView)) -#define E_COMPONENT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_COMPONENT_VIEW, EComponentViewClass)) -#define E_IS_COMPONENT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_COMPONENT_VIEW)) -#define E_IS_COMPONENT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_COMPONENT_VIEW)) - -struct _EComponentView { - BonoboObject parent; - - EComponentViewPrivate *priv; - - gchar *id; - GNOME_Evolution_ShellView shell_view; - - struct _BonoboControl *side_control; - struct _BonoboControl *view_control; - struct _BonoboControl *statusbar_control; -}; - -struct _EComponentViewClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_ComponentView__epv epv; -}; - -GType e_component_view_get_type(void); -EComponentView *e_component_view_new(GNOME_Evolution_ShellView shell_view, const gchar *id, GtkWidget *side, GtkWidget *view, GtkWidget *status); -EComponentView *e_component_view_new_controls(GNOME_Evolution_ShellView parent, const gchar *id, struct _BonoboControl *side, struct _BonoboControl *view, struct _BonoboControl *statusbar); - -void e_component_view_set_title(EComponentView *ecv, const gchar *title); -void e_component_view_set_button_icon (EComponentView *ecv, const gchar *iconName); - -G_END_DECLS - -#endif /* _E_COMPONENT_VIEW_H_ */ - diff --git a/shell/e-corba-config-page.c b/shell/e-corba-config-page.c deleted file mode 100644 index 02f8a631d3..0000000000 --- a/shell/e-corba-config-page.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-corba-config-page.h" - -#include "Evolution.h" - -#include <string.h> - -#include <bonobo/bonobo-widget.h> -#include <bonobo/bonobo-exception.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-listener.h> - -struct _ECorbaConfigPagePrivate { - GNOME_Evolution_ConfigControl config_control_interface; -}; - -G_DEFINE_TYPE (ECorbaConfigPage, e_corba_config_page, E_TYPE_CONFIG_PAGE) - -/* GObject methods. */ - -static void -impl_dispose (GObject *object) -{ - ECorbaConfigPage *corba_config_page; - ECorbaConfigPagePrivate *priv; - CORBA_Environment ev; - - corba_config_page = E_CORBA_CONFIG_PAGE (object); - priv = corba_config_page->priv; - - CORBA_exception_init (&ev); - - if (priv->config_control_interface != CORBA_OBJECT_NIL) { - bonobo_object_release_unref (priv->config_control_interface, &ev); - priv->config_control_interface = CORBA_OBJECT_NIL; - } - - CORBA_exception_free (&ev); - - (* G_OBJECT_CLASS (e_corba_config_page_parent_class)->dispose) (object); -} - -static void -impl_finalize (GObject *object) -{ - ECorbaConfigPage *corba_config_page; - ECorbaConfigPagePrivate *priv; - - corba_config_page = E_CORBA_CONFIG_PAGE (object); - priv = corba_config_page->priv; - - g_free (priv); - - (* G_OBJECT_CLASS (e_corba_config_page_parent_class)->finalize) (object); -} - -/* GTK+ ctors. */ - -static void -e_corba_config_page_class_init (ECorbaConfigPageClass *class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; -} - -static void -e_corba_config_page_init (ECorbaConfigPage *corba_config_page) -{ - ECorbaConfigPagePrivate *priv; - - priv = g_new (ECorbaConfigPagePrivate, 1); - priv->config_control_interface = CORBA_OBJECT_NIL; - - corba_config_page->priv = priv; -} - - -gboolean -e_corba_config_page_construct (ECorbaConfigPage *corba_config_page, - GNOME_Evolution_ConfigControl corba_object) -{ - Bonobo_Control control; - GtkWidget *control_widget; - CORBA_Environment ev; - - g_return_val_if_fail (E_IS_CORBA_CONFIG_PAGE (corba_config_page), FALSE); - g_return_val_if_fail (corba_object != CORBA_OBJECT_NIL, FALSE); - - CORBA_exception_init (&ev); - - control = GNOME_Evolution_ConfigControl__get_control (corba_object, &ev); - if (BONOBO_EX (&ev)) { - g_warning ("Can't get control from ::ConfigControl -- %s", BONOBO_EX_REPOID (&ev)); - CORBA_exception_init (&ev); - return FALSE; - } - - control_widget = bonobo_widget_new_control_from_objref (control, CORBA_OBJECT_NIL); - gtk_widget_show (control_widget); - gtk_container_add (GTK_CONTAINER (corba_config_page), control_widget); - - /* Notice we *don't* unref the corba_object here as - bonobo_widget_new_control_from_objref() effectively takes ownership - for the object that we get from ::__get_control. */ - - CORBA_exception_free (&ev); - - return TRUE; -} - -GtkWidget * -e_corba_config_page_new_from_objref (GNOME_Evolution_ConfigControl corba_object) -{ - ECorbaConfigPage *corba_config_page; - - g_return_val_if_fail (corba_object != CORBA_OBJECT_NIL, NULL); - g_return_val_if_fail (corba_object != CORBA_OBJECT_NIL, NULL); - - corba_config_page = g_object_new (e_corba_config_page_get_type (), NULL); - if (! e_corba_config_page_construct (corba_config_page, corba_object)) { - gtk_widget_destroy (GTK_WIDGET (corba_config_page)); - return NULL; - } - - return GTK_WIDGET (corba_config_page); -} diff --git a/shell/e-corba-config-page.h b/shell/e-corba-config-page.h deleted file mode 100644 index a09b86d0fe..0000000000 --- a/shell/e-corba-config-page.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_CORBA_CONFIG_PAGE_H_ -#define _E_CORBA_CONFIG_PAGE_H_ - -#include "e-config-page.h" - -#include "Evolution.h" - -#include <bonobo/bonobo-object.h> - -G_BEGIN_DECLS - -#define E_TYPE_CORBA_CONFIG_PAGE (e_corba_config_page_get_type ()) -#define E_CORBA_CONFIG_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CORBA_CONFIG_PAGE, ECorbaConfigPage)) -#define E_CORBA_CONFIG_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CORBA_CONFIG_PAGE, ECorbaConfigPageClass)) -#define E_IS_CORBA_CONFIG_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CORBA_CONFIG_PAGE)) -#define E_IS_CORBA_CONFIG_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_CORBA_CONFIG_PAGE)) - - -typedef struct _ECorbaConfigPage ECorbaConfigPage; -typedef struct _ECorbaConfigPagePrivate ECorbaConfigPagePrivate; -typedef struct _ECorbaConfigPageClass ECorbaConfigPageClass; - -struct _ECorbaConfigPage { - EConfigPage parent; - - ECorbaConfigPagePrivate *priv; -}; - -struct _ECorbaConfigPageClass { - EConfigPageClass parent_class; -}; - - -GType e_corba_config_page_get_type (void); -GtkWidget *e_corba_config_page_new_from_objref (GNOME_Evolution_ConfigControl objref); -gboolean e_corba_config_page_construct (ECorbaConfigPage *corba_config_page, - GNOME_Evolution_ConfigControl objref); - -G_END_DECLS - -#endif /* _E_CORBA_CONFIG_PAGE_H_ */ diff --git a/shell/e-shell-backend.c b/shell/e-shell-backend.c new file mode 100644 index 0000000000..c996d8ab01 --- /dev/null +++ b/shell/e-shell-backend.c @@ -0,0 +1,403 @@ +/* + * e-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-backend.h" + +#include <errno.h> +#include <glib/gi18n.h> + +#include "e-util/e-util.h" + +#include "e-shell.h" +#include "e-shell-view.h" + +#define E_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_BACKEND, EShellBackendPrivate)) + +struct _EShellBackendPrivate { + + gpointer shell; /* weak pointer */ + + /* We keep a reference to corresponding EShellView subclass + * since it keeps a reference back to us. This ensures the + * subclass is not finalized before we are, otherwise it + * would leak its EShellBackend reference. */ + EShellViewClass *shell_view_class; + + gchar *config_dir; + gchar *data_dir; + + guint started : 1; +}; + +enum { + PROP_0, + PROP_SHELL +}; + +enum { + ACTIVITY_ADDED, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +shell_backend_set_shell (EShellBackend *shell_backend, + EShell *shell) +{ + g_return_if_fail (shell_backend->priv->shell == NULL); + + shell_backend->priv->shell = shell; + + g_object_add_weak_pointer ( + G_OBJECT (shell_backend), + &shell_backend->priv->shell); +} + +static void +shell_backend_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL: + shell_backend_set_shell ( + E_SHELL_BACKEND (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_backend_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL: + g_value_set_object ( + value, e_shell_backend_get_shell ( + E_SHELL_BACKEND (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_backend_dispose (GObject *object) +{ + EShellBackendPrivate *priv; + + priv = E_SHELL_BACKEND_GET_PRIVATE (object); + + if (priv->shell != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell), &priv->shell); + priv->shell = NULL; + } + + if (priv->shell_view_class != NULL) { + g_type_class_unref (priv->shell_view_class); + priv->shell_view_class = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_backend_finalize (GObject *object) +{ + EShellBackendPrivate *priv; + + priv = E_SHELL_BACKEND_GET_PRIVATE (object); + + g_free (priv->data_dir); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_backend_class_init (EShellBackendClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_backend_set_property; + object_class->get_property = shell_backend_get_property; + object_class->dispose = shell_backend_dispose; + object_class->finalize = shell_backend_finalize; + + /** + * EShellBackend:shell + * + * The #EShell singleton. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL, + g_param_spec_object ( + "shell", + _("Shell"), + _("The EShell singleton"), + E_TYPE_SHELL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + /** + * EShellBackend::activity-added + * @shell_backend: the #EShellBackend that emitted the signal + * @activity: an #EActivity + * + * Broadcasts a newly added activity. + **/ + signals[ACTIVITY_ADDED] = g_signal_new ( + "activity-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACTIVITY); +} + +static void +shell_backend_init (EShellBackend *shell_backend, + EShellBackendClass *class) +{ + EShellViewClass *shell_view_class; + gchar *dirname; + + shell_backend->priv = E_SHELL_BACKEND_GET_PRIVATE (shell_backend); + + /* Install a reference to ourselves in the corresponding + * EShellViewClass structure, */ + shell_view_class = g_type_class_ref (class->shell_view_type); + shell_view_class->shell_backend = g_object_ref (shell_backend); + shell_backend->priv->shell_view_class = shell_view_class; + + /* Determine the user data directory for this backend. */ + shell_backend->priv->data_dir = g_build_filename ( + e_get_user_data_dir (), class->name, NULL); + + /* Determine the user configuration directory for this backend. */ + shell_backend->priv->config_dir = g_build_filename ( + shell_backend->priv->data_dir, "config", NULL); + + /* Create the user configuration directory for this backend, + * which should also create the user data directory. */ + dirname = shell_backend->priv->config_dir; + if (g_mkdir_with_parents (dirname, 0777) != 0) + g_critical ( + "Cannot create directory %s: %s", + dirname, g_strerror (errno)); +} + +GType +e_shell_backend_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_backend_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EShellBackend", &type_info, 0); + } + + return type; +} + +/** + * e_shell_backend_compare: + * @shell_backend_a: an #EShellBackend + * @shell_backend_b: an #EShellBackend + * + * Using the <structfield>sort_order</structfield> field from both backends' + * #EShellBackendClass, compares @shell_backend_a with @shell_mobule_b and + * returns -1, 0 or +1 if @shell_backend_a is found to be less than, equal + * to or greater than @shell_backend_b, respectively. + * + * Returns: -1, 0 or +1, for a less than, equal to or greater than result + **/ +gint +e_shell_backend_compare (EShellBackend *shell_backend_a, + EShellBackend *shell_backend_b) +{ + gint a = E_SHELL_BACKEND_GET_CLASS (shell_backend_a)->sort_order; + gint b = E_SHELL_BACKEND_GET_CLASS (shell_backend_b)->sort_order; + + return (a < b) ? -1 : (a > b); +} + +/** + * e_shell_backend_get_config_dir: + * @shell_backend: an #EShellBackend + * + * Returns the absolute path to the configuration directory for + * @shell_backend. The string is owned by @shell_backend and should + * not be modified or freed. + * + * Returns: the backend's configuration directory + **/ +const gchar * +e_shell_backend_get_config_dir (EShellBackend *shell_backend) +{ + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), NULL); + g_return_val_if_fail (shell_backend->priv->config_dir != NULL, NULL); + + return shell_backend->priv->config_dir; +} + +/** + * e_shell_backend_get_data_dir: + * @shell_backend: an #EShellBackend + * + * Returns the absolute path to the data directory for @shell_backend. + * The string is owned by @shell_backend and should not be modified or + * freed. + * + * Returns: the backend's data directory + **/ +const gchar * +e_shell_backend_get_data_dir (EShellBackend *shell_backend) +{ + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), NULL); + g_return_val_if_fail (shell_backend->priv->data_dir != NULL, NULL); + + return shell_backend->priv->data_dir; +} + +/** + * e_shell_backend_get_shell: + * @shell_backend: an #EShellBackend + * + * Returns the #EShell singleton. + * + * Returns: the #EShell + **/ +EShell * +e_shell_backend_get_shell (EShellBackend *shell_backend) +{ + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), NULL); + + return E_SHELL (shell_backend->priv->shell); +} + +/** + * e_shell_backend_add_activity: + * @shell_backend: an #EShellBackend + * @activity: an #EActivity + * + * Emits an #EShellBackend::activity-added signal. + **/ +void +e_shell_backend_add_activity (EShellBackend *shell_backend, + EActivity *activity) +{ + g_return_if_fail (E_IS_SHELL_BACKEND (shell_backend)); + g_return_if_fail (E_IS_ACTIVITY (activity)); + + g_signal_emit (shell_backend, signals[ACTIVITY_ADDED], 0, activity); +} + +/** + * e_shell_backend_start: + * @shell_backend: an #EShellBackend + * + * Tells the @shell_backend to begin loading data or running background + * tasks which may consume significant resources. This gets called in + * reponse to the user switching to the corresponding #EShellView for + * the first time. The function is idempotent for each @shell_backend. + **/ +void +e_shell_backend_start (EShellBackend *shell_backend) +{ + EShellBackendClass *class; + + g_return_if_fail (E_IS_SHELL_BACKEND (shell_backend)); + + if (shell_backend->priv->started) + return; + + class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + + if (class->start != NULL) + class->start (shell_backend); + + shell_backend->priv->started = TRUE; +} + +/** + * e_shell_migrate: + * @shell_backend: an #EShellBackend + * @major: major part of version to migrate from + * @minor: minor part of version to migrate from + * @micro: micro part of version to migrate from + * @error: return location for a #GError, or %NULL + * + * Attempts to migrate data and settings from version %major.%minor.%micro. + * Returns %TRUE if the migration was successful or if no action was + * necessary. Returns %FALSE and sets %error if the migration failed. + * + * Returns: %TRUE if successful, %FALSE otherwise + **/ +gboolean +e_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + EShellBackendClass *class; + + g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), TRUE); + + class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + + if (class->migrate == NULL) + return TRUE; + + return class->migrate (shell_backend, major, minor, micro, error); +} diff --git a/shell/e-shell-backend.h b/shell/e-shell-backend.h new file mode 100644 index 0000000000..6dbbb33ea1 --- /dev/null +++ b/shell/e-shell-backend.h @@ -0,0 +1,139 @@ +/* + * e-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-shell-backend + * @short_description: dynamically loaded capabilities + * @include: shell/e-shell-backend.h + **/ + +#ifndef E_SHELL_BACKEND_H +#define E_SHELL_BACKEND_H + +#include <shell/e-shell-common.h> +#include <misc/e-activity.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_BACKEND \ + (e_shell_backend_get_type ()) +#define E_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_BACKEND, EShellBackend)) +#define E_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_BACKEND, EShellBackendClass)) +#define E_IS_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_BACKEND)) +#define E_IS_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SHELL_BACKEND)) +#define E_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_BACKEND, EShellBackendClass)) + +G_BEGIN_DECLS + +/* Avoid including <e-shell.h>, because it includes us! */ +struct _EShell; + +typedef struct _EShellBackend EShellBackend; +typedef struct _EShellBackendClass EShellBackendClass; +typedef struct _EShellBackendPrivate EShellBackendPrivate; + +/** + * EShellBackend: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EShellBackend { + GObject parent; + EShellBackendPrivate *priv; +}; + +/** + * EShellBackendClass: + * @parent_class: The parent class structure. + * @name: The name of the backend. Also becomes the name of + * the corresponding #EShellView subclass that the + * backend will register. + * @aliases: Colon-separated list of aliases that can be used + * when referring to a backend by name. + * @schemes: Colon-separated list of URI schemes. The #EShell + * will forward command-line URIs to the appropriate + * backend based on this list. + * @sort_order: Used to determine the order of backends listed in + * the main menu and in the switcher. See + * e_shell_backend_compare(). + * @shell_view_type: #GType for the corresponding #EShellView subclass. + * @start: Method for notifying the backend to begin loading + * data and running background tasks. This is called + * just before the first instantiation of the + * corresponding #EShellView subclass. It allows the + * backend to delay initialization steps that consume + * significant resources until they are actually needed. + * @migrate: Method for notifying the backend to migrate data and + * settings from the given version. Returns %TRUE if the + * migration was successful or if no action was necessary. + * Returns %FALSE and sets a #GError if the migration + * failed. + * + * #EShellBackendClass contains a number of important settings for subclasses. + **/ +struct _EShellBackendClass { + GObjectClass parent_class; + + GType shell_view_type; + + const gchar *name; + const gchar *aliases; + const gchar *schemes; + gint sort_order; + + /* Methods */ + void (*start) (EShellBackend *shell_backend); + gboolean (*migrate) (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); +}; + +GType e_shell_backend_get_type (void); +gint e_shell_backend_compare (EShellBackend *shell_backend_a, + EShellBackend *shell_backend_b); +const gchar * e_shell_backend_get_config_dir (EShellBackend *shell_backend); +const gchar * e_shell_backend_get_data_dir (EShellBackend *shell_backend); +const gchar * e_shell_backend_get_filename (EShellBackend *shell_backend); +struct _EShell *e_shell_backend_get_shell (EShellBackend *shell_backend); +void e_shell_backend_add_activity (EShellBackend *shell_backend, + EActivity *activity); +void e_shell_backend_start (EShellBackend *shell_backend); +gboolean e_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error); + +G_END_DECLS + +#endif /* E_SHELL_BACKEND_H */ diff --git a/shell/importer/intelligent.h b/shell/e-shell-common.h index 5f5f7187f2..7ff35091aa 100644 --- a/shell/importer/intelligent.h +++ b/shell/e-shell-common.h @@ -1,4 +1,6 @@ /* + * e-shell-common.h + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -13,16 +15,19 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Kjartan Maraas <kmaraas@gnome.org> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef __INTELLIGENT_H__ -#define __INTELLIGENT_H__ - -void intelligent_importer_init (void); +#ifndef E_SHELL_COMMON_H +#define E_SHELL_COMMON_H +#ifdef HAVE_CONFIG_H +#include <config.h> #endif + +#include <gio/gio.h> +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> + +#endif /* E_SHELL_COMMON_H */ diff --git a/shell/e-shell-constants.h b/shell/e-shell-constants.h deleted file mode 100644 index 13beed8aec..0000000000 --- a/shell/e-shell-constants.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef E_SHELL_CONSTANTS_H -#define E_SHELL_CONSTANTS_H - -#define E_SHELL_URI_PREFIX "evolution:" -#define E_SHELL_URI_PREFIX_LEN 10 - -#define E_SHELL_DEFAULTURI_PREFIX "default:" -#define E_SHELL_DEFAULTURI_PREFIX_LEN 8 - -#define E_SHELL_MINI_ICON_SUFFIX "-mini" -#define E_SHELL_MINI_ICON_SUFFIX_LEN 5 - -#define E_SHELL_ICON_SIZE 48 -#define E_SHELL_MINI_ICON_SIZE 16 - -#define E_PATH_SEPARATOR '/' -#define E_PATH_SEPARATOR_S "/" - -#define E_LOCAL_STORAGE_NAME "local" -#define E_SUMMARY_STORAGE_NAME "summary" - -#define E_SUMMARY_URI "evolution:/summary" -#define E_LOCAL_INBOX_URI "evolution:/local/Inbox" -#define E_LOCAL_CONTACTS_URI "evolution:/local/Contacts" -#define E_LOCAL_CALENDAR_URI "evolution:/local/Calendar" -#define E_LOCAL_TASKS_URI "evolution:/local/Tasks" - -#endif diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c new file mode 100644 index 0000000000..2fc9569bd2 --- /dev/null +++ b/shell/e-shell-content.c @@ -0,0 +1,1559 @@ +/* + * e-shell-content.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-content.h" + +#include <glib/gi18n.h> + +#include "e-util/e-binding.h" +#include "e-util/e-util.h" +#include "filter/rule-editor.h" +#include "widgets/misc/e-action-combo-box.h" +#include "widgets/misc/e-hinted-entry.h" + +#include "e-shell-backend.h" +#include "e-shell-view.h" +#include "e-shell-window-actions.h" + +#define E_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_CONTENT, EShellContentPrivate)) + +#define STATE_KEY_SEARCH_FILTER "SearchFilter" +#define STATE_KEY_SEARCH_SCOPE "SearchScope" +#define STATE_KEY_SEARCH_TEXT "SearchText" + +struct _EShellContentPrivate { + + gpointer shell_view; /* weak pointer */ + + RuleContext *search_context; + FilterRule *search_rule; + gchar *system_filename; + gchar *user_filename; + + /* Container for the following widgets */ + GtkWidget *search_bar; + + /* Search bar widgets */ + GtkWidget *filter_label; + GtkWidget *filter_combo_box; + GtkWidget *search_label; + GtkWidget *search_entry; + GtkWidget *scope_label; + GtkWidget *scope_combo_box; +}; + +enum { + PROP_0, + PROP_FILTER_ACTION, + PROP_FILTER_VALUE, + PROP_FILTER_VISIBLE, + PROP_SEARCH_CONTEXT, + PROP_SEARCH_HINT, + PROP_SEARCH_RULE, + PROP_SEARCH_TEXT, + PROP_SEARCH_VISIBLE, + PROP_SCOPE_ACTION, + PROP_SCOPE_VALUE, + PROP_SCOPE_VISIBLE, + PROP_SHELL_VIEW +}; + +static gpointer parent_class; + +static void +shell_content_dialog_rule_changed (GtkWidget *dialog, + FilterRule *rule) +{ + gboolean sensitive; + + sensitive = (rule != NULL) && (rule->parts != NULL); + + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive); + gtk_dialog_set_response_sensitive ( + GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, sensitive); +} + +static void +action_search_execute_cb (GtkAction *action, + EShellContent *shell_content) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkWidget *widget; + const gchar *search_text; + + /* EShellView subclasses are responsible for actually + * executing the search. This is all cosmetic stuff. */ + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + if (!e_shell_view_is_active (shell_view)) + return; + + widget = shell_content->priv->search_entry; + + search_text = e_shell_content_get_search_text (shell_content); + + if (search_text != NULL && *search_text != '\0') { + GtkStyle *style; + const GdkColor *color; + + style = gtk_widget_get_style (widget); + color = &style->base[GTK_STATE_SELECTED]; + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, color); + + style = gtk_widget_get_style (widget); + color = &style->text[GTK_STATE_SELECTED]; + gtk_widget_modify_text (widget, GTK_STATE_NORMAL, color); + } else { + /* Text color will be updated when we move the focus. */ + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, NULL); + } + + action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); + gtk_action_set_sensitive (action, TRUE); + + action = E_SHELL_WINDOW_ACTION_SEARCH_SAVE (shell_window); + gtk_action_set_sensitive (action, TRUE); + + /* Direct the focus away from the search entry, so that a + * focus-in event is required before the text can be changed. + * This will reset the entry to the appropriate visual state. */ + widget = gtk_bin_get_child (GTK_BIN (shell_content)); + if (GTK_IS_PANED (widget)) + widget = gtk_paned_get_child1 (GTK_PANED (widget)); + gtk_widget_grab_focus (widget); +} + +static void +shell_content_entry_activated_cb (EShellContent *shell_content, + GtkWidget *entry) +{ + EShellWindow *shell_window; + EShellView *shell_view; + GtkAction *action; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + /* Verify the shell view is active before proceeding. */ + if (!e_shell_view_is_active (shell_view)) + return; + + action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window); + gtk_action_activate (action); +} + +static void +shell_content_entry_icon_press_cb (EShellContent *shell_content, + GtkEntryIconPosition icon_pos, + GdkEvent *event) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkAction *action; + + /* Show the search options menu when the icon is pressed. */ + + if (icon_pos != GTK_ENTRY_ICON_PRIMARY) + return; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); + gtk_action_activate (action); +} + +static void +shell_content_entry_icon_release_cb (EShellContent *shell_content, + GtkEntryIconPosition icon_pos, + GdkEvent *event) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkAction *action; + + /* Clear the search when the icon is pressed and released. */ + + if (icon_pos != GTK_ENTRY_ICON_SECONDARY) + return; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); + gtk_action_activate (action); +} + +static gboolean +shell_content_entry_key_press_cb (EShellContent *shell_content, + GdkEventKey *key_event, + GtkWidget *entry) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkAction *action; + guint mask; + + mask = gtk_accelerator_get_default_mod_mask (); + if ((key_event->state & mask) != GDK_MOD1_MASK) + return FALSE; + + if (key_event->keyval != GDK_Down) + return FALSE; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + + action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); + gtk_action_activate (action); + + return TRUE; +} + +static void +shell_content_init_search_context (EShellContent *shell_content) +{ + EShellContentClass *shell_content_class; + EShellView *shell_view; + EShellViewClass *shell_view_class; + EShellBackend *shell_backend; + RuleContext *context; + FilterRule *rule; + FilterPart *part; + gchar *system_filename; + gchar *user_filename; + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + g_return_if_fail (shell_view_class->search_rules != NULL); + + shell_content_class = E_SHELL_CONTENT_GET_CLASS (shell_content); + g_return_if_fail (shell_content_class->new_search_context != NULL); + + /* The basename for built-in searches is specified in the + * shell view class. All built-in search rules live in the + * same directory. */ + system_filename = g_build_filename ( + EVOLUTION_RULEDIR, shell_view_class->search_rules, NULL); + + /* The filename for custom saved searches is always of + * the form "$(shell_backend_data_dir)/searches.xml". */ + user_filename = g_build_filename ( + e_shell_backend_get_data_dir (shell_backend), + "searches.xml", NULL); + + context = shell_content_class->new_search_context (); + rule_context_add_part_set ( + context, "partset", FILTER_TYPE_PART, + rule_context_add_part, rule_context_next_part); + rule_context_add_rule_set ( + context, "ruleset", FILTER_TYPE_RULE, + rule_context_add_rule, rule_context_next_rule); + rule_context_load (context, system_filename, user_filename); + + /* XXX Not sure why this is necessary. */ + g_object_set_data_full ( + G_OBJECT (context), "system", + g_strdup (system_filename), g_free); + g_object_set_data_full ( + G_OBJECT (context), "user", + g_strdup (user_filename), g_free); + + rule = filter_rule_new (); + part = rule_context_next_part (context, NULL); + if (part == NULL) + g_warning ( + "Could not load %s search: no parts", + e_shell_view_get_name (shell_view)); + else + filter_rule_add_part (rule, filter_part_clone (part)); + + shell_content->priv->search_context = context; + shell_content->priv->system_filename = system_filename; + shell_content->priv->user_filename = user_filename; +} + +static void +shell_content_set_shell_view (EShellContent *shell_content, + EShellView *shell_view) +{ + g_return_if_fail (shell_content->priv->shell_view == NULL); + + shell_content->priv->shell_view = shell_view; + + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &shell_content->priv->shell_view); +} + +static void +shell_content_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILTER_ACTION: + e_shell_content_set_filter_action ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_FILTER_VALUE: + e_shell_content_set_filter_value ( + E_SHELL_CONTENT (object), + g_value_get_int (value)); + return; + + case PROP_FILTER_VISIBLE: + e_shell_content_set_filter_visible ( + E_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SEARCH_HINT: + e_shell_content_set_search_hint ( + E_SHELL_CONTENT (object), + g_value_get_string (value)); + return; + + case PROP_SEARCH_RULE: + e_shell_content_set_search_rule ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_SEARCH_TEXT: + e_shell_content_set_search_text ( + E_SHELL_CONTENT (object), + g_value_get_string (value)); + return; + + case PROP_SEARCH_VISIBLE: + e_shell_content_set_search_visible ( + E_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SCOPE_ACTION: + e_shell_content_set_scope_action ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + + case PROP_SCOPE_VALUE: + e_shell_content_set_scope_value ( + E_SHELL_CONTENT (object), + g_value_get_int (value)); + return; + + case PROP_SCOPE_VISIBLE: + e_shell_content_set_scope_visible ( + E_SHELL_CONTENT (object), + g_value_get_boolean (value)); + return; + + case PROP_SHELL_VIEW: + shell_content_set_shell_view ( + E_SHELL_CONTENT (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_content_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILTER_ACTION: + g_value_set_object ( + value, e_shell_content_get_filter_action ( + E_SHELL_CONTENT (object))); + return; + + case PROP_FILTER_VALUE: + g_value_set_int ( + value, e_shell_content_get_filter_value ( + E_SHELL_CONTENT (object))); + return; + + case PROP_FILTER_VISIBLE: + g_value_set_boolean ( + value, e_shell_content_get_filter_visible ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_CONTEXT: + g_value_set_object ( + value, e_shell_content_get_search_context ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_HINT: + g_value_set_string ( + value, e_shell_content_get_search_hint ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_RULE: + g_value_set_object ( + value, e_shell_content_get_search_rule ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_TEXT: + g_value_set_string ( + value, e_shell_content_get_search_text ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SEARCH_VISIBLE: + g_value_set_boolean ( + value, e_shell_content_get_search_visible ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SCOPE_ACTION: + g_value_set_object ( + value, e_shell_content_get_scope_action ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SCOPE_VALUE: + g_value_set_int ( + value, e_shell_content_get_scope_value ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SCOPE_VISIBLE: + g_value_set_boolean ( + value, e_shell_content_get_scope_visible ( + E_SHELL_CONTENT (object))); + return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_shell_content_get_shell_view ( + E_SHELL_CONTENT (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_content_dispose (GObject *object) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), &priv->shell_view); + priv->shell_view = NULL; + } + + if (priv->filter_label != NULL) { + g_object_unref (priv->filter_label); + priv->filter_label = NULL; + } + + if (priv->filter_combo_box != NULL) { + g_object_unref (priv->filter_combo_box); + priv->filter_combo_box = NULL; + } + + if (priv->search_context != NULL) { + g_object_unref (priv->search_context); + priv->search_context = NULL; + } + + if (priv->search_label != NULL) { + g_object_unref (priv->search_label); + priv->search_label = NULL; + } + + if (priv->search_entry != NULL) { + g_object_unref (priv->search_entry); + priv->search_entry = NULL; + } + + if (priv->scope_label != NULL) { + g_object_unref (priv->scope_label); + priv->scope_label = NULL; + } + + if (priv->scope_combo_box != NULL) { + g_object_unref (priv->scope_combo_box); + priv->scope_combo_box = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_content_finalize (GObject *object) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (object); + + g_free (priv->system_filename); + g_free (priv->user_filename); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_content_constructed (GObject *object) +{ + EShellView *shell_view; + EShellWindow *shell_window; + EShellContent *shell_content; + GtkSizeGroup *size_group; + GtkAction *action; + GtkWidget *widget; + + shell_content = E_SHELL_CONTENT (object); + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + size_group = e_shell_view_get_size_group (shell_view); + + widget = shell_content->priv->search_entry; + + action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); + e_binding_new ( + G_OBJECT (action), "sensitive", + G_OBJECT (widget), "secondary-icon-sensitive"); + e_binding_new ( + G_OBJECT (action), "stock-id", + G_OBJECT (widget), "secondary-icon-stock"); + e_binding_new ( + G_OBJECT (action), "tooltip", + G_OBJECT (widget), "secondary-icon-tooltip-text"); + + action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window); + g_signal_connect ( + action, "activate", + G_CALLBACK (action_search_execute_cb), shell_content); + + action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); + e_binding_new ( + G_OBJECT (action), "sensitive", + G_OBJECT (widget), "primary-icon-sensitive"); + e_binding_new ( + G_OBJECT (action), "stock-id", + G_OBJECT (widget), "primary-icon-stock"); + e_binding_new ( + G_OBJECT (action), "tooltip", + G_OBJECT (widget), "primary-icon-tooltip-text"); + + widget = shell_content->priv->search_bar; + gtk_size_group_add_widget (size_group, widget); + + shell_content_init_search_context (shell_content); +} + +static void +shell_content_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EShellContentPrivate *priv; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_CONTENT_GET_PRIVATE (widget); + + requisition->width = 0; + requisition->height = 0; + + child = gtk_bin_get_child (GTK_BIN (widget)); + gtk_widget_size_request (child, requisition); + + child = priv->search_bar; + gtk_widget_size_request (child, &child_requisition); + requisition->width = MAX (requisition->width, child_requisition.width); + requisition->height += child_requisition.height; +} + +static void +shell_content_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EShellContentPrivate *priv; + GtkAllocation child_allocation; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_CONTENT_GET_PRIVATE (widget); + + widget->allocation = *allocation; + + child = priv->search_bar; + gtk_widget_size_request (child, &child_requisition); + + child_allocation.x = allocation->x; + child_allocation.y = allocation->y; + child_allocation.width = allocation->width; + child_allocation.height = child_requisition.height; + + gtk_widget_size_allocate (child, &child_allocation); + + child_allocation.y += child_requisition.height; + child_allocation.height = + allocation->height - child_requisition.height; + + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_size_allocate (child, &child_allocation); +} + +static void +shell_content_remove (GtkContainer *container, + GtkWidget *widget) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (container); + + /* Look in the internal widgets first. */ + + if (widget == priv->search_bar) { + gtk_widget_unparent (priv->search_bar); + gtk_widget_queue_resize (GTK_WIDGET (container)); + return; + } + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); +} + +static void +shell_content_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (container); + + if (include_internals) + callback (priv->search_bar, callback_data); + + /* Chain up to parent's forall() method. */ + GTK_CONTAINER_CLASS (parent_class)->forall ( + container, include_internals, callback, callback_data); +} + +static void +shell_content_class_init (EShellContentClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_content_set_property; + object_class->get_property = shell_content_get_property; + object_class->dispose = shell_content_dispose; + object_class->finalize = shell_content_finalize; + object_class->constructed = shell_content_constructed; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->size_request = shell_content_size_request; + widget_class->size_allocate = shell_content_size_allocate; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = shell_content_remove; + container_class->forall = shell_content_forall; + + class->new_search_context = rule_context_new; + + g_object_class_install_property ( + object_class, + PROP_FILTER_ACTION, + g_param_spec_object ( + "filter-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VALUE, + g_param_spec_int ( + "filter-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VISIBLE, + g_param_spec_boolean ( + "filter-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_CONTEXT, + g_param_spec_object ( + "search-context", + NULL, + NULL, + RULE_TYPE_CONTEXT, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_HINT, + g_param_spec_string ( + "search-hint", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_RULE, + g_param_spec_object ( + "search-rule", + NULL, + NULL, + FILTER_TYPE_RULE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_TEXT, + g_param_spec_string ( + "search-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VISIBLE, + g_param_spec_boolean ( + "search-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_ACTION, + g_param_spec_object ( + "scope-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VALUE, + g_param_spec_int ( + "scope-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VISIBLE, + g_param_spec_boolean ( + "scope-visible", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + NULL, + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +shell_content_init (EShellContent *shell_content) +{ + GtkBox *box; + GtkLabel *label; + GtkWidget *widget; + + shell_content->priv = E_SHELL_CONTENT_GET_PRIVATE (shell_content); + + GTK_WIDGET_SET_FLAGS (shell_content, GTK_NO_WINDOW); + + /*** Build the Search Bar ***/ + + widget = gtk_hbox_new (FALSE, 24); + gtk_widget_set_parent (widget, GTK_WIDGET (shell_content)); + shell_content->priv->search_bar = g_object_ref_sink (widget); + gtk_widget_show (widget); + + /* Filter Combo Widgets */ + + box = GTK_BOX (shell_content->priv->search_bar); + + widget = gtk_hbox_new (FALSE, 3); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + box = GTK_BOX (widget); + + /* Translators: The "Show:" label precedes a combo box that + * allows the user to filter the current view. Examples of + * items that appear in the combo box are "Unread Messages", + * "Important Messages", or "Active Appointments". */ + widget = gtk_label_new_with_mnemonic (_("Sho_w:")); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->filter_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_action_combo_box_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->filter_combo_box = g_object_ref (widget); + gtk_widget_show (widget); + + /* Search Entry Widgets */ + + box = GTK_BOX (shell_content->priv->search_bar); + + widget = gtk_hbox_new (FALSE, 3); + gtk_box_pack_start (box, widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + box = GTK_BOX (widget); + + /* Translators: This is part of the quick search interface. + * example: Search: [_______________] in [ Current Folder ] */ + widget = gtk_label_new_with_mnemonic (_("Sear_ch:")); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->search_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_hinted_entry_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (box, widget, TRUE, TRUE, 0); + shell_content->priv->search_entry = g_object_ref (widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + widget, "activate", + G_CALLBACK (shell_content_entry_activated_cb), + shell_content); + + g_signal_connect_swapped ( + widget, "icon-press", + G_CALLBACK (shell_content_entry_icon_press_cb), + shell_content); + + g_signal_connect_swapped ( + widget, "icon-release", + G_CALLBACK (shell_content_entry_icon_release_cb), + shell_content); + + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (shell_content_entry_key_press_cb), + shell_content); + + /* Scope Combo Widgets */ + + /* Translators: This is part of the quick search interface. + * example: Search: [_______________] in [ Current Folder ] */ + widget = gtk_label_new_with_mnemonic (_("i_n")); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->scope_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_action_combo_box_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_content->priv->scope_combo_box = g_object_ref (widget); + gtk_widget_show (widget); +} + +GType +e_shell_content_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_content_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_BIN, "EShellContent", &type_info, 0); + } + + return type; +} + +/** + * e_shell_content_new: + * @shell_view: an #EShellView + * + * Creates a new #EShellContent instance belonging to @shell_view. + * + * Returns: a new #EShellContent instance + **/ +GtkWidget * +e_shell_content_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_SHELL_CONTENT, "shell-view", shell_view, NULL); +} + +/** + * e_shell_content_check_state: + * @shell_content: an #EShellContent + * + * #EShellContent subclasses should implement the + * <structfield>check_state</structfield> method in #EShellContentClass + * to return a set of flags describing the current content selection. + * Subclasses are responsible for defining their own flags. This is + * primarily used to assist shell views with updating actions (see + * e_shell_view_update_actions()). + * + * Returns: a set of flags describing the current @shell_content selection + **/ +guint32 +e_shell_content_check_state (EShellContent *shell_content) +{ + EShellContentClass *shell_content_class; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); + + shell_content_class = E_SHELL_CONTENT_GET_CLASS (shell_content); + g_return_val_if_fail (shell_content_class->check_state != NULL, 0); + + return shell_content_class->check_state (shell_content); +} + +/** + * e_shell_content_get_shell_view: + * @shell_content: an #EShellContent + * + * Returns the #EShellView that was passed to e_shell_content_new(). + * + * Returns: the #EShellView to which @shell_content belongs + **/ +EShellView * +e_shell_content_get_shell_view (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return E_SHELL_VIEW (shell_content->priv->shell_view); +} + +GtkRadioAction * +e_shell_content_get_filter_action (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + return e_action_combo_box_get_action (combo_box); +} + +void +e_shell_content_set_filter_action (EShellContent *shell_content, + GtkRadioAction *filter_action) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + e_action_combo_box_set_action (combo_box, filter_action); + + g_object_notify (G_OBJECT (shell_content), "filter-action"); +} + +gint +e_shell_content_get_filter_value (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + return e_action_combo_box_get_current_value (combo_box); +} + +void +e_shell_content_set_filter_value (EShellContent *shell_content, + gint filter_value) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + e_action_combo_box_set_current_value (combo_box, filter_value); + + g_object_notify (G_OBJECT (shell_content), "filter-value"); +} + +gboolean +e_shell_content_get_filter_visible (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); + + return GTK_WIDGET_VISIBLE (shell_content->priv->filter_combo_box); +} + +void +e_shell_content_set_filter_visible (EShellContent *shell_content, + gboolean filter_visible) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (filter_visible) { + gtk_widget_show (shell_content->priv->filter_label); + gtk_widget_show (shell_content->priv->filter_combo_box); + } else { + gtk_widget_hide (shell_content->priv->filter_label); + gtk_widget_hide (shell_content->priv->filter_combo_box); + } +} + +void +e_shell_content_add_filter_separator_before (EShellContent *shell_content, + gint action_value) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + e_action_combo_box_add_separator_before (combo_box, action_value); +} + +void +e_shell_content_add_filter_separator_after (EShellContent *shell_content, + gint action_value) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->filter_combo_box); + + e_action_combo_box_add_separator_after (combo_box, action_value); +} + +RuleContext * +e_shell_content_get_search_context (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return shell_content->priv->search_context; +} + +const gchar * +e_shell_content_get_search_hint (EShellContent *shell_content) +{ + EHintedEntry *entry; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + entry = E_HINTED_ENTRY (shell_content->priv->search_entry); + + return e_hinted_entry_get_hint (entry); +} + +void +e_shell_content_set_search_hint (EShellContent *shell_content, + const gchar *search_hint) +{ + EHintedEntry *entry; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + entry = E_HINTED_ENTRY (shell_content->priv->search_entry); + + e_hinted_entry_set_hint (entry, search_hint); + + g_object_notify (G_OBJECT (shell_content), "search-hint"); +} + +FilterRule * +e_shell_content_get_search_rule (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return shell_content->priv->search_rule; +} + +void +e_shell_content_set_search_rule (EShellContent *shell_content, + FilterRule *search_rule) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (search_rule != NULL) { + g_return_if_fail (IS_FILTER_RULE (search_rule)); + g_object_ref (search_rule); + } + + if (shell_content->priv->search_rule != NULL) + g_object_unref (shell_content->priv->search_rule); + + shell_content->priv->search_rule = search_rule; + + g_object_notify (G_OBJECT (shell_content), "search-rule"); +} + +const gchar * +e_shell_content_get_search_text (EShellContent *shell_content) +{ + EHintedEntry *entry; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + entry = E_HINTED_ENTRY (shell_content->priv->search_entry); + + return e_hinted_entry_get_text (entry); +} + +void +e_shell_content_set_search_text (EShellContent *shell_content, + const gchar *search_text) +{ + EHintedEntry *entry; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + entry = E_HINTED_ENTRY (shell_content->priv->search_entry); + + e_hinted_entry_set_text (entry, search_text); + + g_object_notify (G_OBJECT (shell_content), "search-text"); +} + +gboolean +e_shell_content_get_search_visible (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); + + return GTK_WIDGET_VISIBLE (shell_content->priv->search_entry); +} + +void +e_shell_content_set_search_visible (EShellContent *shell_content, + gboolean search_visible) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (search_visible) { + gtk_widget_show (shell_content->priv->search_label); + gtk_widget_show (shell_content->priv->search_entry); + } else { + gtk_widget_hide (shell_content->priv->search_label); + gtk_widget_hide (shell_content->priv->search_entry); + } +} + +GtkRadioAction * +e_shell_content_get_scope_action (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + return e_action_combo_box_get_action (combo_box); +} + +void +e_shell_content_set_scope_action (EShellContent *shell_content, + GtkRadioAction *scope_action) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + e_action_combo_box_set_action (combo_box, scope_action); + + g_object_notify (G_OBJECT (shell_content), "scope-action"); +} + +gint +e_shell_content_get_scope_value (EShellContent *shell_content) +{ + EActionComboBox *combo_box; + + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), 0); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + return e_action_combo_box_get_current_value (combo_box); +} + +void +e_shell_content_set_scope_value (EShellContent *shell_content, + gint scope_value) +{ + EActionComboBox *combo_box; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + combo_box = E_ACTION_COMBO_BOX (shell_content->priv->scope_combo_box); + + e_action_combo_box_set_current_value (combo_box, scope_value); + + g_object_notify (G_OBJECT (shell_content), "scope-value"); +} + +gboolean +e_shell_content_get_scope_visible (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), FALSE); + + return GTK_WIDGET_VISIBLE (shell_content->priv->scope_combo_box); +} + +void +e_shell_content_set_scope_visible (EShellContent *shell_content, + gboolean scope_visible) +{ + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + if (scope_visible) { + gtk_widget_show (shell_content->priv->scope_label); + gtk_widget_show (shell_content->priv->scope_combo_box); + } else { + gtk_widget_hide (shell_content->priv->scope_label); + gtk_widget_hide (shell_content->priv->scope_combo_box); + } + + g_object_notify (G_OBJECT (shell_content), "scope-visible"); +} + +void +e_shell_content_run_advanced_search_dialog (EShellContent *shell_content) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkAction *action; + GtkWidget *dialog; + GtkWidget *widget; + FilterRule *rule; + RuleContext *context; + const gchar *user_filename; + gint response; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + user_filename = shell_content->priv->user_filename; + + rule = e_shell_content_get_search_rule (shell_content); + + if (rule == NULL) + rule = filter_rule_new (); + else + rule = filter_rule_clone (rule); + + context = e_shell_content_get_search_context (shell_content); + widget = filter_rule_get_widget (rule, context); + filter_rule_set_source (rule, FILTER_SOURCE_INCOMING); + + dialog = gtk_dialog_new_with_buttons ( + _("Advanced Search"), GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_APPLY, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + + gtk_container_set_border_width (GTK_CONTAINER (dialog), 7); + gtk_container_set_border_width (GTK_CONTAINER (widget), 3); + gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 300); + + gtk_box_pack_start ( + GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 0); + + g_signal_connect_swapped ( + rule, "changed", G_CALLBACK ( + shell_content_dialog_rule_changed), dialog); + + shell_content_dialog_rule_changed (dialog, rule); + +run: + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response != GTK_RESPONSE_OK && response != GTK_RESPONSE_APPLY) + goto exit; + + if (!filter_rule_validate (rule)) + goto run; + + e_shell_content_set_search_rule (shell_content, rule); + + action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window); + gtk_action_activate (action); + + if (response == GTK_RESPONSE_APPLY) { + if (!rule_context_find_rule (context, rule->name, rule->source)) + rule_context_add_rule (context, rule); + rule_context_save (context, user_filename); + goto run; + } + +exit: + g_object_unref (rule); + gtk_widget_destroy (dialog); +} + +void +e_shell_content_run_edit_searches_dialog (EShellContent *shell_content) +{ + RuleContext *context; + RuleEditor *editor; + const gchar *user_filename; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + context = e_shell_content_get_search_context (shell_content); + user_filename = shell_content->priv->user_filename; + + editor = rule_editor_new ( + context, FILTER_SOURCE_INCOMING, _("Searches")); + gtk_window_set_title (GTK_WINDOW (editor), _("Searches")); + + if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK) + rule_context_save (context, user_filename); + + gtk_widget_destroy (GTK_WIDGET (editor)); +} + +void +e_shell_content_run_save_search_dialog (EShellContent *shell_content) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GtkWidget *dialog; + GtkWidget *widget; + FilterRule *rule; + RuleContext *context; + const gchar *search_text; + const gchar *user_filename; + gchar *search_name; + gint response; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + user_filename = shell_content->priv->user_filename; + + rule = e_shell_content_get_search_rule (shell_content); + g_return_if_fail (IS_FILTER_RULE (rule)); + rule = filter_rule_clone (rule); + + search_text = e_shell_content_get_search_text (shell_content); + if (search_text == NULL || *search_text == '\0') + search_text = "''"; + + search_name = g_strdup_printf ("%s %s", rule->name, search_text); + filter_rule_set_name (rule, search_name); + g_free (search_name); + + context = e_shell_content_get_search_context (shell_content); + widget = filter_rule_get_widget (rule, context); + filter_rule_set_source (rule, FILTER_SOURCE_INCOMING); + + dialog = gtk_dialog_new_with_buttons ( + _("Save Search"), GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); + + gtk_container_set_border_width (GTK_CONTAINER (dialog), 7); + gtk_container_set_border_width (GTK_CONTAINER (widget), 3); + gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 300); + + gtk_box_pack_start ( + GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 0); + + g_signal_connect_swapped ( + rule, "changed", G_CALLBACK ( + shell_content_dialog_rule_changed), dialog); + + shell_content_dialog_rule_changed (dialog, rule); + +run: + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response != GTK_RESPONSE_OK) + goto exit; + + if (!filter_rule_validate (rule)) + goto run; + + rule_context_add_rule (context, rule); + rule_context_save (context, user_filename); + +exit: + g_object_unref (rule); + gtk_widget_destroy (dialog); +} + +void +e_shell_content_restore_state (EShellContent *shell_content, + const gchar *group_name) +{ + EShellView *shell_view; + EShellWindow *shell_window; + GKeyFile *key_file; + GtkAction *action; + GtkWidget *widget; + const gchar *key; + gchar *string; + + g_return_if_fail (E_IS_SHELL_CONTENT (shell_content)); + g_return_if_fail (group_name != NULL); + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_window = e_shell_view_get_shell_window (shell_view); + key_file = e_shell_view_get_state_key_file (shell_view); + + /* Changing the combo boxes triggers searches, so block + * the search action until the state is fully restored. */ + action = e_shell_window_get_action (shell_window, "search-execute"); + gtk_action_block_activate (action); + + key = STATE_KEY_SEARCH_FILTER; + string = g_key_file_get_string (key_file, group_name, key, NULL); + if (string != NULL && *string != '\0') + action = e_shell_window_get_action (shell_window, string); + else + action = NULL; + if (action != NULL) + gtk_action_activate (action); + else { + /* Pick the first combo box item. */ + widget = shell_content->priv->filter_combo_box; + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + } + g_free (string); + + key = STATE_KEY_SEARCH_SCOPE; + string = g_key_file_get_string (key_file, group_name, key, NULL); + if (string != NULL && *string != '\0') + action = e_shell_window_get_action (shell_window, string); + else + action = NULL; + if (action != NULL) + gtk_action_activate (action); + else { + /* Pick the first combo box item. */ + widget = shell_content->priv->scope_combo_box; + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + } + g_free (string); + + key = STATE_KEY_SEARCH_TEXT; + string = g_key_file_get_string (key_file, group_name, key, NULL); + e_shell_content_set_search_text (shell_content, string); + g_free (string); + + action = e_shell_window_get_action (shell_window, "search-execute"); + gtk_action_unblock_activate (action); + + /* Now execute the search. */ + gtk_action_activate (action); +} diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h new file mode 100644 index 0000000000..8e754fff26 --- /dev/null +++ b/shell/e-shell-content.h @@ -0,0 +1,148 @@ +/* + * e-shell-content.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-shell-content + * @short_description: the right side of the main window + * @include: shell/e-shell-content.h + **/ + +#ifndef E_SHELL_CONTENT_H +#define E_SHELL_CONTENT_H + +#include <shell/e-shell-common.h> +#include <filter/filter-rule.h> +#include <filter/rule-context.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_CONTENT \ + (e_shell_content_get_type ()) +#define E_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_CONTENT, EShellContent)) +#define E_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_CONTENT, EShellContentClass)) +#define E_IS_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_CONTENT)) +#define E_IS_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_CONTENT)) +#define E_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_CONTENT, EShellContentClass)) + +G_BEGIN_DECLS + +/* Avoid including <e-shell-view.h>, because it includes us! */ +struct _EShellView; + +typedef struct _EShellContent EShellContent; +typedef struct _EShellContentClass EShellContentClass; +typedef struct _EShellContentPrivate EShellContentPrivate; + +/** + * EShellContent: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EShellContent { + GtkBin parent; + EShellContentPrivate *priv; +}; + +struct _EShellContentClass { + GtkBinClass parent_class; + + /* Factory Methods */ + RuleContext * (*new_search_context) (void); + + guint32 (*check_state) (EShellContent *shell_content); +}; + +GType e_shell_content_get_type (void); +GtkWidget * e_shell_content_new (struct _EShellView *shell_view); +guint32 e_shell_content_check_state (EShellContent *shell_content); +struct _EShellView * + e_shell_content_get_shell_view (EShellContent *shell_content); +GtkRadioAction *e_shell_content_get_filter_action + (EShellContent *shell_content); +void e_shell_content_set_filter_action + (EShellContent *shell_content, + GtkRadioAction *filter_action); +gint e_shell_content_get_filter_value(EShellContent *shell_content); +void e_shell_content_set_filter_value(EShellContent *shell_content, + gint filter_value); +gboolean e_shell_content_get_filter_visible + (EShellContent *shell_content); +void e_shell_content_set_filter_visible + (EShellContent *shell_content, + gboolean filter_visible); +void e_shell_content_add_filter_separator_before + (EShellContent *shell_content, + gint action_value); +void e_shell_content_add_filter_separator_after + (EShellContent *shell_content, + gint action_value); +RuleContext * e_shell_content_get_search_context + (EShellContent *shell_content); +const gchar * e_shell_content_get_search_hint (EShellContent *shell_content); +void e_shell_content_set_search_hint (EShellContent *shell_content, + const gchar *search_hint); +FilterRule * e_shell_content_get_search_rule (EShellContent *shell_content); +void e_shell_content_set_search_rule (EShellContent *shell_content, + FilterRule *search_rule); +const gchar * e_shell_content_get_search_text (EShellContent *shell_content); +void e_shell_content_set_search_text (EShellContent *shell_content, + const gchar *search_text); +gboolean e_shell_content_get_search_visible + (EShellContent *shell_content); +void e_shell_content_set_search_visible + (EShellContent *shell_content, + gboolean search_visible); +GtkRadioAction *e_shell_content_get_scope_action(EShellContent *shell_content); +void e_shell_content_set_scope_action(EShellContent *shell_content, + GtkRadioAction *scope_action); +gint e_shell_content_get_scope_value (EShellContent *shell_content); +void e_shell_content_set_scope_value (EShellContent *shell_content, + gint scope_value); +gboolean e_shell_content_get_scope_visible + (EShellContent *shell_content); +void e_shell_content_set_scope_visible + (EShellContent *shell_content, + gboolean scope_visible); +const gchar * e_shell_content_get_view_id (EShellContent *shell_content); +void e_shell_content_set_view_id (EShellContent *shell_content, + const gchar *view_id); +void e_shell_content_run_advanced_search_dialog + (EShellContent *shell_content); +void e_shell_content_run_edit_searches_dialog + (EShellContent *shell_content); +void e_shell_content_run_save_search_dialog + (EShellContent *shell_content); +void e_shell_content_restore_state (EShellContent *shell_content, + const gchar *group_name); + +G_END_DECLS + +#endif /* E_SHELL_CONTENT_H */ diff --git a/shell/e-shell-importer.c b/shell/e-shell-importer.c index c9953b9589..aba3546443 100644 --- a/shell/e-shell-importer.c +++ b/shell/e-shell-importer.c @@ -34,10 +34,6 @@ #include <glib/gi18n.h> -#include <libgnomeui/gnome-druid.h> -#include <libgnomeui/gnome-druid-page-edge.h> -#include <libgnomeui/gnome-druid-page-standard.h> - #include "misc/e-gui-utils.h" #include "e-util/e-dialog-utils.h" @@ -48,7 +44,6 @@ #include "e-shell.h" #include "e-shell-window.h" -#include "e-shell-constants.h" #include "e-shell-importer.h" @@ -84,9 +79,7 @@ typedef struct _ImportDialogImporterPage { typedef struct _ImportData { EShellWindow *window; - GladeXML *wizard; - GtkWidget *dialog; - GtkWidget *druid; + GtkWidget *assistant; ImportDialogFilePage *filepage; ImportDialogDestPage *destpage; ImportDialogTypePage *typepage; @@ -96,8 +89,6 @@ typedef struct _ImportData { GtkWidget *typedialog; GtkWidget *destdialog; GtkWidget *intelligent; - GnomeDruidPageEdge *start; - GnomeDruidPageEdge *finish; GtkWidget *vbox; EImport *import; @@ -236,7 +227,7 @@ filename_changed (GtkWidget *widget, } } - gnome_druid_set_buttons_sensitive(GNOME_DRUID (data->druid), TRUE, fileok, TRUE, FALSE); + gtk_assistant_set_page_complete (GTK_ASSISTANT (data->assistant), page->vbox, fileok); } static void @@ -250,29 +241,6 @@ filetype_changed_cb (GtkWidget *combobox, ImportData *data) filename_changed (data->filepage->filename, data); } -#if 0 -static gint -compare_info_name (gconstpointer data1, const void *data2) -{ - const Bonobo_ServerInfo *info1 = (Bonobo_ServerInfo *)data1; - const Bonobo_ServerInfo *info2 = (Bonobo_ServerInfo *)data2; - const gchar *name1 = get_name_from_component_info (info1); - const gchar *name2 = get_name_from_component_info (info2); - - /* If we can't find a name for a plug-in, its iid will be used - * for display. Put such plug-ins at the end of the list since - * their displayed name won't be really user-friendly - */ - if (name1 == NULL) { - return -1; - } - if (name2 == NULL) { - return 1; - } - return g_utf8_collate (name1, name2); -} -#endif - static ImportDialogFilePage * importer_file_page_new (ImportData *data) { @@ -328,6 +296,8 @@ importer_file_page_new (ImportData *data) row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_label_set_mnemonic_widget(GTK_LABEL(label), page->filetype); + gtk_container_set_border_width (GTK_CONTAINER (page->vbox), 12); + gtk_widget_show_all (table); return page; @@ -342,6 +312,8 @@ importer_dest_page_new (ImportData *data) page->vbox = gtk_vbox_new (FALSE, 5); + gtk_container_set_border_width (GTK_CONTAINER (page->vbox), 12); + return page; } @@ -359,7 +331,10 @@ importer_type_page_new (ImportData *data) page->file = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (page->intelligent), _("Import a _single file")); gtk_box_pack_start (GTK_BOX (page->vbox), page->file, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (page->vbox), 12); + gtk_widget_show_all (page->vbox); + return page; } @@ -377,23 +352,25 @@ importer_importer_page_new (ImportData *data) sep = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (page->vbox), sep, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (page->vbox), 12); + gtk_widget_show_all (page->vbox); return page; } -static gboolean -prepare_intelligent_page (GnomeDruidPage *dpage, - GnomeDruid *druid, - ImportData *data) +static void +prepare_intelligent_page (GtkAssistant *assistant, GtkWidget *apage, ImportData *data) { GSList *l; GtkWidget *table; gint row; ImportDialogImporterPage *page = data->importerpage; - if (page->target != NULL) - return FALSE; + if (page->target != NULL) { + gtk_assistant_set_page_complete (assistant, apage, FALSE); + return; + } page->target = e_import_target_new_home(data->import, g_get_home_dir()); @@ -403,8 +380,8 @@ prepare_intelligent_page (GnomeDruidPage *dpage, if (l == NULL) { gtk_box_pack_start(GTK_BOX (data->importerpage->vbox), create_help("nodata_html"), FALSE, TRUE, 0); - gnome_druid_set_buttons_sensitive(druid, TRUE, FALSE, TRUE, FALSE); - return TRUE; + gtk_assistant_set_page_complete (assistant, apage, FALSE); + return; } table = gtk_table_new(g_slist_length(l), 2, FALSE); @@ -432,33 +409,30 @@ prepare_intelligent_page (GnomeDruidPage *dpage, gtk_widget_show(table); gtk_box_pack_start((GtkBox *)data->importerpage->vbox, table, FALSE, FALSE, 0); - return FALSE; + gtk_assistant_set_page_complete (assistant, apage, TRUE); } static void -import_druid_cancel (GnomeDruid *druid, - ImportData *data) +import_assistant_cancel (GtkAssistant *assistant, ImportData *data) { if (data->import_dialog) gtk_dialog_response (GTK_DIALOG (data->import_dialog), GTK_RESPONSE_CANCEL); else - gtk_widget_destroy (GTK_WIDGET (data->dialog)); + gtk_widget_destroy (GTK_WIDGET (data->assistant)); } static gboolean -import_druid_esc (GnomeDruid *druid, - GdkEventKey *event, - ImportData *data) +import_assistant_esc (GtkAssistant *assistant, GdkEventKey *event, ImportData *data) { if (event->keyval == GDK_Escape) { - gtk_widget_destroy (GTK_WIDGET (data->dialog)); + gtk_widget_destroy (GTK_WIDGET (assistant)); return TRUE; } else return FALSE; } static void -import_druid_weak_notify (gpointer blah, +import_assistant_weak_notify (gpointer blah, GObject *where_the_object_was) { ImportData *data = (ImportData *) blah; @@ -466,8 +440,8 @@ import_druid_weak_notify (gpointer blah, if (data->import_dialog && (GObject *)data->import_dialog != where_the_object_was) { /* postpone freeing of 'data' after the 'import_dialog' will stop, but also indicate that the 'dialog' gone already */ - data->dialog = NULL; - g_object_weak_ref ((GObject *)data->import_dialog, import_druid_weak_notify, data); + data->assistant = NULL; + g_object_weak_ref ((GObject *)data->import_dialog, import_assistant_weak_notify, data); gtk_dialog_response (GTK_DIALOG (data->import_dialog), GTK_RESPONSE_CANCEL); return; } @@ -481,7 +455,6 @@ import_druid_weak_notify (gpointer blah, g_object_unref(data->import); - g_object_unref(data->wizard); g_free(data); } @@ -505,7 +478,7 @@ static void import_done(EImport *ei, gpointer d) { ImportData *data = d; - gboolean have_dialog = data->dialog != NULL; + gboolean have_dialog = data->assistant != NULL; gtk_widget_destroy (data->import_dialog); @@ -513,7 +486,7 @@ import_done(EImport *ei, gpointer d) on the above destroy call */ if (have_dialog) { data->import_dialog = NULL; - gtk_widget_destroy (data->dialog); + gtk_widget_destroy (data->assistant); } } @@ -532,9 +505,7 @@ import_intelligent_done(EImport *ei, gpointer d) } static void -import_druid_finish (GnomeDruidPage *page, - GnomeDruid *druid, - ImportData *data) +import_assistant_apply (GtkAssistant *assistant, ImportData *data) { EImportCompleteFunc done = NULL; gchar *msg = NULL; @@ -567,16 +538,14 @@ import_druid_finish (GnomeDruidPage *page, e_import_import(data->import, data->import_target, data->import_importer, import_status, import_done, data); } else { - gtk_widget_destroy(data->dialog); + gtk_widget_destroy(data->assistant); } g_free(msg); } -static gboolean -prepare_file_page (GnomeDruidPage *dpage, - GnomeDruid *druid, - ImportData *data) +static void +prepare_file_page (GtkAssistant *assistant, GtkWidget *apage, ImportData *data) { GSList *importers, *imp; GtkListStore *store; @@ -584,7 +553,7 @@ prepare_file_page (GnomeDruidPage *dpage, if (page->target != NULL) { filename_changed(data->filepage->filename, data); - return FALSE; + return; } page->target = e_import_target_new_uri(data->import, NULL, NULL); @@ -613,23 +582,10 @@ prepare_file_page (GnomeDruidPage *dpage, filename_changed (data->filepage->filename, data); g_signal_connect (page->filetype, "changed", G_CALLBACK (filetype_changed_cb), data); - - return FALSE; -} - -static gboolean -next_file_page (GnomeDruidPage *page, - GnomeDruid *druid, - ImportData *data) -{ - /* We dont sensitise the next button if we're not already usable */ - return FALSE; } static gboolean -prepare_dest_page (GnomeDruidPage *dpage, - GnomeDruid *druid, - ImportData *data) +prepare_dest_page (GtkAssistant *assistant, GtkWidget *apage, ImportData *data) { ImportDialogDestPage *page = data->destpage; @@ -643,174 +599,184 @@ prepare_dest_page (GnomeDruidPage *dpage, gtk_widget_show(page->control); } - gtk_box_pack_start((GtkBox *)data->destpage->vbox, page->control, TRUE, TRUE, 0); + gtk_box_pack_start ((GtkBox *)data->destpage->vbox, page->control, TRUE, TRUE, 0); + gtk_assistant_set_page_complete (assistant, apage, TRUE); return FALSE; } -static gboolean -next_dest_page (GnomeDruidPage *page, - GnomeDruid *druid, - ImportData *data) -{ - gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->finish)); - return TRUE; -} - -static gboolean -next_type_page (GnomeDruidPage *page, - GnomeDruid *druid, - ImportData *data) +static void +dialog_weak_notify (gpointer data, + GObject *where_the_dialog_was) { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) { - gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->intelligent)); - } else { - gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog)); - } + gboolean *dialog_open = (gboolean *) data; - return TRUE; + *dialog_open = FALSE; } -static gboolean -back_finish_page (GnomeDruidPage *page, - GnomeDruid *druid, - ImportData *data) +enum { + PAGE_START, + PAGE_INTELI_OR_DIRECT, + PAGE_INTELI_SOURCE, + PAGE_FILE_CHOOSE, + PAGE_FILE_DEST, + PAGE_FINISH +}; + +static gint +forward_cb (gint current_page, gpointer user_data) { - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) { - gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->intelligent)); - } else { - gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->destdialog)); + ImportData *data = user_data; + + switch (current_page) { + case PAGE_INTELI_OR_DIRECT: + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) + return PAGE_INTELI_SOURCE; + else + return PAGE_FILE_CHOOSE; + case PAGE_INTELI_SOURCE: + return PAGE_FINISH; } - return TRUE; -} - -static gboolean -back_intelligent_page (GnomeDruidPage *page, - GnomeDruid *druid, - ImportData *data) -{ - gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->typedialog)); - return TRUE; + return current_page + 1; } static void -dialog_weak_notify (gpointer data, - GObject *where_the_dialog_was) +import_assistant_prepare (GtkAssistant *assistant, GtkWidget *page, gpointer user_data) { - gboolean *dialog_open = (gboolean *) data; - - *dialog_open = FALSE; + ImportData *data = user_data; + + if (page == data->importerpage->vbox) + prepare_intelligent_page (assistant, page, data); + else if (page == data->filepage->vbox) + prepare_file_page (assistant, page, data); + else if (page == data->destpage->vbox) + prepare_dest_page (assistant, page, data); } void e_shell_importer_start_import (EShellWindow *shell_window) { + const gchar *empty_xpm_img[] = { + "48 1 2 1", + " c None", + ". c #FFFFFF", + " "}; ImportData *data = g_new0 (ImportData, 1); - GtkWidget *html; + GtkWidget *html, *page; static gboolean dialog_open = FALSE; - GdkPixbuf *icon; - gchar *gladefile; + GdkPixbuf *icon, *spacer; + GtkAssistant *assistant; if (dialog_open) { return; } - data->import = e_import_new("org.gnome.evolution.shell.importer"); + data->import = e_import_new ("org.gnome.evolution.shell.importer"); icon = e_icon_factory_get_icon ("stock_mail-import", GTK_ICON_SIZE_DIALOG); + spacer = gdk_pixbuf_new_from_xpm_data (empty_xpm_img); dialog_open = TRUE; data->window = shell_window; + data->assistant = gtk_assistant_new (); - gladefile = g_build_filename (EVOLUTION_GLADEDIR, "import.glade", NULL); - data->wizard = glade_xml_new (gladefile, NULL, NULL); - g_free (gladefile); - data->dialog = glade_xml_get_widget (data->wizard, "importwizard"); - gtk_window_set_default_size (GTK_WINDOW (data->dialog), 480, 320); - gtk_window_set_wmclass (GTK_WINDOW (data->dialog), "importdruid", - "Evolution:shell"); - e_dialog_set_transient_for (GTK_WINDOW (data->dialog), GTK_WIDGET (shell_window)); - g_object_weak_ref ((GObject *)data->dialog, dialog_weak_notify, &dialog_open); - - data->druid = glade_xml_get_widget (data->wizard, "druid1"); - g_signal_connect (data->druid, "cancel", - G_CALLBACK (import_druid_cancel), data); - g_signal_connect (data->druid, "key_press_event", - G_CALLBACK (import_druid_esc), data); - - gtk_button_set_use_underline ((GtkButton *)((GnomeDruid *)data->druid)->finish, TRUE); - gtk_button_set_label((GtkButton *)((GnomeDruid *)data->druid)->finish, _("_Import")); + assistant = GTK_ASSISTANT (data->assistant); + + gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER); + gtk_window_set_title (GTK_WINDOW (assistant), _("Evolution Import Assistant")); + gtk_window_set_default_size (GTK_WINDOW (assistant), 500, 330); /* Start page */ - data->start = GNOME_DRUID_PAGE_EDGE (glade_xml_get_widget (data->wizard, "page0")); - gnome_druid_page_edge_set_logo (data->start, icon); + page = gtk_label_new (""); + gtk_label_set_line_wrap (GTK_LABEL (page), TRUE); + gtk_misc_set_alignment (GTK_MISC (page), 0.0, 0.5); + gtk_misc_set_padding (GTK_MISC (page), 12, 12); + gtk_label_set_text (GTK_LABEL (page), _( + "Welcome to the Evolution Import Assistant.\n" + "With this assistant you will be guided through the process of importing external files into Evolution.")); + + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_header_image (assistant, page, icon); + gtk_assistant_set_page_title (assistant, page, _("Evolution Import Assistant")); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_INTRO); + gtk_assistant_set_page_side_image (assistant, page, spacer); + gtk_assistant_set_page_complete (assistant, page, TRUE); /* Intelligent or direct import page */ - data->typedialog = glade_xml_get_widget (data->wizard, "page1"); - gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (data->typedialog), icon); - g_signal_connect (data->typedialog, "next", - G_CALLBACK (next_type_page), data); data->typepage = importer_type_page_new (data); html = create_help ("type_html"); gtk_box_pack_start (GTK_BOX (data->typepage->vbox), html, FALSE, TRUE, 0); gtk_box_reorder_child (GTK_BOX (data->typepage->vbox), html, 0); - gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->typedialog)->vbox), data->typepage->vbox, TRUE, TRUE, 0); + page = data->typepage->vbox; + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_header_image (assistant, page, icon); + gtk_assistant_set_page_title (assistant, page, _("Importer Type")); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT); + gtk_assistant_set_page_complete (assistant, page, TRUE); /* Intelligent importer source page */ - data->intelligent = glade_xml_get_widget (data->wizard, "page2-intelligent"); - gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (data->intelligent), icon); - g_signal_connect (data->intelligent, "back", - G_CALLBACK (back_intelligent_page), data); - g_signal_connect_after (data->intelligent, "prepare", - G_CALLBACK (prepare_intelligent_page), data); - data->importerpage = importer_importer_page_new (data); html = create_help ("intelligent_html"); gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), html, FALSE, TRUE, 0); gtk_box_reorder_child (GTK_BOX (data->importerpage->vbox), html, 0); - gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->intelligent)->vbox), data->importerpage->vbox, TRUE, TRUE, 0); + page = data->importerpage->vbox; + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_header_image (assistant, page, icon); + gtk_assistant_set_page_title (assistant, page, _("Select Information to Import")); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT); /* File selection and file type page */ - data->filedialog = glade_xml_get_widget (data->wizard, "page2-file"); - gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (data->filedialog), icon); - g_signal_connect_after (data->filedialog, "prepare", - G_CALLBACK (prepare_file_page), data); - g_signal_connect (data->filedialog, "next", - G_CALLBACK (next_file_page), data); data->filepage = importer_file_page_new (data); - html = create_help ("file_html"); gtk_box_pack_start (GTK_BOX (data->filepage->vbox), html, FALSE, TRUE, 0); gtk_box_reorder_child (GTK_BOX (data->filepage->vbox), html, 0); - gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->filedialog)->vbox), data->filepage->vbox, TRUE, TRUE, 0); + page = data->filepage->vbox; + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_header_image (assistant, page, icon); + gtk_assistant_set_page_title (assistant, page, _("Select a File")); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT); /* File destination page */ - data->destdialog = glade_xml_get_widget (data->wizard, "page3-file"); - g_signal_connect_after (data->destdialog, "prepare", - G_CALLBACK (prepare_dest_page), data); - g_signal_connect (data->destdialog, "next", - G_CALLBACK (next_dest_page), data); - data->destpage = importer_dest_page_new (data); - gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->destdialog)->vbox), data->destpage->vbox, TRUE, TRUE, 0); + page = data->destpage->vbox; + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_header_image (assistant, page, icon); + gtk_assistant_set_page_title (assistant, page, _("Import Location")); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT); /* Finish page */ - data->finish = GNOME_DRUID_PAGE_EDGE (glade_xml_get_widget (data->wizard, "page4")); - gnome_druid_page_edge_set_logo (data->finish, icon); - g_signal_connect (data->finish, "back", - G_CALLBACK (back_finish_page), data); + page = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (page), 0.5, 0.5); + gtk_label_set_text (GTK_LABEL (page), _("Click \"Apply\" to begin importing the file into Evolution.")); - g_signal_connect (data->finish, "finish", - G_CALLBACK (import_druid_finish), data); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_header_image (assistant, page, icon); + gtk_assistant_set_page_title (assistant, page, _("Import File")); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM); + gtk_assistant_set_page_side_image (assistant, page, spacer); + gtk_assistant_set_page_complete (assistant, page, TRUE); - g_object_weak_ref ((GObject *)data->dialog, import_druid_weak_notify, data); + /* setup the rest */ + g_object_weak_ref ((GObject *)assistant, dialog_weak_notify, &dialog_open); + + gtk_assistant_set_forward_page_func (assistant, forward_cb, data, NULL); + + g_signal_connect (assistant, "key_press_event", G_CALLBACK (import_assistant_esc), data); + g_signal_connect (assistant, "cancel", G_CALLBACK (import_assistant_cancel), data); + g_signal_connect (assistant, "prepare", G_CALLBACK (import_assistant_prepare), data); + g_signal_connect (assistant, "apply", G_CALLBACK (import_assistant_apply), data); + + g_object_weak_ref ((GObject *)assistant, import_assistant_weak_notify, data); g_object_unref (icon); + g_object_unref (spacer); + + gtk_assistant_update_buttons_state (assistant); - gtk_widget_show_all (data->dialog); + gtk_widget_show_all (data->assistant); } diff --git a/shell/e-shell-importer.h b/shell/e-shell-importer.h index d9dffcfb0b..bd57fbd4f0 100644 --- a/shell/e-shell-importer.h +++ b/shell/e-shell-importer.h @@ -20,9 +20,16 @@ * */ -#ifndef _E_SHELL_IMPORTER_H_ -#define _E_SHELL_IMPORTER_H_ +#ifndef E_SHELL_IMPORTER_H +#define E_SHELL_IMPORTER_H -void e_shell_importer_start_import (EShellWindow *shell_window); +#include "e-shell-common.h" +#include "e-shell-window.h" -#endif +G_BEGIN_DECLS + +void e_shell_importer_start_import (EShellWindow *shell_window); + +G_END_DECLS + +#endif /* E_SHELL_IMPORTER_H */ diff --git a/shell/e-shell-migrate.c b/shell/e-shell-migrate.c new file mode 100644 index 0000000000..18e085f0cc --- /dev/null +++ b/shell/e-shell-migrate.c @@ -0,0 +1,351 @@ +/* + * e-shell-migrate.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-migrate.h" + +#include <string.h> +#include <unistd.h> +#include <glib/gi18n.h> +#include <glib/gstdio.h> +#include <libedataserver/e-xml-utils.h> + +#include "e-util/e-bconf-map.h" +#include "e-util/e-error.h" +#include "e-util/e-fsutils.h" +#include "e-util/e-util.h" + +#include "es-event.h" + +#define GCONF_VERSION_KEY "/apps/evolution/version" +#define GCONF_LAST_VERSION_KEY "/apps/evolution/last_version" + +static const gchar * +shell_migrate_get_old_data_dir (void) +{ + static gchar *old_data_dir = NULL; + + if (G_UNLIKELY (old_data_dir == NULL)) + old_data_dir = g_build_filename ( + g_get_home_dir (), "evolution", NULL); + + return old_data_dir; +} + +static gboolean +shell_migrate_attempt (EShell *shell, + gint major, + gint minor, + gint micro) +{ + GList *backends; + gboolean success = TRUE; + + backends = e_shell_get_shell_backends (shell); + + while (success && backends != NULL) { + EShellBackend *shell_backend = backends->data; + GError *error = NULL; + + success = e_shell_backend_migrate ( + shell_backend, major, minor, micro, &error); + + if (error != NULL) { + gint response; + + response = e_error_run ( + NULL, "shell:upgrade-failed", + error->message, NULL); + + if (response == GTK_RESPONSE_CANCEL) + success = FALSE; + + g_error_free (error); + } + + backends = g_list_next (backends); + } + + return success; +} + +static void +shell_migrate_get_version (EShell *shell, + gint *major, + gint *minor, + gint *micro) +{ + GConfClient *client; + const gchar *key; + const gchar *old_data_dir; + gchar *string; + + old_data_dir = shell_migrate_get_old_data_dir (); + + key = GCONF_VERSION_KEY; + client = e_shell_get_gconf_client (shell); + string = gconf_client_get_string (client, key, NULL); + + if (string != NULL) { + /* Since 1.4.0 we've kept the version key in GConf. */ + sscanf (string, "%d.%d.%d", major, minor, micro); + g_free (string); + + } else if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) { + /* If the old data directory does not exist, + * it must be a new installation. */ + *major = 0; + *minor = 0; + *micro = 0; + + } else { + xmlDocPtr doc; + xmlNodePtr source; + gchar *filename; + + filename = g_build_filename ( + old_data_dir, "config.xmldb", NULL); + doc = e_xml_parse_file (filename); + g_free (filename); + + if (doc == NULL) + return; + + source = e_bconf_get_path (doc, "/Shell"); + if (source != NULL) { + key = "upgrade_from_1_0_to_1_2_performed"; + string = e_bconf_get_value (source, key); + } + + if (string != NULL && *string == '1') { + *major = 1; + *minor = 2; + *micro = 0; + } else { + *major = 1; + *minor = 0; + *micro = 0; + } + + g_free (string); + + if (doc != NULL) + xmlFreeDoc (doc); + } +} + +static gint +shell_migrate_remove_dir (const gchar *root, + const gchar *path) +{ + GDir *dir; + const gchar *basename; + gchar *filename; + gint result = -1; + + /* Recursively removes a directory and its contents. */ + + dir = g_dir_open (path, 0, NULL); + if (dir == NULL) + return -1; + + while ((basename = g_dir_read_name (dir)) != NULL) { + filename = g_build_filename (path, basename, NULL); + + /* Make sure we haven't strayed from the evolution dir. */ + g_return_val_if_fail (strlen (path) >= strlen (root), -1); + g_return_val_if_fail (g_str_has_prefix (path, root), -1); + + if (g_file_test (filename, G_FILE_TEST_IS_DIR)) { + if (shell_migrate_remove_dir (root, filename) < 0) + goto fail; + } else { + if (g_unlink (filename) < 0) + goto fail; + } + + g_free (filename); + filename = NULL; + } + + result = g_rmdir (path); + +fail: + g_free (filename); + g_dir_close (dir); + + return result; +} + +gboolean +e_shell_migrate_attempt (EShell *shell) +{ + ESEvent *ese; + GConfClient *client; + const gchar *key; + const gchar *old_data_dir; + gint major, minor, micro; + gint last_major, last_minor, last_micro; + gint curr_major, curr_minor, curr_micro; + gboolean migrated = FALSE; + gchar *string; + + g_return_val_if_fail (E_IS_SHELL (shell), FALSE); + + client = e_shell_get_gconf_client (shell); + old_data_dir = shell_migrate_get_old_data_dir (); + + if (sscanf (BASE_VERSION, "%d.%d", &curr_major, &curr_minor) != 2) { + g_warning ("Could not parse BASE_VERSION (%s)", BASE_VERSION); + return TRUE; + } + + curr_micro = atoi (UPGRADE_REVISION); + + shell_migrate_get_version (shell, &major, &minor, µ); + + if (!(curr_major > major || + (curr_major == major && curr_minor > minor) || + (curr_minor == minor && curr_micro > micro))) + goto check_old; + + /* If upgrading from < 1.5, we need to copy most data from + * ~/evolution to ~/.evolution. Make sure we have the disk + * space for it before proceeding. */ + if (major == 1 && minor < 5) { + glong avail; + glong usage; + + usage = e_fsutils_usage (old_data_dir); + avail = e_fsutils_avail (g_get_home_dir ()); + if (usage >= 0 && avail >= 0 && avail < usage) { + gchar *need; + gchar *have; + + need = g_strdup_printf (_("%ld KB"), usage); + have = g_strdup_printf (_("%ld KB"), avail); + + e_error_run ( + NULL, "shell:upgrade-nospace", + need, have, NULL); + + g_free (need); + g_free (have); + + _exit (EXIT_SUCCESS); + } + } + + if (!shell_migrate_attempt (shell, major, minor, micro)) + _exit (EXIT_SUCCESS); + + /* Record a successful migration. */ + string = g_strdup_printf ("%d.%d.%d", major, minor, micro); + gconf_client_set_string (client, GCONF_VERSION_KEY, string, NULL); + g_free (string); + + migrated = TRUE; + +check_old: + + key = GCONF_LAST_VERSION_KEY; + + /* Try to retrieve the last migrated version from GConf. */ + string = gconf_client_get_string (client, key, NULL); + if (migrated || string == NULL || sscanf (string, "%d.%d.%d", + &last_major, &last_minor, &last_micro) != 3) { + last_major = major; + last_minor = minor; + last_micro = micro; + } + g_free (string); + + /* If the last migrated version was old, check for stuff to remove. */ + if (last_major == 1 && last_minor < 5 && + g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) { + + gint response; + + string = g_strdup_printf ( + "%d.%d.%d", last_major, last_minor, last_micro); + response = e_error_run ( + NULL, "shell:upgrade-remove-1-4", string, NULL); + g_free (string); + + switch (response) { + case GTK_RESPONSE_OK: /* delete */ + response = e_error_run ( + NULL, + "shell:upgrade-remove-1-4-confirm", + NULL); + if (response == GTK_RESPONSE_OK) + shell_migrate_remove_dir ( + old_data_dir, old_data_dir); + else + break; + /* fall through */ + + case GTK_RESPONSE_ACCEPT: /* keep */ + last_major = curr_major; + last_minor = curr_minor; + last_micro = curr_micro; + break; + + default: + break; + } + } else { + last_major = curr_major; + last_minor = curr_minor; + last_micro = curr_micro; + } + + string = g_strdup_printf ( + "%d.%d.%d", last_major, last_minor, last_micro); + gconf_client_set_string (client, key, string, NULL); + g_free (string); + + /** @Event: Shell attempted upgrade + * @Id: upgrade.done + * @Target: ESMenuTargetState + * + * This event is emitted whenever the shell successfully attempts + * an upgrade. + **/ + ese = es_event_peek (); + e_event_emit ( + (EEvent *) ese, "upgrade.done", + (EEventTarget *) es_event_target_new_upgrade ( + ese, curr_major, curr_minor, curr_micro)); + + return TRUE; +} + +GQuark +e_shell_migrate_error_quark (void) +{ + static GQuark quark = 0; + + if (G_UNLIKELY (quark == 0)) + quark = g_quark_from_static_string ( + "e-shell-migrate-error-quark"); + + return quark; +} diff --git a/shell/evolution-shell-component-utils.h b/shell/e-shell-migrate.h index 1c2412e230..8ebe69709b 100644 --- a/shell/evolution-shell-component-utils.h +++ b/shell/e-shell-migrate.h @@ -1,4 +1,6 @@ /* + * e-shell-migrate.h + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -13,35 +15,38 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef __EVOLUTION_SHELL_COMPONENT_UTILS_H__ -#define __EVOLUTION_SHELL_COMPONENT_UTILS_H__ +/* This is an EShell extension that handles migrating from older versions. */ -#include <bonobo/bonobo-ui-component.h> -#include <gtk/gtk.h> +#ifndef E_SHELL_MIGRATE_H +#define E_SHELL_MIGRATE_H -G_BEGIN_DECLS +#include <shell/e-shell-common.h> +#include <shell/e-shell.h> -typedef struct _EPixmap { - const gchar *path; - const gchar *name; - GtkIconSize size; - gchar *pixbuf; -} EPixmap; +/** + * E_SHELL_MIGRATE_ERROR: + * + * Error domain for migration operations. Errors in this domain will be + * from the #EShellMigrateError enumeration. See #GError for information + * on error domains. + **/ +#define E_SHELL_MIGRATE_ERROR \ + (e_shell_migrate_error_quark ()) -#define E_PIXMAP(path,name,size) { (path), (name), (size), NULL } -#define E_PIXMAP_END { NULL, NULL, 0, NULL } +G_BEGIN_DECLS -/* Takes an array of pixmaps, terminated by E_PIXMAP_END, and loads into uic */ -void e_pixmaps_update (BonoboUIComponent *uic, EPixmap *pixcache); +/* XXX Need more specific error codes? */ +typedef enum { + E_SHELL_MIGRATE_ERROR_FAILED +} EShellMigrateError; -gchar *e_get_activation_failure_msg (CORBA_Environment *ev); +gboolean e_shell_migrate_attempt (EShell *shell); +GQuark e_shell_migrate_error_quark (void); G_END_DECLS -#endif /* __EVOLUTION_SHELL_COMPONENT_UTILS_H__ */ +#endif /* E_SHELL_MIGRATE_H */ diff --git a/shell/e-shell-nm.c b/shell/e-shell-nm.c index 6a56d0f71b..c520600769 100644 --- a/shell/e-shell-nm.c +++ b/shell/e-shell-nm.c @@ -30,48 +30,40 @@ #include <string.h> #include <glib.h> #include <e-shell.h> -#include <Evolution.h> #include <dbus/dbus.h> #include <dbus/dbus-glib-lowlevel.h> #include <dbus/dbus-glib.h> #include <NetworkManager/NetworkManager.h> -gboolean e_shell_dbus_initialise (EShell *shell); +static DBusConnection *dbus_connection; -static DBusConnection *dbus_connection = NULL; +/* Forward Declaration */ +gboolean e_shell_dbus_initialize (EShell *shell); static gboolean -reinit_dbus (gpointer user_data) +reinit_dbus (EShell *shell) { - EShell *shell = user_data; - - if (e_shell_dbus_initialise (shell)) - return FALSE; - - /* keep trying to re-establish dbus connection */ - - return TRUE; + return !e_shell_dbus_initialize (shell); } static DBusHandlerResult e_shell_network_monitor (DBusConnection *connection G_GNUC_UNUSED, - DBusMessage *message, gpointer user_data) + DBusMessage *message, + gpointer user_data) { - const gchar *object; - EShell *shell = user_data; - GNOME_Evolution_ShellState shell_state; - EShellLineStatus line_status; DBusError error = DBUS_ERROR_INIT; + EShell *shell = user_data; + const gchar *path; guint32 state; - object = dbus_message_get_path (message); + path = dbus_message_get_path (message); if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") && - object && !strcmp (object, DBUS_PATH_LOCAL)) { + path != NULL && strcmp (path, DBUS_PATH_LOCAL) == 0) { dbus_connection_unref (dbus_connection); dbus_connection = NULL; - g_timeout_add_seconds (3, reinit_dbus, shell); + g_timeout_add_seconds (3, (GSourceFunc) reinit_dbus, shell); return DBUS_HANDLER_RESULT_HANDLED; } @@ -89,14 +81,16 @@ e_shell_network_monitor (DBusConnection *connection G_GNUC_UNUSED, return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - line_status = e_shell_get_line_status (shell); - - if (line_status == E_SHELL_LINE_STATUS_ONLINE && (state == NM_STATE_ASLEEP || state == NM_STATE_DISCONNECTED)) { - shell_state = GNOME_Evolution_FORCED_OFFLINE; - e_shell_set_line_status (shell, shell_state); - } else if (line_status == E_SHELL_LINE_STATUS_FORCED_OFFLINE && state == NM_STATE_CONNECTED) { - shell_state = GNOME_Evolution_USER_ONLINE; - e_shell_set_line_status (shell, shell_state); + switch (state) { + case NM_STATE_CONNECTED: + e_shell_set_network_available (shell, TRUE); + break; + case NM_STATE_ASLEEP: + case NM_STATE_DISCONNECTED: + e_shell_set_network_available (shell, FALSE); + break; + default: + break; } return DBUS_HANDLER_RESULT_HANDLED; @@ -109,32 +103,39 @@ check_initial_state (EShell *shell) guint32 state = -1; DBusError error = DBUS_ERROR_INIT; - message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "state"); + message = dbus_message_new_method_call ( + NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "state"); /* assuming this should be safe to call syncronously */ - response = dbus_connection_send_with_reply_and_block (dbus_connection, message, 100, &error); + response = dbus_connection_send_with_reply_and_block ( + dbus_connection, message, 100, &error); if (response) - dbus_message_get_args (response, &error, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID); + dbus_message_get_args ( + response, &error, DBUS_TYPE_UINT32, + &state, DBUS_TYPE_INVALID); else { - g_warning ("%s \n", error.message); + g_warning ("%s", error.message); dbus_error_free (&error); return; } - /* update the state only in the absence of network connection else let the old state prevail */ + /* Update the state only in the absence of a network connection, + * otherwise let the old state prevail. */ if (state == NM_STATE_DISCONNECTED) - e_shell_set_line_status (shell, GNOME_Evolution_FORCED_OFFLINE); + e_shell_set_network_available (shell, FALSE); dbus_message_unref (message); dbus_message_unref (response); } gboolean -e_shell_dbus_initialise (EShell *shell) +e_shell_dbus_initialize (EShell *shell) { DBusError error = DBUS_ERROR_INIT; + g_return_val_if_fail (E_IS_SHELL (shell), FALSE); + if (dbus_connection != NULL) return TRUE; diff --git a/shell/e-shell-settings-dialog.c b/shell/e-shell-settings-dialog.c deleted file mode 100644 index 9c7c32d1d5..0000000000 --- a/shell/e-shell-settings-dialog.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib/gi18n.h> - -#include "e-shell-settings-dialog.h" - -#include "e-corba-config-page.h" -#include <e-util/e-icon-factory.h> - -#include <bonobo/bonobo-widget.h> -#include <bonobo/bonobo-exception.h> - -#include <bonobo-activation/bonobo-activation.h> - -#include <stdlib.h> -#include <string.h> - -struct _EShellSettingsDialogPrivate { - GHashTable *types; -}; - -G_DEFINE_TYPE (EShellSettingsDialog, e_shell_settings_dialog, E_TYPE_MULTI_CONFIG_DIALOG) - - -/* FIXME ugly hack to work around that sizing of invisible widgets is broken - with Bonobo. */ - -static void -set_dialog_size (EShellSettingsDialog *dialog) -{ - PangoLayout *layout; - PangoContext *context; - PangoFontMetrics *metrics; - gint width, height; - - layout = gtk_widget_create_pango_layout (GTK_WIDGET (dialog), "M"); - context = pango_layout_get_context (layout); - metrics = pango_context_get_metrics (context, - gtk_widget_get_style (GTK_WIDGET (dialog))->font_desc, - pango_context_get_language (context)); - - pango_layout_get_pixel_size (layout, &width, NULL); - - width *= 60; - height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) - + pango_font_metrics_get_descent (metrics)) * 30; - - gtk_window_set_default_size((GtkWindow *)dialog, width, height); - g_object_unref (layout); - pango_font_metrics_unref (metrics); -} - - -/* Page handling. */ - -struct _Page { - gchar *title; - gchar *description; - GdkPixbuf *icon; - Bonobo_ActivationProperty *type; - gint priority; - EConfigPage *page_widget; -}; -typedef struct _Page Page; - -static Page * -page_new (const gchar *title, - const gchar *description, - GdkPixbuf *icon, - Bonobo_ActivationProperty *type, - gint priority, - EConfigPage *page_widget) -{ - Page *page; - - if (icon != NULL) - g_object_ref (icon); - - page = g_new (Page, 1); - page->title = g_strdup (title); - page->description = g_strdup (description); - page->icon = icon; - page->type = type; - page->priority = priority; - page->page_widget = page_widget; - - return page; -} - -static void -page_free (Page *page) -{ - g_free (page->title); - g_free (page->description); - - if (page->icon != NULL) - g_object_unref (page->icon); - - g_free (page); -} - -static gint -compare_page_func (gconstpointer a, - gconstpointer b) -{ - const Page *page_a; - const Page *page_b; - - page_a = (const Page *) a; - page_b = (const Page *) b; - - if (page_a->priority == page_b->priority) - return strcmp (page_a->title, page_b->title); - - return page_a->priority - page_b->priority; -} - -static GList * -sort_page_list (GList *list) -{ - return g_list_sort (list, compare_page_func); -} - -static void -load_pages (EShellSettingsDialog *dialog) -{ - EShellSettingsDialogPrivate *priv; - Bonobo_ServerInfoList *control_list; - const gchar * const *language_names; - CORBA_Environment ev; - GSList *languages = NULL; - GList *page_list; - GList *p; - gint i, j; - - priv = dialog->priv; - - CORBA_exception_init (&ev); - - control_list = bonobo_activation_query ("repo_ids.has('IDL:GNOME/Evolution/ConfigControl:" BASE_VERSION "')", NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION || control_list == NULL) { - g_warning ("Cannot load configuration pages -- %s", BONOBO_EX_REPOID (&ev)); - CORBA_exception_free (&ev); - return; - } - - CORBA_exception_free (&ev); - - language_names = g_get_language_names (); - while (*language_names != NULL) - languages = g_slist_append (languages, (gpointer)(*language_names++)); - - page_list = NULL; - for (i = 0; i < control_list->_length; i ++) { - CORBA_Object corba_object; - Bonobo_ServerInfo *info; - const gchar *title; - const gchar *description; - const gchar *icon_path; - const gchar *priority_string; - Bonobo_ActivationProperty *type; - gint priority; - GdkPixbuf *icon; - - CORBA_exception_init (&ev); - - info = & control_list->_buffer[i]; - - title = bonobo_server_info_prop_lookup (info, "evolution2:config_item:title", languages); - description = bonobo_server_info_prop_lookup (info, "evolution2:config_item:description", languages); - icon_path = bonobo_server_info_prop_lookup (info, "evolution2:config_item:icon_name", NULL); - type = bonobo_server_info_prop_find (info, "evolution2:config_item:type"); - priority_string = bonobo_server_info_prop_lookup (info, "evolution2:config_item:priority", NULL); - - if (icon_path == NULL) { - icon = NULL; - } else { - if (g_path_is_absolute (icon_path)) { - icon = gdk_pixbuf_new_from_file (icon_path, NULL); - } else { - icon = e_icon_factory_get_icon (icon_path, GTK_ICON_SIZE_DIALOG); - } - } - - if (type != NULL && type->v._d != Bonobo_ACTIVATION_P_STRINGV) - type = NULL; - if (priority_string == NULL) - priority = 0xffff; - else - priority = atoi (priority_string); - - corba_object = bonobo_activation_activate_from_id ((gchar *) info->iid, 0, NULL, &ev); - - if (! BONOBO_EX (&ev)) { - Page *page; - - page = page_new (title, description, icon, type, priority, - E_CONFIG_PAGE (e_corba_config_page_new_from_objref (corba_object))); - - page_list = g_list_prepend (page_list, page); - } else { - gchar *bonobo_ex_text = bonobo_exception_get_text (&ev); - g_warning ("Cannot activate %s -- %s", info->iid, bonobo_ex_text); - g_free (bonobo_ex_text); - } - - if (icon != NULL) - g_object_unref (icon); - - CORBA_exception_free (&ev); - } - g_slist_free(languages); - - page_list = sort_page_list (page_list); - for (p = page_list, i = 0; p != NULL; p = p->next, i++) { - Page *page; - - page = (Page *) p->data; - - e_multi_config_dialog_add_page (E_MULTI_CONFIG_DIALOG (dialog), - page->title, - page->description, - page->icon, - page->page_widget); - - if (page->type != NULL) { - Bonobo_StringList list = page->type->v._u.value_stringv; - - for (j = 0; j < list._length; j++) { - if (g_hash_table_lookup (priv->types, list._buffer[j]) == NULL) - g_hash_table_insert (priv->types, g_strdup (list._buffer[j]), - GINT_TO_POINTER (i)); - } - } - - page_free (page); - } - - g_list_free (page_list); - CORBA_free (control_list); -} - - -/* GtkObject methods. */ - -static void -impl_finalize (GObject *object) -{ - EShellSettingsDialog *dialog; - EShellSettingsDialogPrivate *priv; - - dialog = E_SHELL_SETTINGS_DIALOG (object); - priv = dialog->priv; - - g_hash_table_destroy (priv->types); - - g_free (priv); - - (* G_OBJECT_CLASS (e_shell_settings_dialog_parent_class)->finalize) (object); -} - - -static void -e_shell_settings_dialog_class_init (EShellSettingsDialogClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = impl_finalize; -} - -static void -e_shell_settings_dialog_init (EShellSettingsDialog *dialog) -{ - EShellSettingsDialogPrivate *priv; - - priv = g_new (EShellSettingsDialogPrivate, 1); - priv->types = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) NULL); - - dialog->priv = priv; - - load_pages (dialog); - set_dialog_size (dialog); - - gtk_window_set_title (GTK_WINDOW (dialog), _("Evolution Preferences")); - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); -} - - -GtkWidget * -e_shell_settings_dialog_new (void) -{ - EShellSettingsDialog *new; - - new = g_object_new (e_shell_settings_dialog_get_type (), NULL); - - return GTK_WIDGET (new); -} - -void -e_shell_settings_dialog_show_type (EShellSettingsDialog *dialog, const gchar *type) -{ - EShellSettingsDialogPrivate *priv; - gpointer key, value; - gint page; - - g_return_if_fail (dialog != NULL); - g_return_if_fail (E_IS_SHELL_SETTINGS_DIALOG (dialog)); - g_return_if_fail (type != NULL); - - priv = dialog->priv; - - if (!g_hash_table_lookup_extended (priv->types, type, &key, &value)) { - gchar *slash, *supertype; - - slash = strchr (type, '/'); - if (slash) { - supertype = g_strndup (type, slash - type); - value = g_hash_table_lookup (priv->types, type); - g_free (supertype); - } else - value = NULL; - } - page = GPOINTER_TO_INT (value); - - e_multi_config_dialog_show_page (E_MULTI_CONFIG_DIALOG (dialog), page); -} - diff --git a/shell/e-shell-settings-dialog.h b/shell/e-shell-settings-dialog.h deleted file mode 100644 index b39bc7beb3..0000000000 --- a/shell/e-shell-settings-dialog.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_SHELL_SETTINGS_DIALOG_H_ -#define _E_SHELL_SETTINGS_DIALOG_H_ - -#include "e-multi-config-dialog.h" - -G_BEGIN_DECLS - -#define E_TYPE_SHELL_SETTINGS_DIALOG (e_shell_settings_dialog_get_type ()) -#define E_SHELL_SETTINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SHELL_SETTINGS_DIALOG, EShellSettingsDialog)) -#define E_SHELL_SETTINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_SETTINGS_DIALOG, EShellSettingsDialogClass)) -#define E_IS_SHELL_SETTINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SHELL_SETTINGS_DIALOG)) -#define E_IS_SHELL_SETTINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_SETTINGS_DIALOG)) - - -typedef struct _EShellSettingsDialog EShellSettingsDialog; -typedef struct _EShellSettingsDialogPrivate EShellSettingsDialogPrivate; -typedef struct _EShellSettingsDialogClass EShellSettingsDialogClass; - -struct _EShellSettingsDialog { - EMultiConfigDialog parent; - - EShellSettingsDialogPrivate *priv; -}; - -struct _EShellSettingsDialogClass { - EMultiConfigDialogClass parent_class; -}; - - -GType e_shell_settings_dialog_get_type (void); -GtkWidget *e_shell_settings_dialog_new (void); -void e_shell_settings_dialog_show_type (EShellSettingsDialog *dialog, - const gchar *type); - -G_END_DECLS - -#endif /* _E_SHELL_SETTINGS_DIALOG_H_ */ diff --git a/shell/e-shell-settings.c b/shell/e-shell-settings.c new file mode 100644 index 0000000000..21cc855beb --- /dev/null +++ b/shell/e-shell-settings.c @@ -0,0 +1,702 @@ +/* + * e-shell-settings.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-settings.h" + +#include "e-util/gconf-bridge.h" + +#define E_SHELL_SETTINGS_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_SETTINGS, EShellSettingsPrivate)) + +struct _EShellSettingsPrivate { + GArray *value_array; + guint debug : 1; +}; + +static GList *instances; +static guint property_count; +static gpointer parent_class; + +static GParamSpec * +shell_settings_pspec_for_key (const gchar *property_name, + const gchar *gconf_key) +{ + GConfClient *client; + GConfEntry *entry; + GConfSchema *schema; + GConfValue *default_value; + GConfValueType value_type; + GParamSpec *pspec; + const gchar *bad_type; + const gchar *schema_name; + GError *error = NULL; + + client = gconf_client_get_default (); + + entry = gconf_client_get_entry (client, gconf_key, NULL, TRUE, &error); + if (error != NULL) { + g_error ("%s", error->message); + g_assert_not_reached (); + } + + schema_name = gconf_entry_get_schema_name (entry); + if (schema_name == NULL) { + g_error ("No schema for GConf key '%s'", gconf_key); + g_assert_not_reached (); + } + + schema = gconf_client_get_schema (client, schema_name, &error); + if (error != NULL) { + g_error ("%s", error->message); + g_assert_not_reached (); + } + + value_type = gconf_schema_get_type (schema); + default_value = gconf_schema_get_default_value (schema); + + /* If the schema does not specify a default value, make one up. */ + if (default_value == NULL) { + default_value = gconf_value_new (value_type); + + /* XXX This should NOT be necessary, but the GConfValue + * documentation claims it is. Bother. */ + switch (value_type) { + case GCONF_VALUE_STRING: + gconf_value_set_string (default_value, ""); + break; + + case GCONF_VALUE_INT: + gconf_value_set_int (default_value, 0); + break; + + case GCONF_VALUE_FLOAT: + gconf_value_set_float (default_value, 0.0); + break; + + case GCONF_VALUE_BOOL: + gconf_value_set_bool (default_value, FALSE); + break; + + default: + /* We'll fail in the next switch statement. */ + break; + } + } + + switch (value_type) { + case GCONF_VALUE_STRING: + pspec = g_param_spec_string ( + property_name, NULL, NULL, + gconf_value_get_string (default_value), + G_PARAM_READWRITE); + break; + + case GCONF_VALUE_INT: + pspec = g_param_spec_int ( + property_name, NULL, NULL, + G_MININT, G_MAXINT, + gconf_value_get_int (default_value), + G_PARAM_READWRITE); + break; + + case GCONF_VALUE_FLOAT: + pspec = g_param_spec_double ( + property_name, NULL, NULL, + -G_MAXDOUBLE, G_MAXDOUBLE, + gconf_value_get_float (default_value), + G_PARAM_READWRITE); + break; + + case GCONF_VALUE_BOOL: + pspec = g_param_spec_boolean ( + property_name, NULL, NULL, + gconf_value_get_bool (default_value), + G_PARAM_READWRITE); + break; + + case GCONF_VALUE_SCHEMA: + bad_type = "schema"; + goto fail; + + case GCONF_VALUE_LIST: + bad_type = "list"; + goto fail; + + case GCONF_VALUE_PAIR: + bad_type = "pair"; + goto fail; + + default: + bad_type = "invalid"; + goto fail; + } + + gconf_value_free (default_value); + + return pspec; + +fail: + g_error ( + "Unable to create EShellSettings property for " + "GConf key '%s' of type '%s'", gconf_key, bad_type); + g_assert_not_reached (); +} + +static void +shell_settings_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EShellSettingsPrivate *priv; + GValue *dest_value; + + priv = E_SHELL_SETTINGS_GET_PRIVATE (object); + + dest_value = &g_array_index ( + priv->value_array, GValue, property_id - 1); + + g_value_copy (value, dest_value); + g_object_notify (object, pspec->name); + + if (priv->debug) { + gchar *contents; + + contents = g_strdup_value_contents (value); + g_debug ( + "Setting '%s' set to '%s' (%s)", + pspec->name, contents, G_VALUE_TYPE_NAME (value)); + g_free (contents); + } +} + +static void +shell_settings_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EShellSettingsPrivate *priv; + GValue *src_value; + + priv = E_SHELL_SETTINGS_GET_PRIVATE (object); + + src_value = &g_array_index ( + priv->value_array, GValue, property_id - 1); + + g_value_copy (src_value, value); +} + +static void +shell_settings_finalize (GObject *object) +{ + EShellSettingsPrivate *priv; + guint ii; + + priv = E_SHELL_SETTINGS_GET_PRIVATE (object); + + for (ii = 0; ii < priv->value_array->len; ii++) + g_value_unset (&g_array_index (priv->value_array, GValue, ii)); + + g_array_free (priv->value_array, TRUE); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_settings_class_init (EShellSettingsClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellSettingsPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_settings_set_property; + object_class->get_property = shell_settings_get_property; + object_class->finalize = shell_settings_finalize; +} + +static void +shell_settings_init (EShellSettings *shell_settings, + GObjectClass *object_class) +{ + GArray *value_array; + GParamSpec **pspecs; + guint ii; + + instances = g_list_prepend (instances, shell_settings); + + value_array = g_array_new (FALSE, TRUE, sizeof (GValue)); + g_array_set_size (value_array, property_count); + + shell_settings->priv = E_SHELL_SETTINGS_GET_PRIVATE (shell_settings); + shell_settings->priv->value_array = value_array; + + g_object_freeze_notify (G_OBJECT (shell_settings)); + + pspecs = g_object_class_list_properties (object_class, NULL); + for (ii = 0; ii < property_count; ii++) { + GParamSpec *pspec = pspecs[ii]; + GValue *value; + + value = &g_array_index (value_array, GValue, ii); + g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_param_value_set_default (pspec, value); + g_object_notify (G_OBJECT (shell_settings), pspec->name); + + /* FIXME Need to bind those properties that have + * associated GConf keys. */ + } + g_free (pspecs); + + g_object_thaw_notify (G_OBJECT (shell_settings)); +} + +GType +e_shell_settings_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EShellSettingsClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_settings_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellSettings), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_settings_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EShellSettings", &type_info, 0); + } + + return type; +} + +/** + * e_shell_settings_install_property: + * @pspec: a #GParamSpec + * + * Installs a new #EShellSettings class property from @pspec. + * This is usually done during initialization of an #EShellBackend + * or other dynamically loaded entity. + **/ +void +e_shell_settings_install_property (GParamSpec *pspec) +{ + static GObjectClass *class = NULL; + GList *iter, *next; + + g_return_if_fail (G_IS_PARAM_SPEC (pspec)); + + if (G_UNLIKELY (class == NULL)) + class = g_type_class_ref (E_TYPE_SHELL_SETTINGS); + + if (g_object_class_find_property (class, pspec->name) != NULL) { + g_warning ( + "Settings property \"%s\" already exists", + pspec->name); + return; + } + + for (iter = instances; iter != NULL; iter = iter->next) + g_object_freeze_notify (iter->data); + + g_object_class_install_property (class, ++property_count, pspec); + + for (iter = instances; iter != NULL; iter = iter->next) { + EShellSettings *shell_settings; + GArray *value_array; + GValue *value; + + shell_settings = E_SHELL_SETTINGS (iter->data); + value_array = shell_settings->priv->value_array; + g_array_set_size (value_array, property_count); + + value = &g_array_index ( + value_array, GValue, property_count - 1); + g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec)); + g_param_value_set_default (pspec, value); + g_object_notify (G_OBJECT (shell_settings), pspec->name); + } + + for (iter = instances; iter != NULL; iter = next) { + next = iter->next; + g_object_thaw_notify (iter->data); + } +} + +/** + * e_shell_settings_install_property_for_key: + * @property_name: the name of the property to install + * @gconf_key: the GConf key to bind the property to + * + * Installs a new #EShellSettings class property by examining the + * GConf schema for @gconf_key to determine the appropriate type and + * default value. This is usually done during initialization of an + * #EShellBackend of other dynamically loaded entity. + * + * After the class property is installed, all #EShellSettings instances + * are bound to @gconf_key, causing @property_name and @gconf_key to have + * the same value at all times. + **/ +void +e_shell_settings_install_property_for_key (const gchar *property_name, + const gchar *gconf_key) +{ + GParamSpec *pspec; + GList *iter, *next; + + g_return_if_fail (property_name != NULL); + g_return_if_fail (gconf_key != NULL); + + pspec = shell_settings_pspec_for_key (property_name, gconf_key); + e_shell_settings_install_property (pspec); + + for (iter = instances; iter != NULL; iter = iter->next) + g_object_freeze_notify (iter->data); + + for (iter = instances; iter != NULL; iter = iter->next) { + EShellSettings *shell_settings; + + shell_settings = E_SHELL_SETTINGS (iter->data); + + gconf_bridge_bind_property ( + gconf_bridge_get (), gconf_key, + G_OBJECT (shell_settings), property_name); + } + + for (iter = instances; iter != NULL; iter = next) { + next = iter->next; + g_object_thaw_notify (iter->data); + } +} + +/** + * e_shell_settings_enable_debug: + * @shell_settings: an #EShellSettings + * + * Print a debug message to standard output when a property value changes. + **/ +void +e_shell_settings_enable_debug (EShellSettings *shell_settings) +{ + g_return_if_fail (E_IS_SHELL_SETTINGS (shell_settings)); + + shell_settings->priv->debug = TRUE; +} + +/** + * e_shell_settings_get_boolean: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * + * Return the contents of an #EShellSettings property of type + * #G_TYPE_BOOLEAN. + * + * Returns: boolean contents of @property_name + **/ +gboolean +e_shell_settings_get_boolean (EShellSettings *shell_settings, + const gchar *property_name) +{ + GObject *object; + GValue value = { 0, }; + gboolean v_boolean; + + g_return_val_if_fail (E_IS_SHELL_SETTINGS (shell_settings), FALSE); + g_return_val_if_fail (property_name != NULL, FALSE); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_BOOLEAN); + g_object_get_property (object, property_name, &value); + v_boolean = g_value_get_boolean (&value); + g_value_unset (&value); + + return v_boolean; +} + +/** + * e_shell_settings_set_boolean: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * @v_boolean: boolean value to be set + * + * Sets the contents of an #EShellSettings property of type #G_TYPE_BOOLEAN + * to @v_boolean. If @property_name is bound to a GConf key, the GConf key + * will also be set to @v_boolean. + **/ +void +e_shell_settings_set_boolean (EShellSettings *shell_settings, + const gchar *property_name, + gboolean v_boolean) +{ + GObject *object; + GValue value = { 0, }; + + g_return_if_fail (E_IS_SHELL_SETTINGS (shell_settings)); + g_return_if_fail (property_name != NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, v_boolean); + g_object_set_property (object, property_name, &value); + g_value_unset (&value); +} + +/** + * e_shell_settings_get_int: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * + * Returns the contents of an #EShellSettings property of type + * #G_TYPE_INT. + * + * Returns: integer contents of @property_name + **/ +gint +e_shell_settings_get_int (EShellSettings *shell_settings, + const gchar *property_name) +{ + GObject *object; + GValue value = { 0, }; + gint v_int; + + g_return_val_if_fail (E_IS_SHELL_SETTINGS (shell_settings), 0); + g_return_val_if_fail (property_name != NULL, 0); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_INT); + g_object_get_property (object, property_name, &value); + v_int = g_value_get_int (&value); + g_value_unset (&value); + + return v_int; +} + +/** + * e_shell_settings_set_int: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * @v_int: integer value to be set + * + * Sets the contents of an #EShellSettings property of type #G_TYPE_INT + * to @v_int. If @property_name is bound to a GConf key, the GConf key + * will also be set to @v_int. + **/ +void +e_shell_settings_set_int (EShellSettings *shell_settings, + const gchar *property_name, + gint v_int) +{ + GObject *object; + GValue value = { 0, }; + + g_return_if_fail (E_IS_SHELL_SETTINGS (shell_settings)); + g_return_if_fail (property_name != NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, v_int); + g_object_set_property (object, property_name, &value); + g_value_unset (&value); +} + +/** + * e_shell_settings_get_string: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * + * Returns the contents of an #EShellSettings property of type + * #G_TYPE_STRING. The returned string should be freed using g_free(). + * + * Returns: string contents of @property_name + **/ +gchar * +e_shell_settings_get_string (EShellSettings *shell_settings, + const gchar *property_name) +{ + GObject *object; + GValue value = { 0, }; + gchar *v_string; + + g_return_val_if_fail (E_IS_SHELL_SETTINGS (shell_settings), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_STRING); + g_object_get_property (object, property_name, &value); + v_string = g_value_dup_string (&value); + g_value_unset (&value); + + return v_string; +} + +/** + * e_shell_settings_set_string: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * @v_string: string to be set + * + * Sets the contents of an #EShellSettings property of type #G_TYPE_STRING + * to @v_string. If @property_name is bound to a GConf key, the GConf key + * will also be set to @v_string. + **/ +void +e_shell_settings_set_string (EShellSettings *shell_settings, + const gchar *property_name, + const gchar *v_string) +{ + GObject *object; + GValue value = { 0, }; + + g_return_if_fail (E_IS_SHELL_SETTINGS (shell_settings)); + g_return_if_fail (property_name != NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, v_string); + g_object_set_property (object, property_name, &value); + g_value_unset (&value); +} + +/** + * e_shell_settings_get_object: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * + * Returns the contents of an #EShellSettings property of type + * #G_TYPE_OBJECT. The caller owns the reference to the returned + * object, and should call g_object_unref() when finished with it. + * + * Returns: a new reference to the object under @property_name + **/ +gpointer +e_shell_settings_get_object (EShellSettings *shell_settings, + const gchar *property_name) +{ + GObject *object; + GValue value = { 0, }; + gpointer v_object; + + g_return_val_if_fail (E_IS_SHELL_SETTINGS (shell_settings), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_OBJECT); + g_object_get_property (object, property_name, &value); + v_object = g_value_dup_object (&value); + g_value_unset (&value); + + return v_object; +} + +/** + * e_shell_settings_set_object: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * @v_object: object to be set + * + * Sets the contents of an #EShellSettings property of type #G_TYPE_OBJECT + * to @v_object. + **/ +void +e_shell_settings_set_object (EShellSettings *shell_settings, + const gchar *property_name, + gpointer v_object) +{ + GObject *object; + GValue value = { 0, }; + + g_return_if_fail (E_IS_SHELL_SETTINGS (shell_settings)); + g_return_if_fail (property_name != NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_OBJECT); + g_value_set_object (&value, v_object); + g_object_set_property (object, property_name, &value); + g_value_unset (&value); +} + +/** + * e_shell_settings_get_pointer: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * + * Returns the contents of an #EShellSettings property of type + * #G_TYPE_POINTER. + * + * Returns: pointer contents of @property_name + **/ +gpointer +e_shell_settings_get_pointer (EShellSettings *shell_settings, + const gchar *property_name) +{ + GObject *object; + GValue value = { 0, }; + gpointer v_pointer; + + g_return_val_if_fail (E_IS_SHELL_SETTINGS (shell_settings), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_POINTER); + g_object_get_property (object, property_name, &value); + v_pointer = g_value_get_pointer (&value); + g_value_unset (&value); + + return v_pointer; +} + +/** + * e_shell_settings_set_pointer: + * @shell_settings: an #EShellSettings + * @property_name: an installed property name + * @v_pointer: pointer to be set + * + * Sets the contents of an #EShellSettings property of type #G_TYPE_POINTER + * to @v_pointer. + **/ +void +e_shell_settings_set_pointer (EShellSettings *shell_settings, + const gchar *property_name, + gpointer v_pointer) +{ + GObject *object; + GValue value = { 0, }; + + g_return_if_fail (E_IS_SHELL_SETTINGS (shell_settings)); + g_return_if_fail (property_name != NULL); + + object = G_OBJECT (shell_settings); + g_value_init (&value, G_TYPE_POINTER); + g_value_set_pointer (&value, v_pointer); + g_object_set_property (object, property_name, &value); + g_value_unset (&value); +} diff --git a/shell/e-shell-settings.h b/shell/e-shell-settings.h new file mode 100644 index 0000000000..c1ac497dec --- /dev/null +++ b/shell/e-shell-settings.h @@ -0,0 +1,114 @@ +/* + * e-shell-settings.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-shell-settings + * @short_description: settings management + * @include: shell/e-shell-settings.h + **/ + +#ifndef E_SHELL_SETTINGS_H +#define E_SHELL_SETTINGS_H + +#include <shell/e-shell-common.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_SETTINGS \ + (e_shell_settings_get_type ()) +#define E_SHELL_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_SETTINGS, EShellSettings)) +#define E_SHELL_SETTINGS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_SETTINGS, EShellSettingsClass)) +#define E_IS_SHELL_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_SETTINGS)) +#define E_IS_SHELL_SETTINGS_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SHELL_SETTINGS)) +#define E_SHELL_SETTINGS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_SETTINGS, EShellSettingsClass)) + +G_BEGIN_DECLS + +typedef struct _EShellSettings EShellSettings; +typedef struct _EShellSettingsClass EShellSettingsClass; +typedef struct _EShellSettingsPrivate EShellSettingsPrivate; + +/** + * EShellSettings: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EShellSettings { + GObject parent; + EShellSettingsPrivate *priv; +}; + +struct _EShellSettingsClass { + GObjectClass parent_class; +}; + +GType e_shell_settings_get_type (void); +void e_shell_settings_install_property + (GParamSpec *pspec); +void e_shell_settings_install_property_for_key + (const gchar *property_name, + const gchar *gconf_key); +void e_shell_settings_enable_debug (EShellSettings *shell_settings); + +/* Getters and setters for common EShellSettings property types. + * These are more convenient than g_object_get() / g_object_set(). + * Add more types as needed. If GObject ever adds similar functions, + * kill these. */ + +gboolean e_shell_settings_get_boolean (EShellSettings *shell_settings, + const gchar *property_name); +void e_shell_settings_set_boolean (EShellSettings *shell_settings, + const gchar *property_name, + gboolean v_boolean); +gint e_shell_settings_get_int (EShellSettings *shell_settings, + const gchar *property_name); +void e_shell_settings_set_int (EShellSettings *shell_settings, + const gchar *property_name, + gint v_int); +gchar * e_shell_settings_get_string (EShellSettings *shell_settings, + const gchar *property_name); +void e_shell_settings_set_string (EShellSettings *shell_settings, + const gchar *property_name, + const gchar *v_string); +gpointer e_shell_settings_get_object (EShellSettings *shell_settings, + const gchar *property_name); +void e_shell_settings_set_object (EShellSettings *shell_settings, + const gchar *property_name, + gpointer v_object); +gpointer e_shell_settings_get_pointer (EShellSettings *shell_settings, + const gchar *property_name); +void e_shell_settings_set_pointer (EShellSettings *shell_settings, + const gchar *property_name, + gpointer v_pointer); + +G_END_DECLS + +#endif /* E_SHELL_SETTINGS_H */ diff --git a/shell/e-shell-sidebar.c b/shell/e-shell-sidebar.c new file mode 100644 index 0000000000..7763e64918 --- /dev/null +++ b/shell/e-shell-sidebar.c @@ -0,0 +1,683 @@ +/* + * e-shell-sidebar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-sidebar.h" + +#include <e-shell-view.h> + +#define E_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebarPrivate)) + +struct _EShellSidebarPrivate { + + gpointer shell_view; /* weak pointer */ + + GtkWidget *event_box; + GtkWidget *image; + GtkWidget *primary_label; + GtkWidget *secondary_label; + gchar *primary_text; + gchar *secondary_text; +}; + +enum { + PROP_0, + PROP_ICON_NAME, + PROP_PRIMARY_TEXT, + PROP_SECONDARY_TEXT, + PROP_SHELL_VIEW +}; + +static gpointer parent_class; + +static void +shell_sidebar_set_shell_view (EShellSidebar *shell_sidebar, + EShellView *shell_view) +{ + g_return_if_fail (shell_sidebar->priv->shell_view == NULL); + + shell_sidebar->priv->shell_view = shell_view; + + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &shell_sidebar->priv->shell_view); +} + +static void +shell_sidebar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ICON_NAME: + e_shell_sidebar_set_icon_name ( + E_SHELL_SIDEBAR (object), + g_value_get_string (value)); + return; + + case PROP_PRIMARY_TEXT: + e_shell_sidebar_set_primary_text ( + E_SHELL_SIDEBAR (object), + g_value_get_string (value)); + return; + + case PROP_SECONDARY_TEXT: + e_shell_sidebar_set_secondary_text ( + E_SHELL_SIDEBAR (object), + g_value_get_string (value)); + return; + + case PROP_SHELL_VIEW: + shell_sidebar_set_shell_view ( + E_SHELL_SIDEBAR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ICON_NAME: + g_value_set_string ( + value, e_shell_sidebar_get_icon_name ( + E_SHELL_SIDEBAR (object))); + return; + + case PROP_PRIMARY_TEXT: + g_value_set_string ( + value, e_shell_sidebar_get_primary_text ( + E_SHELL_SIDEBAR (object))); + return; + + case PROP_SECONDARY_TEXT: + g_value_set_string ( + value, e_shell_sidebar_get_secondary_text ( + E_SHELL_SIDEBAR (object))); + return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_shell_sidebar_get_shell_view ( + E_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_sidebar_dispose (GObject *object) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), &priv->shell_view); + priv->shell_view = NULL; + } + + if (priv->image != NULL) { + g_object_unref (priv->image); + priv->image = NULL; + } + + if (priv->event_box != NULL) { + g_object_unref (priv->event_box); + priv->event_box = NULL; + } + + if (priv->primary_label != NULL) { + g_object_unref (priv->primary_label); + priv->primary_label = NULL; + } + + if (priv->secondary_label != NULL) { + g_object_unref (priv->secondary_label); + priv->secondary_label = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_sidebar_finalize (GObject *object) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_free (priv->primary_text); + g_free (priv->secondary_text); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_sidebar_constructed (GObject *object) +{ + EShellView *shell_view; + EShellSidebar *shell_sidebar; + GtkSizeGroup *size_group; + GtkAction *action; + GtkWidget *container; + GtkWidget *widget; + gchar *label; + gchar *icon_name; + + shell_sidebar = E_SHELL_SIDEBAR (object); + shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); + size_group = e_shell_view_get_size_group (shell_view); + action = e_shell_view_get_action (shell_view); + + widget = shell_sidebar->priv->event_box; + gtk_size_group_add_widget (size_group, widget); + + container = widget; + + widget = gtk_hbox_new (FALSE, 6); + gtk_container_set_border_width (GTK_CONTAINER (widget), 6); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + shell_sidebar->priv->image = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + shell_sidebar->priv->primary_label = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + shell_sidebar->priv->secondary_label = g_object_ref (widget); + gtk_widget_show (widget); + + g_object_get (action, "icon-name", &icon_name, NULL); + e_shell_sidebar_set_icon_name (shell_sidebar, icon_name); + g_free (icon_name); + + g_object_get (action, "label", &label, NULL); + e_shell_sidebar_set_primary_text (shell_sidebar, label); + g_free (label); +} + +static void +shell_sidebar_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EShellSidebarPrivate *priv; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (widget); + + requisition->width = 0; + requisition->height = 0; + + child = gtk_bin_get_child (GTK_BIN (widget)); + gtk_widget_size_request (child, requisition); + + child = priv->event_box; + gtk_widget_size_request (child, &child_requisition); + requisition->width = MAX (requisition->width, child_requisition.width); + requisition->height += child_requisition.height; +} + +static void +shell_sidebar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EShellSidebarPrivate *priv; + GtkAllocation child_allocation; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (widget); + + widget->allocation = *allocation; + + child = priv->event_box; + gtk_widget_size_request (child, &child_requisition); + + child_allocation.x = allocation->x; + child_allocation.y = allocation->y; + child_allocation.width = allocation->width; + child_allocation.height = child_requisition.height; + + gtk_widget_size_allocate (child, &child_allocation); + + child_allocation.y += child_requisition.height; + child_allocation.height = + allocation->height - child_requisition.height; + + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_size_allocate (child, &child_allocation); +} + +static void +shell_sidebar_remove (GtkContainer *container, + GtkWidget *widget) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (container); + + /* Look in the internal widgets first. */ + + if (widget == priv->event_box) { + gtk_widget_unparent (priv->event_box); + gtk_widget_queue_resize (GTK_WIDGET (container)); + return; + } + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); +} + +static void +shell_sidebar_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (container); + + if (include_internals) + callback (priv->event_box, callback_data); + + /* Chain up to parent's forall() method. */ + GTK_CONTAINER_CLASS (parent_class)->forall ( + container, include_internals, callback, callback_data); +} + +static void +shell_sidebar_class_init (EShellSidebarClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_sidebar_set_property; + object_class->get_property = shell_sidebar_get_property; + object_class->dispose = shell_sidebar_dispose; + object_class->finalize = shell_sidebar_finalize; + object_class->constructed = shell_sidebar_constructed; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->size_request = shell_sidebar_size_request; + widget_class->size_allocate = shell_sidebar_size_allocate; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = shell_sidebar_remove; + container_class->forall = shell_sidebar_forall; + + /** + * EShellSidebar:icon-name + * + * The named icon is displayed at the top of the sidebar. + */ + g_object_class_install_property ( + object_class, + PROP_ICON_NAME, + g_param_spec_string ( + "icon-name", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + /** + * EShellSidebar:primary-text + * + * The primary text is displayed in bold at the top of the sidebar. + **/ + g_object_class_install_property ( + object_class, + PROP_PRIMARY_TEXT, + g_param_spec_string ( + "primary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + /** + * EShellSidebar:secondary-text + * + * The secondary text is displayed in a smaller font at the top of + * the sidebar. + **/ + g_object_class_install_property ( + object_class, + PROP_SECONDARY_TEXT, + g_param_spec_string ( + "secondary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + /** + * EShellSidebar:shell-view + * + * The #EShellView to which the sidebar widget belongs. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + NULL, + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +shell_sidebar_init (EShellSidebar *shell_sidebar) +{ + GtkStyle *style; + GtkWidget *widget; + const GdkColor *color; + + shell_sidebar->priv = E_SHELL_SIDEBAR_GET_PRIVATE (shell_sidebar); + + GTK_WIDGET_SET_FLAGS (shell_sidebar, GTK_NO_WINDOW); + + widget = gtk_event_box_new (); + style = gtk_widget_get_style (widget); + color = &style->bg[GTK_STATE_ACTIVE]; + gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, color); + gtk_widget_set_parent (widget, GTK_WIDGET (shell_sidebar)); + shell_sidebar->priv->event_box = g_object_ref (widget); + gtk_widget_show (widget); + + /* Finish initialization once we have a shell view. */ +} + +GType +e_shell_sidebar_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_sidebar_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_BIN, "EShellSidebar", &type_info, 0); + } + + return type; +} + +/** + * e_shell_sidebar_new: + * @shell_view: an #EShellView + * + * Creates a new #EShellSidebar instance belonging to @shell_view. + * + * Returns: a new #EShellSidebar instance + **/ +GtkWidget * +e_shell_sidebar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_SHELL_SIDEBAR, + "shell-view", shell_view, NULL); +} + +/** + * e_shell_sidebar_check_state: + * @shell_sidebar: an #EShellSidebar + * + * #EShellSidebar subclasses should implement the + * <structfield>check_state</structfield> method in #EShellSidebarClass + * to return a set of flags describing the current sidebar selection. + * Subclasses are responsible for defining their own flags. This is + * primarily used to assist shell views with updating actions (see + * e_shell_view_update_actions()). + * + * Returns: a set of flags describing the current @shell_sidebar selection + **/ +guint32 +e_shell_sidebar_check_state (EShellSidebar *shell_sidebar) +{ + EShellSidebarClass *shell_sidebar_class; + + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), 0); + + shell_sidebar_class = E_SHELL_SIDEBAR_GET_CLASS (shell_sidebar); + g_return_val_if_fail (shell_sidebar_class->check_state != NULL, 0); + + return shell_sidebar_class->check_state (shell_sidebar); +} + +/** + * e_shell_sidebar_get_shell_view: + * @shell_sidebar: an #EShellSidebar + * + * Returns the #EShellView that was passed to e_shell_sidebar_new(). + * + * Returns: the #EShellView to which @shell_sidebar belongs + **/ +EShellView * +e_shell_sidebar_get_shell_view (EShellSidebar *shell_sidebar) +{ + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return E_SHELL_VIEW (shell_sidebar->priv->shell_view); +} + +/** + * e_shell_sidebar_get_icon_name: + * @shell_sidebar: an #EShellSidebar + * + * Returns the icon name displayed at the top of the sidebar. + * + * Returns: the icon name for @shell_sidebar + **/ +const gchar * +e_shell_sidebar_get_icon_name (EShellSidebar *shell_sidebar) +{ + GtkImage *image; + const gchar *icon_name; + + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + image = GTK_IMAGE (shell_sidebar->priv->image); + gtk_image_get_icon_name (image, &icon_name, NULL); + + return icon_name; +} + +/** + * e_shell_sidebar_set_icon_name: + * @shell_sidebar: an #EShellSidebar + * @icon_name: a themed icon name + * + * Sets the icon name displayed at the top of the sidebar. + **/ +void +e_shell_sidebar_set_icon_name (EShellSidebar *shell_sidebar, + const gchar *icon_name) +{ + GtkImage *image; + + g_return_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar)); + + image = GTK_IMAGE (shell_sidebar->priv->image); + gtk_image_set_from_icon_name (image, icon_name, GTK_ICON_SIZE_MENU); + + g_object_notify (G_OBJECT (shell_sidebar), "icon-name"); +} + +/** + * e_shell_sidebar_get_primary_text: + * @shell_sidebar: an #EShellSidebar + * + * Returns the primary text for @shell_sidebar. + * + * The primary text is displayed in bold at the top of the sidebar. It + * defaults to the shell view's label (as seen on the switcher button), + * but typically shows the name of the selected item in the sidebar. + * + * Returns: the primary text for @shell_sidebar + **/ +const gchar * +e_shell_sidebar_get_primary_text (EShellSidebar *shell_sidebar) +{ + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return shell_sidebar->priv->primary_text; +} + +/** + * e_shell_sidebar_set_primary_text: + * @shell_sidebar: an #EShellSidebar + * @primary_text: text to be displayed in a bold font + * + * Sets the primary text for @shell_sidebar. + * + * The primary text is displayed in bold at the top of the sidebar. It + * defaults to the shell view's label (as seen on the switcher button), + * but typically shows the name of the selected item in the sidebar. + **/ +void +e_shell_sidebar_set_primary_text (EShellSidebar *shell_sidebar, + const gchar *primary_text) +{ + GtkLabel *label; + gchar *markup; + + g_return_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar)); + + g_free (shell_sidebar->priv->primary_text); + shell_sidebar->priv->primary_text = g_strdup (primary_text); + + if (primary_text == NULL) + primary_text = ""; + + label = GTK_LABEL (shell_sidebar->priv->primary_label); + markup = g_markup_printf_escaped ("<b>%s</b>", primary_text); + gtk_label_set_markup (label, markup); + g_free (markup); + + gtk_widget_queue_resize (GTK_WIDGET (shell_sidebar)); + g_object_notify (G_OBJECT (shell_sidebar), "primary-text"); +} + +/** + * e_shell_sidebar_get_secondary_text: + * @shell_sidebar: an #EShellSidebar + * + * Returns the secondary text for @shell_sidebar. + * + * The secondary text is displayed in a smaller font at the top of the + * sidebar. It typically shows information about the contents of the + * selected sidebar item, such as total number of items, number of + * selected items, etc. + * + * Returns: the secondary text for @shell_sidebar + **/ +const gchar * +e_shell_sidebar_get_secondary_text (EShellSidebar *shell_sidebar) +{ + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return shell_sidebar->priv->secondary_text; +} + +/** + * e_shell_sidebar_set_secondary_text: + * @shell_sidebar: an #EShellSidebar + * @secondary_text: text to be displayed in a smaller font + * + * Sets the secondary text for @shell_sidebar. + * + * The secondary text is displayed in a smaller font at the top of the + * sidebar. It typically shows information about the contents of the + * selected sidebar item, such as total number of items, number of + * selected items, etc. + **/ +void +e_shell_sidebar_set_secondary_text (EShellSidebar *shell_sidebar, + const gchar *secondary_text) +{ + GtkLabel *label; + gchar *markup; + + g_return_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar)); + + g_free (shell_sidebar->priv->secondary_text); + shell_sidebar->priv->secondary_text = g_strdup (secondary_text); + + if (secondary_text == NULL) + secondary_text = ""; + + label = GTK_LABEL (shell_sidebar->priv->secondary_label); + markup = g_markup_printf_escaped ("<small>%s</small>", secondary_text); + gtk_label_set_markup (label, markup); + g_free (markup); + + gtk_widget_queue_resize (GTK_WIDGET (shell_sidebar)); + g_object_notify (G_OBJECT (shell_sidebar), "secondary-text"); +} diff --git a/shell/e-shell-sidebar.h b/shell/e-shell-sidebar.h new file mode 100644 index 0000000000..5999aa9de2 --- /dev/null +++ b/shell/e-shell-sidebar.h @@ -0,0 +1,97 @@ +/* + * e-shell-sidebar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-shell-sidebar + * @short_description: the left side of the main window + * @include: shell/e-shell-sidebar.h + **/ + +#ifndef E_SHELL_SIDEBAR_H +#define E_SHELL_SIDEBAR_H + +#include <shell/e-shell-common.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_SIDEBAR \ + (e_shell_sidebar_get_type ()) +#define E_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebar)) +#define E_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_SIDEBAR, EShellSidebarClass)) +#define E_IS_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_SIDEBAR)) +#define E_IS_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_SIDEBAR)) +#define E_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebarClass)) + +G_BEGIN_DECLS + +/* Avoid including <e-shell-view.h>, because it includes us! */ +struct _EShellView; + +typedef struct _EShellSidebar EShellSidebar; +typedef struct _EShellSidebarClass EShellSidebarClass; +typedef struct _EShellSidebarPrivate EShellSidebarPrivate; + +/** + * EShellSidebar: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EShellSidebar { + GtkBin parent; + EShellSidebarPrivate *priv; +}; + +struct _EShellSidebarClass { + GtkBinClass parent_class; + + guint32 (*check_state) (EShellSidebar *shell_sidebar); +}; + +GType e_shell_sidebar_get_type (void); +GtkWidget * e_shell_sidebar_new (struct _EShellView *shell_view); +guint32 e_shell_sidebar_check_state (EShellSidebar *shell_sidebar); +struct _EShellView * + e_shell_sidebar_get_shell_view (EShellSidebar *shell_sidebar); +const gchar * e_shell_sidebar_get_icon_name (EShellSidebar *shell_sidebar); +void e_shell_sidebar_set_icon_name (EShellSidebar *shell_sidebar, + const gchar *icon_name); +const gchar * e_shell_sidebar_get_primary_text(EShellSidebar *shell_sidebar); +void e_shell_sidebar_set_primary_text(EShellSidebar *shell_sidebar, + const gchar *primary_text); +const gchar * e_shell_sidebar_get_secondary_text + (EShellSidebar *shell_sidebar); +void e_shell_sidebar_set_secondary_text + (EShellSidebar *shell_sidebar, + const gchar *secondary_text); + +G_END_DECLS + +#endif /* E_SHELL_SIDEBAR_H */ diff --git a/shell/e-shell-switcher.c b/shell/e-shell-switcher.c new file mode 100644 index 0000000000..e1ed8606e5 --- /dev/null +++ b/shell/e-shell-switcher.c @@ -0,0 +1,700 @@ +/* + * e-shell-switcher.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-switcher.h" + +#include <glib/gi18n.h> + +#define E_SHELL_SWITCHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcherPrivate)) + +#define H_PADDING 6 +#define V_PADDING 6 + +struct _EShellSwitcherPrivate { + GList *proxies; + gboolean style_set; + GtkToolbarStyle style; + GtkSettings *settings; + gulong settings_handler_id; + gboolean toolbar_visible; +}; + +enum { + PROP_0, + PROP_TOOLBAR_STYLE, + PROP_TOOLBAR_VISIBLE +}; + +enum { + STYLE_CHANGED, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static gint +shell_switcher_layout_actions (EShellSwitcher *switcher) +{ + GtkAllocation *allocation; + gint num_btns = g_list_length (switcher->priv->proxies), btns_per_row; + GList **rows, *p; + gboolean icons_only; + gint row_number; + gint max_width = 0; + gint max_height = 0; + gint row_last; + gint x, y; + gint i; + + allocation = >K_WIDGET (switcher)->allocation; + y = allocation->y + allocation->height; + + if (num_btns == 0) + return allocation->height; + + icons_only = (switcher->priv->style == GTK_TOOLBAR_ICONS); + + /* Figure out the max width and height. */ + for (p = switcher->priv->proxies; p != NULL; p = p->next) { + GtkWidget *widget = p->data; + GtkRequisition requisition; + + gtk_widget_size_request (widget, &requisition); + max_height = MAX (max_height, requisition.height); + max_width = MAX (max_width, requisition.width); + } + + /* Figure out how many rows and columns we'll use. */ + btns_per_row = MAX (1, allocation->width / (max_width + H_PADDING)); + if (!icons_only) { + /* If using text buttons, we want to try to have a + * completely filled-in grid, but if we can't, we want + * the odd row to have just a single button. */ + while (num_btns % btns_per_row > 1) + btns_per_row--; + } + + /* Assign buttons to rows. */ + rows = g_new0 (GList *, num_btns / btns_per_row + 1); + + if (!icons_only && num_btns % btns_per_row != 0) { + rows[0] = g_list_append (rows[0], switcher->priv->proxies->data); + + p = switcher->priv->proxies->next; + row_number = p ? 1 : 0; + } else { + p = switcher->priv->proxies; + row_number = 0; + } + + for (; p != NULL; p = p->next) { + GtkWidget *widget = p->data; + + if (g_list_length (rows[row_number]) == btns_per_row) + row_number++; + + rows[row_number] = g_list_append (rows[row_number], widget); + } + + row_last = row_number; + + /* Layout the buttons. */ + for (i = row_last; i >= 0; i--) { + gint len, extra_width; + + x = H_PADDING + allocation->x; + y -= max_height; + len = g_list_length (rows[i]); + if (!icons_only) + extra_width = (allocation->width - (len * max_width ) - (len * H_PADDING)) / len; + else + extra_width = 0; + for (p = rows [i]; p != NULL; p = p->next) { + GtkAllocation child_allocation; + + child_allocation.x = x; + child_allocation.y = y; + child_allocation.width = max_width + extra_width; + child_allocation.height = max_height; + + gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation); + + x += child_allocation.width + H_PADDING; + } + + y -= V_PADDING; + } + + for (i = 0; i <= row_last; i ++) + g_list_free (rows [i]); + g_free (rows); + + return y - allocation->y; +} + +static void +shell_switcher_toolbar_style_changed_cb (EShellSwitcher *switcher) +{ + if (!switcher->priv->style_set) { + switcher->priv->style_set = TRUE; + e_shell_switcher_unset_style (switcher); + } +} + +static void +shell_switcher_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TOOLBAR_STYLE: + e_shell_switcher_set_style ( + E_SHELL_SWITCHER (object), + g_value_get_enum (value)); + return; + + case PROP_TOOLBAR_VISIBLE: + e_shell_switcher_set_visible ( + E_SHELL_SWITCHER (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_switcher_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TOOLBAR_STYLE: + g_value_set_enum ( + value, e_shell_switcher_get_style ( + E_SHELL_SWITCHER (object))); + return; + + case PROP_TOOLBAR_VISIBLE: + g_value_set_boolean ( + value, e_shell_switcher_get_visible ( + E_SHELL_SWITCHER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_switcher_dispose (GObject *object) +{ + EShellSwitcherPrivate *priv; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (object); + + while (priv->proxies != NULL) { + GtkWidget *widget = priv->proxies->data; + gtk_container_remove (GTK_CONTAINER (object), widget); + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_switcher_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EShellSwitcherPrivate *priv; + GtkWidget *child; + GList *iter; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (widget); + + requisition->width = 0; + requisition->height = 0; + + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_size_request (child, requisition); + + if (!priv->toolbar_visible) + return; + + for (iter = priv->proxies; iter != NULL; iter = iter->next) { + GtkWidget *widget = iter->data; + GtkRequisition child_requisition; + + gtk_widget_size_request (widget, &child_requisition); + + child_requisition.width += H_PADDING; + child_requisition.height += V_PADDING; + + requisition->width = MAX ( + requisition->width, child_requisition.width); + requisition->height += child_requisition.height; + } +} + +static void +shell_switcher_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EShellSwitcher *switcher; + GtkAllocation child_allocation; + GtkWidget *child; + gint height; + + switcher = E_SHELL_SWITCHER (widget); + + widget->allocation = *allocation; + + if (switcher->priv->toolbar_visible) + height = shell_switcher_layout_actions (switcher); + else + height = allocation->height; + + child_allocation.x = allocation->x; + child_allocation.y = allocation->y; + child_allocation.width = allocation->width; + child_allocation.height = height; + + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_size_allocate (child, &child_allocation); +} + +static void +shell_switcher_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen) +{ + EShellSwitcherPrivate *priv; + GtkSettings *settings; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (widget); + + if (gtk_widget_has_screen (widget)) + settings = gtk_widget_get_settings (widget); + else + settings = NULL; + + if (settings == priv->settings) + return; + + if (priv->settings != NULL) { + g_signal_handler_disconnect ( + priv->settings, priv->settings_handler_id); + g_object_unref (priv->settings); + } + + if (settings != NULL) { + priv->settings = g_object_ref (settings); + priv->settings_handler_id = g_signal_connect_swapped ( + settings, "notify::gtk-toolbar-style", + G_CALLBACK (shell_switcher_toolbar_style_changed_cb), + widget); + } else + priv->settings = NULL; + + shell_switcher_toolbar_style_changed_cb (E_SHELL_SWITCHER (widget)); +} + +static void +shell_switcher_remove (GtkContainer *container, + GtkWidget *widget) +{ + EShellSwitcherPrivate *priv; + GList *link; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (container); + + /* Look in the internal widgets first. */ + + link = g_list_find (priv->proxies, widget); + if (link != NULL) { + GtkWidget *widget = link->data; + + gtk_widget_unparent (widget); + priv->proxies = g_list_delete_link (priv->proxies, link); + gtk_widget_queue_resize (GTK_WIDGET (container)); + return; + } + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); +} + +static void +shell_switcher_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EShellSwitcherPrivate *priv; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (container); + + if (include_internals) + g_list_foreach ( + priv->proxies, (GFunc) callback, callback_data); + + /* Chain up to parent's forall() method. */ + GTK_CONTAINER_CLASS (parent_class)->forall ( + container, include_internals, callback, callback_data); +} + +static void +shell_switcher_style_changed (EShellSwitcher *switcher, + GtkToolbarStyle style) +{ + if (switcher->priv->style == style) + return; + + switcher->priv->style = style; + + g_list_foreach ( + switcher->priv->proxies, + (GFunc) gtk_tool_item_toolbar_reconfigured, NULL); + + gtk_widget_queue_resize (GTK_WIDGET (switcher)); + g_object_notify (G_OBJECT (switcher), "toolbar-style"); +} + +static GtkIconSize +shell_switcher_get_icon_size (GtkToolShell *shell) +{ + return GTK_ICON_SIZE_LARGE_TOOLBAR; +} + +static GtkOrientation +shell_switcher_get_orientation (GtkToolShell *shell) +{ + return GTK_ORIENTATION_HORIZONTAL; +} + +static GtkToolbarStyle +shell_switcher_get_style (GtkToolShell *shell) +{ + return e_shell_switcher_get_style (E_SHELL_SWITCHER (shell)); +} + +static GtkReliefStyle +shell_switcher_get_relief_style (GtkToolShell *shell) +{ + return GTK_RELIEF_NORMAL; +} + +static void +shell_switcher_class_init (EShellSwitcherClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellSwitcherPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_switcher_set_property; + object_class->get_property = shell_switcher_get_property; + object_class->dispose = shell_switcher_dispose; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->size_request = shell_switcher_size_request; + widget_class->size_allocate = shell_switcher_size_allocate; + widget_class->screen_changed = shell_switcher_screen_changed; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = shell_switcher_remove; + container_class->forall = shell_switcher_forall; + + class->style_changed = shell_switcher_style_changed; + + /** + * EShellSwitcher:toolbar-style + * + * The switcher's toolbar style. + **/ + g_object_class_install_property ( + object_class, + PROP_TOOLBAR_STYLE, + g_param_spec_enum ( + "toolbar-style", + _("Toolbar Style"), + _("The switcher's toolbar style"), + GTK_TYPE_TOOLBAR_STYLE, + E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * EShellSwitcher:toolbar-visible + * + * Whether the switcher is visible. + **/ + g_object_class_install_property ( + object_class, + PROP_TOOLBAR_VISIBLE, + g_param_spec_boolean ( + "toolbar-visible", + _("Toolbar Visible"), + _("Whether the switcher is visible"), + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * EShellSwitcher::style-changed + * @switcher: the #EShellSwitcher which emitted the signal + * @style: the new #GtkToolbarStyle of the switcher + * + * Emitted when the style of the switcher changes. + **/ + signals[STYLE_CHANGED] = g_signal_new ( + "style-changed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EShellSwitcherClass, style_changed), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_TOOLBAR_STYLE); +} + +static void +shell_switcher_init (EShellSwitcher *switcher) +{ + switcher->priv = E_SHELL_SWITCHER_GET_PRIVATE (switcher); + + GTK_WIDGET_SET_FLAGS (switcher, GTK_NO_WINDOW); +} + +static void +shell_switcher_tool_shell_iface_init (GtkToolShellIface *iface) +{ + iface->get_icon_size = shell_switcher_get_icon_size; + iface->get_orientation = shell_switcher_get_orientation; + iface->get_style = shell_switcher_get_style; + iface->get_relief_style = shell_switcher_get_relief_style; +} + +GType +e_shell_switcher_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellSwitcherClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_switcher_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellSwitcher), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_switcher_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo tool_shell_info = { + (GInterfaceInitFunc) shell_switcher_tool_shell_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + GTK_TYPE_BIN, "EShellSwitcher", &type_info, 0); + + g_type_add_interface_static ( + type, GTK_TYPE_TOOL_SHELL, &tool_shell_info); + } + + return type; +} + +/** + * e_shell_switcher_new: + * + * Creates a new #EShellSwitcher instance. + * + * Returns: a new #EShellSwitcher instance + **/ +GtkWidget * +e_shell_switcher_new (void) +{ + return g_object_new (E_TYPE_SHELL_SWITCHER, NULL); +} + +/** + * e_shell_switcher_add_action: + * @switcher: an #EShellSwitcher + * @action: a #GtkAction + * + * Adds a button to @switcher that proxies for @action. Switcher buttons + * appear in the order they were added. + * + * #EShellWindow adds switcher actions in the order given by the + * <structfield>sort_order</structfield> field in #EShellBackendClass. + **/ +void +e_shell_switcher_add_action (EShellSwitcher *switcher, + GtkAction *action) +{ + GtkWidget *widget; + + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + g_return_if_fail (GTK_IS_ACTION (action)); + + g_object_ref (action); + widget = gtk_action_create_tool_item (action); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); + gtk_widget_show (widget); + + switcher->priv->proxies = g_list_append ( + switcher->priv->proxies, widget); + + gtk_widget_set_parent (widget, GTK_WIDGET (switcher)); + gtk_widget_queue_resize (GTK_WIDGET (switcher)); +} + +/** + * e_shell_switcher_get_style: + * @switcher: an #EShellSwitcher + * + * Returns whether @switcher has text, icons or both. + * + * Returns: the current style of @shell + **/ +GtkToolbarStyle +e_shell_switcher_get_style (EShellSwitcher *switcher) +{ + g_return_val_if_fail ( + E_IS_SHELL_SWITCHER (switcher), + E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE); + + return switcher->priv->style; +} + +/** + * e_shell_switcher_set_style: + * @switcher: an #EShellSwitcher + * @style: the new style for @switcher + * + * Alters the view of @switcher to display either icons only, text only, + * or both. + **/ +void +e_shell_switcher_set_style (EShellSwitcher *switcher, + GtkToolbarStyle style) +{ + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + + switcher->priv->style_set = TRUE; + g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style); +} + +/** + * e_shell_switcher_unset_style: + * @switcher: an #EShellSwitcher + * + * Unsets a switcher style set with e_shell_switcher_set_style(), so + * that user preferences will be used to determine the switcher style. + **/ +void +e_shell_switcher_unset_style (EShellSwitcher *switcher) +{ + GtkSettings *settings; + GtkToolbarStyle style; + + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + + if (!switcher->priv->style_set) + return; + + settings = switcher->priv->settings; + if (settings != NULL) + g_object_get (settings, "gtk-toolbar-style", &style, NULL); + else + style = E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE; + + if (style == GTK_TOOLBAR_BOTH) + style = GTK_TOOLBAR_BOTH_HORIZ; + + if (style != switcher->priv->style) + g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style); + + switcher->priv->style_set = FALSE; +} + +/** + * e_shell_switcher_get_visible: + * @switcher: an #EShellSwitcher + * + * Returns %TRUE if the switcher buttons are visible. + * + * Note that switcher button visibility is different than + * @switcher<!-- -->'s GTK_VISIBLE flag, since #EShellSwitcher + * is actually a container widget for #EShellSidebar. + * + * Returns: %TRUE if the switcher buttons are visible + **/ +gboolean +e_shell_switcher_get_visible (EShellSwitcher *switcher) +{ + g_return_val_if_fail (E_IS_SHELL_SWITCHER (switcher), FALSE); + + return switcher->priv->toolbar_visible; +} + +/** + * e_shell_switcher_set_visible: + * @switcher: an #EShellSwitcher + * @visible: whether the switcher buttons should be visible + * + * Sets the switcher button visiblity to @visible. + * + * Note that switcher button visibility is different than + * @switcher<!-- -->'s GTK_VISIBLE flag, since #EShellSwitcher + * is actually a container widget for #EShellSidebar. + **/ +void +e_shell_switcher_set_visible (EShellSwitcher *switcher, + gboolean visible) +{ + GList *iter; + + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + + switcher->priv->toolbar_visible = visible; + + for (iter = switcher->priv->proxies; iter != NULL; iter = iter->next) + g_object_set (iter->data, "visible", visible, NULL); + + gtk_widget_queue_resize (GTK_WIDGET (switcher)); + + g_object_notify (G_OBJECT (switcher), "toolbar-visible"); +} diff --git a/shell/e-shell-switcher.h b/shell/e-shell-switcher.h new file mode 100644 index 0000000000..1cc644595b --- /dev/null +++ b/shell/e-shell-switcher.h @@ -0,0 +1,92 @@ +/* + * e-shell-switcher.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-shell-switcher + * @short_description: buttons for switching views + * @include: shell/e-shell-switcher.h + **/ + +#ifndef E_SHELL_SWITCHER_H +#define E_SHELL_SWITCHER_H + +#include <e-shell-common.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_SWITCHER \ + (e_shell_switcher_get_type ()) +#define E_SHELL_SWITCHER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcher)) +#define E_SHELL_SWITCHER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_SWITCHER, EShellSwitcherClass)) +#define E_IS_SHELL_SWITCHER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_SWITCHER)) +#define E_IS_SHELL_SWITCHER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_SWITCHER)) +#define E_SHELL_SWITCHER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcherClass)) + +#define E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH_HORIZ + +G_BEGIN_DECLS + +typedef struct _EShellSwitcher EShellSwitcher; +typedef struct _EShellSwitcherClass EShellSwitcherClass; +typedef struct _EShellSwitcherPrivate EShellSwitcherPrivate; + +/** + * EShellSwitcher: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EShellSwitcher { + GtkBin parent; + EShellSwitcherPrivate *priv; +}; + +struct _EShellSwitcherClass { + GtkBinClass parent_class; + + void (*style_changed) (EShellSwitcher *switcher, + GtkToolbarStyle style); +}; + +GType e_shell_switcher_get_type (void); +GtkWidget * e_shell_switcher_new (void); +void e_shell_switcher_add_action (EShellSwitcher *switcher, + GtkAction *action); +GtkToolbarStyle e_shell_switcher_get_style (EShellSwitcher *switcher); +void e_shell_switcher_set_style (EShellSwitcher *switcher, + GtkToolbarStyle style); +void e_shell_switcher_unset_style (EShellSwitcher *switcher); +gboolean e_shell_switcher_get_visible (EShellSwitcher *switcher); +void e_shell_switcher_set_visible (EShellSwitcher *switcher, + gboolean visible); + +G_END_DECLS + +#endif /* E_SHELL_SWITCHER_H */ diff --git a/shell/e-shell-taskbar.c b/shell/e-shell-taskbar.c new file mode 100644 index 0000000000..61f27fbc79 --- /dev/null +++ b/shell/e-shell-taskbar.c @@ -0,0 +1,421 @@ +/* + * e-shell-taskbar.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-taskbar.h" + +#include <e-shell-view.h> + +#include <widgets/misc/e-activity-proxy.h> + +#define E_SHELL_TASKBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_TASKBAR, EShellTaskbarPrivate)) + +struct _EShellTaskbarPrivate { + + gpointer shell_view; /* weak pointer */ + + GtkWidget *label; + GtkWidget *hbox; + + GHashTable *proxy_table; +}; + +enum { + PROP_0, + PROP_MESSAGE, + PROP_SHELL_VIEW +}; + +static gpointer parent_class; + +static void +shell_taskbar_activity_remove (EShellTaskbar *shell_taskbar, + EActivity *activity) +{ + GtkBox *box; + GtkWidget *proxy; + GHashTable *proxy_table; + + box = GTK_BOX (shell_taskbar->priv->hbox); + proxy_table = shell_taskbar->priv->proxy_table; + proxy = g_hash_table_lookup (proxy_table, activity); + g_return_if_fail (proxy != NULL); + + g_hash_table_remove (proxy_table, activity); + gtk_container_remove (GTK_CONTAINER (box), proxy); + + if (box->children == NULL) + gtk_widget_hide (GTK_WIDGET (box)); +} + +static void +shell_taskbar_activity_add (EShellTaskbar *shell_taskbar, + EActivity *activity) +{ + GtkBox *box; + GtkWidget *proxy; + + proxy = e_activity_proxy_new (activity); + box = GTK_BOX (shell_taskbar->priv->hbox); + gtk_box_pack_start (box, proxy, TRUE, TRUE, 0); + gtk_box_reorder_child (box, proxy, 0); + gtk_widget_show (GTK_WIDGET (box)); + gtk_widget_show (proxy); + + g_hash_table_insert ( + shell_taskbar->priv->proxy_table, + g_object_ref (activity), g_object_ref (proxy)); + + g_signal_connect_swapped ( + activity, "cancelled", + G_CALLBACK (shell_taskbar_activity_remove), shell_taskbar); + + g_signal_connect_swapped ( + activity, "completed", + G_CALLBACK (shell_taskbar_activity_remove), shell_taskbar); +} + +static void +shell_taskbar_set_shell_view (EShellTaskbar *shell_taskbar, + EShellView *shell_view) +{ + g_return_if_fail (shell_taskbar->priv->shell_view == NULL); + + shell_taskbar->priv->shell_view = shell_view; + + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &shell_taskbar->priv->shell_view); +} + +static void +shell_taskbar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MESSAGE: + e_shell_taskbar_set_message ( + E_SHELL_TASKBAR (object), + g_value_get_string (value)); + return; + + case PROP_SHELL_VIEW: + shell_taskbar_set_shell_view ( + E_SHELL_TASKBAR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_taskbar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MESSAGE: + g_value_set_string ( + value, e_shell_taskbar_get_message ( + E_SHELL_TASKBAR (object))); + return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_shell_taskbar_get_shell_view ( + E_SHELL_TASKBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_taskbar_dispose (GObject *object) +{ + EShellTaskbarPrivate *priv; + + priv = E_SHELL_TASKBAR_GET_PRIVATE (object); + + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), &priv->shell_view); + priv->shell_view = NULL; + } + + if (priv->label != NULL) { + g_object_unref (priv->label); + priv->label = NULL; + } + + if (priv->hbox != NULL) { + g_object_unref (priv->hbox); + priv->hbox = NULL; + } + + g_hash_table_remove_all (priv->proxy_table); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_taskbar_finalize (GObject *object) +{ + EShellTaskbarPrivate *priv; + + priv = E_SHELL_TASKBAR_GET_PRIVATE (object); + + g_hash_table_destroy (priv->proxy_table); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_taskbar_constructed (GObject *object) +{ + EShellView *shell_view; + EShellBackend *shell_backend; + EShellTaskbar *shell_taskbar; + + shell_taskbar = E_SHELL_TASKBAR (object); + shell_view = e_shell_taskbar_get_shell_view (shell_taskbar); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + g_signal_connect_swapped ( + shell_backend, "activity-added", + G_CALLBACK (shell_taskbar_activity_add), shell_taskbar); +} + +static void +shell_taskbar_class_init (EShellTaskbarClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellTaskbarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_taskbar_set_property; + object_class->get_property = shell_taskbar_get_property; + object_class->dispose = shell_taskbar_dispose; + object_class->finalize = shell_taskbar_finalize; + object_class->constructed = shell_taskbar_constructed; + + /** + * EShellTaskbar:message + * + * The message to display in the taskbar. + **/ + g_object_class_install_property ( + object_class, + PROP_MESSAGE, + g_param_spec_string ( + "message", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * EShellTaskbar:shell-view + * + * The #EShellView to which the taskbar widget belongs. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + NULL, + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +shell_taskbar_init (EShellTaskbar *shell_taskbar) +{ + GtkWidget *widget; + GHashTable *proxy_table; + gint height; + + proxy_table = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) g_object_unref, + (GDestroyNotify) g_object_unref); + + shell_taskbar->priv = E_SHELL_TASKBAR_GET_PRIVATE (shell_taskbar); + shell_taskbar->priv->proxy_table = proxy_table; + + gtk_box_set_spacing (GTK_BOX (shell_taskbar), 12); + + widget = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_box_pack_start (GTK_BOX (shell_taskbar), widget, TRUE, TRUE, 0); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + shell_taskbar->priv->label = g_object_ref (widget); + gtk_widget_hide (widget); + + widget = gtk_hbox_new (FALSE, 3); + gtk_box_pack_start (GTK_BOX (shell_taskbar), widget, TRUE, TRUE, 0); + shell_taskbar->priv->hbox = g_object_ref (widget); + gtk_widget_hide (widget); + + /* Make the taskbar large enough to accomodate a small icon. + * XXX The "* 2" is a fudge factor to allow for some padding + * The true value is probably buried in a style property. */ + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height); + gtk_widget_set_size_request ( + GTK_WIDGET (shell_taskbar), -1, (height * 2)); +} + +GType +e_shell_taskbar_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellTaskbarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_taskbar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellTaskbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_taskbar_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_HBOX, "EShellTaskbar", &type_info, 0); + } + + return type; +} + +/** + * e_shell_taskbar_new: + * @shell_view: an #EShellView + * + * Creates a new #EShellTaskbar instance belonging to @shell_view. + * + * Returns: a new #EShellTaskbar instance + **/ +GtkWidget * +e_shell_taskbar_new (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return g_object_new ( + E_TYPE_SHELL_TASKBAR, "shell-view", shell_view, NULL); +} + +/** + * e_shell_taskbar_get_shell_view: + * @shell_taskbar: an #EShellTaskbar + * + * Returns the #EShellView that was passed to e_shell_taskbar_new(). + * + * Returns: the #EShellView to which @shell_taskbar belongs + **/ +EShellView * +e_shell_taskbar_get_shell_view (EShellTaskbar *shell_taskbar) +{ + g_return_val_if_fail (E_IS_SHELL_TASKBAR (shell_taskbar), NULL); + + return shell_taskbar->priv->shell_view; +} + +/** + * e_shell_taskbar_get_message: + * @shell_taskbar: an #EShellTaskbar + * + * Returns the message currently shown in the taskbar, or an empty string + * if no message is shown. Taskbar messages are used primarily for menu + * tooltips. + * + * Returns: the current taskbar message + **/ +const gchar * +e_shell_taskbar_get_message (EShellTaskbar *shell_taskbar) +{ + GtkWidget *label; + + g_return_val_if_fail (E_IS_SHELL_TASKBAR (shell_taskbar), NULL); + + label = shell_taskbar->priv->label; + + return gtk_label_get_text (GTK_LABEL (label)); +} + +/** + * e_shell_taskbar_set_message: + * @shell_taskbar: an #EShellTaskbar + * @message: the message to show + * + * Shows a message in the taskbar. If @message is %NULL or an empty string, + * the taskbar message is cleared. Taskbar messages are used primarily for + * menu tooltips. + **/ +void +e_shell_taskbar_set_message (EShellTaskbar *shell_taskbar, + const gchar *message) +{ + GtkWidget *label; + + g_return_if_fail (E_IS_SHELL_TASKBAR (shell_taskbar)); + + label = shell_taskbar->priv->label; + gtk_label_set_text (GTK_LABEL (label), message); + + if (message != NULL && *message != '\0') + gtk_widget_show (label); + else + gtk_widget_hide (label); + + g_object_notify (G_OBJECT (shell_taskbar), "message"); +} + +/** + * e_shell_taskbar_unset_message: + * @shell_taskbar: an #EShellTaskbar + * + * This is equivalent to passing a %NULL message to + * e_shell_taskbar_set_message(). + **/ +void +e_shell_taskbar_unset_message (EShellTaskbar *shell_taskbar) +{ + g_return_if_fail (E_IS_SHELL_TASKBAR (shell_taskbar)); + + e_shell_taskbar_set_message (shell_taskbar, NULL); +} diff --git a/shell/e-shell-taskbar.h b/shell/e-shell-taskbar.h new file mode 100644 index 0000000000..3c3d40010e --- /dev/null +++ b/shell/e-shell-taskbar.h @@ -0,0 +1,87 @@ +/* + * e-shell-taskbar.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/** + * SECTION: e-shell-taskbar + * @short_description: the bottom of the main window + * @include: shell/e-shell-taskbar.h + **/ + +#ifndef E_SHELL_TASKBAR_H +#define E_SHELL_TASKBAR_H + +#include <shell/e-shell-common.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_TASKBAR \ + (e_shell_taskbar_get_type ()) +#define E_SHELL_TASKBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_TASKBAR, EShellTaskbar)) +#define E_SHELL_TASKBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_TASKBAR, EShellTaskbarClass)) +#define E_IS_SHELL_TASKBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_TASKBAR)) +#define E_IS_SHELL_TASKBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SHELL_TASKBAR)) +#define E_SHELL_TASKBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_TASKBAR, EShellTaskbarClass)) + +G_BEGIN_DECLS + +/* Avoid including <e-shell-view.h>, because it includes us! */ +struct _EShellView; + +typedef struct _EShellTaskbar EShellTaskbar; +typedef struct _EShellTaskbarClass EShellTaskbarClass; +typedef struct _EShellTaskbarPrivate EShellTaskbarPrivate; + +/** + * EShellTaskbar: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ +struct _EShellTaskbar { + GtkHBox parent; + EShellTaskbarPrivate *priv; +}; + +struct _EShellTaskbarClass { + GtkHBoxClass parent_class; +}; + +GType e_shell_taskbar_get_type (void); +GtkWidget * e_shell_taskbar_new (struct _EShellView *shell_view); +struct _EShellView * + e_shell_taskbar_get_shell_view (EShellTaskbar *shell_taskbar); +const gchar * e_shell_taskbar_get_message (EShellTaskbar *shell_taskbar); +void e_shell_taskbar_set_message (EShellTaskbar *shell_taskbar, + const gchar *message); +void e_shell_taskbar_unset_message (EShellTaskbar *shell_taskbar); + +G_END_DECLS + +#endif /* E_SHELL_TASKBAR_H */ diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index 319a0d3c76..5808f9e027 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -1,5 +1,5 @@ /* - * Helper class for evolution shells to setup a view + * e-shell-view.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -15,126 +15,1177 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif +#include "e-shell-view.h" -#include <gtk/gtk.h> +#include <string.h> #include <glib/gi18n.h> -#include "e-shell-view.h" -#include "e-shell-window.h" +#include "e-util/e-util.h" +#include "e-util/e-plugin-ui.h" + +#include "e-shell-window-actions.h" + +#define E_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_VIEW, EShellViewPrivate)) -static BonoboObjectClass *parent_class = NULL; +#define STATE_SAVE_TIMEOUT_SECONDS 3 struct _EShellViewPrivate { - gint dummy; + + gpointer shell_window; /* weak pointer */ + + GKeyFile *state_key_file; + guint state_save_source_id; + + gchar *title; + gchar *view_id; + gint page_num; + guint merge_id; + + GtkAction *action; + GtkSizeGroup *size_group; + GtkWidget *shell_content; + GtkWidget *shell_sidebar; + GtkWidget *shell_taskbar; }; +enum { + PROP_0, + PROP_ACTION, + PROP_PAGE_NUM, + PROP_TITLE, + PROP_SHELL_BACKEND, + PROP_SHELL_CONTENT, + PROP_SHELL_SIDEBAR, + PROP_SHELL_TASKBAR, + PROP_SHELL_WINDOW, + PROP_VIEW_ID +}; + +enum { + TOGGLED, + UPDATE_ACTIONS, + LAST_SIGNAL +}; + +static gpointer parent_class; +static gulong signals[LAST_SIGNAL]; + +static void +shell_view_init_view_collection (EShellViewClass *class) +{ + EShellBackend *shell_backend; + const gchar *base_dir; + const gchar *backend_name; + gchar *system_dir; + gchar *local_dir; + + shell_backend = class->shell_backend; + g_return_if_fail (E_IS_SHELL_BACKEND (shell_backend)); + backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + base_dir = EVOLUTION_GALVIEWSDIR; + system_dir = g_build_filename (base_dir, backend_name, NULL); + + base_dir = e_shell_backend_get_data_dir (shell_backend); + local_dir = g_build_filename (base_dir, "views", NULL); + + /* The view collection is never destroyed. */ + class->view_collection = gal_view_collection_new (); + + gal_view_collection_set_title ( + class->view_collection, class->label); + + gal_view_collection_set_storage_directories ( + class->view_collection, system_dir, local_dir); + + g_free (system_dir); + g_free (local_dir); + + /* This is all we can do. It's up to the subclasses to + * add the appropriate factories to the view collection. */ +} + static void -impl_ShellView_setTitle(PortableServer_Servant _servant, const CORBA_char *id, const CORBA_char * title, CORBA_Environment * ev) +shell_view_update_view_id (EShellView *shell_view, + GalViewInstance *view_instance) { - EShellView *esw = (EShellView *)bonobo_object_from_servant(_servant); - /* To translators: This is the window title and %s is the - component name. Most translators will want to keep it as is. */ - gchar *tmp = g_strdup_printf(_("%s - Evolution"), title); + gchar *view_id; - e_shell_window_set_title(esw->window, id, tmp); - g_free(tmp); + view_id = gal_view_instance_get_current_view_id (view_instance); + e_shell_view_set_view_id (shell_view, view_id); + g_free (view_id); } static void -impl_ShellView_setComponent(PortableServer_Servant _servant, const CORBA_char *id, CORBA_Environment * ev) +shell_view_load_state (EShellView *shell_view) { - EShellView *esw = (EShellView *)bonobo_object_from_servant(_servant); + EShellBackend *shell_backend; + GKeyFile *key_file; + const gchar *config_dir; + gchar *filename; + GError *error = NULL; - e_shell_window_switch_to_component(esw->window, id); + shell_backend = e_shell_view_get_shell_backend (shell_view); + config_dir = e_shell_backend_get_config_dir (shell_backend); + filename = g_build_filename (config_dir, "state", NULL); + + /* XXX Should do this asynchronously. */ + key_file = shell_view->priv->state_key_file; + g_key_file_load_from_file (key_file, filename, 0, &error); + + if (error == NULL) + goto exit; + + if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + g_warning ("%s", error->message); + + g_error_free (error); + +exit: + g_free (filename); } -struct change_icon_struct { - const gchar *component_name; - const gchar *icon_name; -}; +static void +shell_view_save_state (EShellView *shell_view) +{ + EShellBackend *shell_backend; + GKeyFile *key_file; + const gchar *config_dir; + gchar *contents; + gchar *filename; + GError *error = NULL; + + shell_backend = e_shell_view_get_shell_backend (shell_view); + config_dir = e_shell_backend_get_config_dir (shell_backend); + filename = g_build_filename (config_dir, "state", NULL); + + /* XXX Should do this asynchronously. */ + key_file = shell_view->priv->state_key_file; + contents = g_key_file_to_data (key_file, NULL, NULL); + g_file_set_contents (filename, contents, -1, &error); + g_free (contents); + + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + } + + g_free (filename); +} static gboolean -change_button_icon_func (EShell *shell, EShellWindow *window, gpointer user_data) +shell_view_state_timeout_cb (EShellView *shell_view) { - struct change_icon_struct *cis = (struct change_icon_struct*)user_data; + shell_view_save_state (shell_view); + shell_view->priv->state_save_source_id = 0; - g_return_val_if_fail (window != NULL, FALSE); - g_return_val_if_fail (cis != NULL, FALSE); + return FALSE; +} + +static gboolean +shell_view_register_ui_manager (EShellView *shell_view) +{ + EShellViewClass *shell_view_class; + EShellWindow *shell_window; + GtkUIManager *ui_manager; + const gchar *id; - e_shell_window_change_component_button_icon (window, cis->component_name, cis->icon_name); + /* This is a one-time, post-construction idle callback. */ - return TRUE; + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + id = shell_view_class->ui_manager_id; + + e_plugin_ui_register_manager (ui_manager, id, shell_view); + + if (e_shell_view_is_active (shell_view)) { + e_plugin_ui_enable_manager (ui_manager, id); + e_shell_view_update_actions (shell_view); + } + + return FALSE; +} + +static void +shell_view_emit_toggled (EShellView *shell_view) +{ + g_signal_emit (shell_view, signals[TOGGLED], 0); } static void -impl_ShellView_setButtonIcon (PortableServer_Servant _servant, const CORBA_char *id, const CORBA_char * iconName, CORBA_Environment * ev) +shell_view_set_action (EShellView *shell_view, + GtkAction *action) { - EShellView *esw = (EShellView *)bonobo_object_from_servant(_servant); - EShell *shell = e_shell_window_peek_shell (esw->window); + gchar *label; + + g_return_if_fail (shell_view->priv->action == NULL); - struct change_icon_struct cis; - cis.component_name = id; - cis.icon_name = iconName; + shell_view->priv->action = g_object_ref (action); - e_shell_foreach_shell_window (shell, change_button_icon_func, &cis); + g_object_get (action, "label", &label, NULL); + e_shell_view_set_title (shell_view, label); + g_free (label); + + g_signal_connect_swapped ( + action, "toggled", + G_CALLBACK (shell_view_emit_toggled), shell_view); } static void -impl_dispose (GObject *object) +shell_view_set_shell_window (EShellView *shell_view, + GtkWidget *shell_window) { - /*EShellView *esv = (EShellView *)object;*/ + g_return_if_fail (shell_view->priv->shell_window == NULL); + + shell_view->priv->shell_window = shell_window; - ((GObjectClass *)parent_class)->dispose(object); + g_object_add_weak_pointer ( + G_OBJECT (shell_window), + &shell_view->priv->shell_window); } static void -impl_finalise (GObject *object) +shell_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - ((GObjectClass *)parent_class)->finalize(object); + switch (property_id) { + case PROP_ACTION: + shell_view_set_action ( + E_SHELL_VIEW (object), + g_value_get_object (value)); + return; + + case PROP_PAGE_NUM: + e_shell_view_set_page_num ( + E_SHELL_VIEW (object), + g_value_get_int (value)); + return; + + case PROP_TITLE: + e_shell_view_set_title ( + E_SHELL_VIEW (object), + g_value_get_string (value)); + return; + + case PROP_SHELL_WINDOW: + shell_view_set_shell_window ( + E_SHELL_VIEW (object), + g_value_get_object (value)); + return; + + case PROP_VIEW_ID: + e_shell_view_set_view_id ( + E_SHELL_VIEW (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -e_shell_view_class_init (EShellViewClass *klass) +shell_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTION: + g_value_set_object ( + value, e_shell_view_get_action ( + E_SHELL_VIEW (object))); + return; + + case PROP_PAGE_NUM: + g_value_set_int ( + value, e_shell_view_get_page_num ( + E_SHELL_VIEW (object))); + return; + + case PROP_TITLE: + g_value_set_string ( + value, e_shell_view_get_title ( + E_SHELL_VIEW (object))); + return; + + case PROP_SHELL_BACKEND: + g_value_set_object ( + value, e_shell_view_get_shell_backend ( + E_SHELL_VIEW (object))); + + case PROP_SHELL_CONTENT: + g_value_set_object ( + value, e_shell_view_get_shell_content ( + E_SHELL_VIEW (object))); + return; + + case PROP_SHELL_SIDEBAR: + g_value_set_object ( + value, e_shell_view_get_shell_sidebar ( + E_SHELL_VIEW (object))); + return; + + case PROP_SHELL_TASKBAR: + g_value_set_object ( + value, e_shell_view_get_shell_taskbar ( + E_SHELL_VIEW (object))); + return; + + case PROP_SHELL_WINDOW: + g_value_set_object ( + value, e_shell_view_get_shell_window ( + E_SHELL_VIEW (object))); + return; + + case PROP_VIEW_ID: + g_value_set_string ( + value, e_shell_view_get_view_id ( + E_SHELL_VIEW (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_view_dispose (GObject *object) +{ + EShellViewPrivate *priv; + + priv = E_SHELL_VIEW_GET_PRIVATE (object); + + /* Expedite any pending state saves. */ + if (priv->state_save_source_id > 0) { + g_source_remove (priv->state_save_source_id); + priv->state_save_source_id = 0; + shell_view_save_state (E_SHELL_VIEW (object)); + } + + if (priv->shell_window != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_window), &priv->shell_window); + priv->shell_window = NULL; + } + + if (priv->size_group != NULL) { + g_object_unref (priv->size_group); + priv->size_group = NULL; + } + + if (priv->shell_content != NULL) { + g_object_unref (priv->shell_content); + priv->shell_content = NULL; + } + + if (priv->shell_sidebar != NULL) { + g_object_unref (priv->shell_sidebar); + priv->shell_sidebar = NULL; + } + + if (priv->shell_taskbar != NULL) { + g_object_unref (priv->shell_taskbar); + priv->shell_taskbar = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_view_finalize (GObject *object) +{ + EShellViewPrivate *priv; + + priv = E_SHELL_VIEW_GET_PRIVATE (object); + + g_key_file_free (priv->state_key_file); + + g_free (priv->title); + g_free (priv->view_id); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_view_constructed (GObject *object) +{ + EShellViewClass *shell_view_class; + EShellView *shell_view; + GtkWidget *widget; + + shell_view = E_SHELL_VIEW (object); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + + /* Defer EPluginUI registration to an idle callback to give the + * shell view subclass a chance to register its own actions and + * action groups. Registration will immediately load EPlugins + * that specify the shell view's GtkUIManager ID, and their + * initialization routines may require those actions or action + * groups that have not yet been added. */ + g_idle_add ((GSourceFunc) shell_view_register_ui_manager, shell_view); + + shell_view_load_state (shell_view); + + /* Invoke factory methods. */ + + widget = shell_view_class->new_shell_content (shell_view); + shell_view->priv->shell_content = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = shell_view_class->new_shell_sidebar (shell_view); + shell_view->priv->shell_sidebar = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = shell_view_class->new_shell_taskbar (shell_view); + shell_view->priv->shell_taskbar = g_object_ref_sink (widget); + gtk_widget_show (widget); +} + +static void +shell_view_toggled (EShellView *shell_view) +{ + EShellViewPrivate *priv = shell_view->priv; + EShellViewClass *shell_view_class; + EShellWindow *shell_window; + GtkUIManager *ui_manager; + const gchar *basename, *id; + gboolean view_is_active; + + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + view_is_active = e_shell_view_is_active (shell_view); + basename = shell_view_class->ui_definition; + id = shell_view_class->ui_manager_id; + + if (view_is_active && priv->merge_id == 0) { + priv->merge_id = e_load_ui_definition (ui_manager, basename); + e_plugin_ui_enable_manager (ui_manager, id); + + } else if (!view_is_active && priv->merge_id != 0) { + e_plugin_ui_disable_manager (ui_manager, id); + gtk_ui_manager_remove_ui (ui_manager, priv->merge_id); + priv->merge_id = 0; + } + + gtk_ui_manager_ensure_update (ui_manager); +} + +static void +shell_view_class_init (EShellViewClass *class) { GObjectClass *object_class; - POA_GNOME_Evolution_ShellView__epv *epv; - parent_class = g_type_class_ref(bonobo_object_get_type()); + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_view_set_property; + object_class->get_property = shell_view_get_property; + object_class->dispose = shell_view_dispose; + object_class->finalize = shell_view_finalize; + object_class->constructed = shell_view_constructed; + + /* Default Factories */ + class->new_shell_content = e_shell_content_new; + class->new_shell_sidebar = e_shell_sidebar_new; + class->new_shell_taskbar = e_shell_taskbar_new; + + class->toggled = shell_view_toggled; + + /** + * EShellView:action: + * + * The #GtkRadioAction registered with #EShellSwitcher. + **/ + g_object_class_install_property ( + object_class, + PROP_ACTION, + g_param_spec_object ( + "action", + _("Switcher Action"), + _("The switcher action for this shell view"), + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + /** + * EShellView:page-num + * + * The #GtkNotebook page number of the shell view. + **/ + g_object_class_install_property ( + object_class, + PROP_PAGE_NUM, + g_param_spec_int ( + "page-num", + _("Page Number"), + _("The notebook page number of the shell view"), + -1, + G_MAXINT, + -1, + G_PARAM_READWRITE)); + + /** + * EShellView:title + * + * The title of the shell view. Also serves as the #EShellWindow + * title when the shell view is active. + **/ + g_object_class_install_property ( + object_class, + PROP_TITLE, + g_param_spec_string ( + "title", + _("Title"), + _("The title of the shell view"), + NULL, + G_PARAM_READWRITE)); + + /** + * EShellView::shell-backend + * + * The #EShellBackend for this shell view. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_BACKEND, + g_param_spec_object ( + "shell-backend", + _("Shell Backend"), + _("The EShellBackend for this shell view"), + E_TYPE_SHELL_BACKEND, + G_PARAM_READABLE)); + + /** + * EShellView:shell-content + * + * The content widget appears in an #EShellWindow<!-- -->'s + * right pane. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_CONTENT, + g_param_spec_object ( + "shell-content", + _("Shell Content Widget"), + _("The content widget appears in " + "a shell window's right pane"), + E_TYPE_SHELL_CONTENT, + G_PARAM_READABLE)); + + /** + * EShellView:shell-sidebar + * + * The sidebar widget appears in an #EShellWindow<!-- -->'s + * left pane. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_SIDEBAR, + g_param_spec_object ( + "shell-sidebar", + _("Shell Sidebar Widget"), + _("The sidebar widget appears in " + "a shell window's left pane"), + E_TYPE_SHELL_SIDEBAR, + G_PARAM_READABLE)); - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalise; + /** + * EShellView:shell-taskbar + * + * The taskbar widget appears at the bottom of an #EShellWindow. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_TASKBAR, + g_param_spec_object ( + "shell-taskbar", + _("Shell Taskbar Widget"), + _("The taskbar widget appears at " + "the bottom of a shell window"), + E_TYPE_SHELL_TASKBAR, + G_PARAM_READABLE)); - epv = & klass->epv; - epv->setTitle = impl_ShellView_setTitle; - epv->setComponent = impl_ShellView_setComponent; - epv->setButtonIcon = impl_ShellView_setButtonIcon; + /** + * EShellView:shell-window + * + * The #EShellWindow to which the shell view belongs. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_WINDOW, + g_param_spec_object ( + "shell-window", + _("Shell Window"), + _("The window to which the shell view belongs"), + E_TYPE_SHELL_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + /** + * EShellView:view-id + * + * The current #GalView ID. + **/ + g_object_class_install_property ( + object_class, + PROP_VIEW_ID, + g_param_spec_string ( + "view-id", + _("Current View ID"), + _("The current GAL view ID"), + NULL, + G_PARAM_READWRITE)); + + /** + * EShellView::toggled + * @shell_view: the #EShellView which emitted the signal + * + * Emitted when @shell_view is activated or deactivated. + * Use e_shell_view_is_active() to find out which event has + * occurred. The shell view being deactivated is always + * notified before the shell view being activated. + * + * By default, #EShellView adds the UI definition file + * given in the <structfield>ui_definition</structfield> + * field of #EShellViewClass on activation, and removes the + * UI definition on deactivation. + **/ + signals[TOGGLED] = g_signal_new ( + "toggled", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EShellViewClass, toggled), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * EShellView::update-actions + * @shell_view: the #EShellView which emitted the signal + * + * #EShellView subclasses should override the + * <structfield>update_actions</structfield> method in + * #EShellViewClass to update sensitivities, labels, or any + * other aspect of the #GtkAction<!-- -->s they have registered. + * + * Plugins can also connect to this signal to be notified + * when to update their own #GtkAction<!-- -->s. + **/ + signals[UPDATE_ACTIONS] = g_signal_new ( + "update-actions", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EShellViewClass, update_actions), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void -e_shell_view_init (EShellView *shell) +shell_view_init (EShellView *shell_view, + EShellViewClass *class) { + GtkSizeGroup *size_group; + + if (class->view_collection == NULL) + shell_view_init_view_collection (class); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + + shell_view->priv = E_SHELL_VIEW_GET_PRIVATE (shell_view); + shell_view->priv->state_key_file = g_key_file_new (); + shell_view->priv->size_group = size_group; } -EShellView *e_shell_view_new(struct _EShellWindow *window) +GType +e_shell_view_get_type (void) { - EShellView *new = g_object_new (e_shell_view_get_type (), NULL); + static GType type = 0; - /* TODO: listen to destroy? */ - new->window = window; + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_view_init, + NULL /* value_table */ + }; - return new; + type = g_type_register_static ( + G_TYPE_OBJECT, "EShellView", + &type_info, G_TYPE_FLAG_ABSTRACT); + } + + return type; } -BONOBO_TYPE_FUNC_FULL (EShellView, GNOME_Evolution_ShellView, bonobo_object_get_type(), e_shell_view) +/** + * e_shell_view_get_name: + * @shell_view: an #EShellView + * + * Returns the view name for @shell_view, which is also the name of + * the corresponding #EShellBackend (see the <structfield>name</structfield> + * field in #EShellBackendInfo). + * + * Returns: the view name for @shell_view + **/ +const gchar * +e_shell_view_get_name (EShellView *shell_view) +{ + GtkAction *action; + + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + action = e_shell_view_get_action (shell_view); + /* Switcher actions have a secret "view-name" data value. + * This gets set in e_shell_window_create_switcher_actions(). */ + return g_object_get_data (G_OBJECT (action), "view-name"); +} + +/** + * e_shell_view_get_action: + * @shell_view: an #EShellView + * + * Returns the switcher action for @shell_view. + * + * An #EShellWindow creates a #GtkRadioAction for each registered subclass + * of #EShellView. This action gets passed to the #EShellSwitcher, which + * displays a button that proxies the action. The icon at the top of the + * sidebar also proxies the action. When @shell_view is active, the + * action's icon becomes the #EShellWindow icon. + * + * Returns: the switcher action for @shell_view + **/ +GtkAction * +e_shell_view_get_action (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->action; +} + +/** + * e_shell_view_get_title: + * @shell_view: an #EShellView + * + * Returns the title for @shell_view. When @shell_view is active, the + * shell view's title becomes the #EShellWindow title. + * + * Returns: the title for @shell_view + **/ +const gchar * +e_shell_view_get_title (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->title; +} + +/** + * e_shell_view_set_title: + * @shell_view: an #EShellView + * @title: a title for @shell_view + * + * Sets the title for @shell_view. When @shell_view is active, the + * shell view's title becomes the #EShellWindow title. + **/ +void +e_shell_view_set_title (EShellView *shell_view, + const gchar *title) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (title == NULL) + title = E_SHELL_VIEW_GET_CLASS (shell_view)->label; + + if (g_strcmp0 (shell_view->priv->title, title) == 0) + return; + + g_free (shell_view->priv->title); + shell_view->priv->title = g_strdup (title); + + g_object_notify (G_OBJECT (shell_view), "title"); +} + +/** + * e_shell_view_get_view_id: + * @shell_view: an #EShellView + * + * Returns the ID of the currently selected #GalView. + * + * #EShellView subclasses are responsible for keeping this property in + * sync with their #GalViewInstance. #EShellView itself just provides + * a place to store the view ID, and emits a #GObject::notify signal + * when the property changes. + * + * Returns: the ID of the current #GalView + **/ +const gchar * +e_shell_view_get_view_id (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->view_id; +} + +/** + * e_shell_view_set_view_id: + * @shell_view: an #EShellView + * @view_id: a #GalView ID + * + * Selects the #GalView whose ID is equal to @view_id. + * + * #EShellView subclasses are responsible for keeping this property in + * sync with their #GalViewInstance. #EShellView itself just provides + * a place to store the view ID, and emits a #GObject::notify signal + * when the property changes. + **/ +void +e_shell_view_set_view_id (EShellView *shell_view, + const gchar *view_id) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (g_strcmp0 (shell_view->priv->view_id, view_id) == 0) + return; + + g_free (shell_view->priv->view_id); + shell_view->priv->view_id = g_strdup (view_id); + + g_object_notify (G_OBJECT (shell_view), "view-id"); +} + +/** + * e_shell_view_get_shell_window: + * @shell_view: an #EShellView + * + * Returns the #EShellWindow to which @shell_view belongs. + * + * Returns: the #EShellWindow to which @shell_view belongs + **/ +EShellWindow * +e_shell_view_get_shell_window (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return E_SHELL_WINDOW (shell_view->priv->shell_window); +} + +/** + * e_shell_view_is_active: + * @shell_view: an #EShellView + * + * Returns %TRUE if @shell_view is active. That is, if it's currently + * visible in its #EShellWindow. An #EShellWindow can only display one + * shell view at a time. + * + * Technically this just checks the #GtkToggleAction:active property of + * the shell view's switcher action. See e_shell_view_get_action(). + * + * Returns: %TRUE if @shell_view is active + **/ +gboolean +e_shell_view_is_active (EShellView *shell_view) +{ + GtkAction *action; + + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + action = e_shell_view_get_action (shell_view); + + return gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); +} + +/** + * e_shell_view_get_page_num: + * @shell_view: an #EShellView + * + * This function is only interesting to #EShellWindow. It returns the + * #GtkNotebook page number for @shell_view. The rest of the application + * should have no need for this. + * + * Returns: the notebook page number for @shell_view + **/ +gint +e_shell_view_get_page_num (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), -1); + + return shell_view->priv->page_num; +} + +/** + * e_shell_view_set_page_num: + * @shell_view: an #EShellView + * @page_num: a notebook page number + * + * This function is only interesting to #EShellWindow. It sets the + * #GtkNotebook page number for @shell_view. The rest of the application + * must never call this because it could mess up shell view switching. + **/ +void +e_shell_view_set_page_num (EShellView *shell_view, + gint page_num) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + shell_view->priv->page_num = page_num; + + g_object_notify (G_OBJECT (shell_view), "page-num"); +} + +/** + * e_shell_view_get_size_group: + * @shell_view: an #EShellView + * + * Returns a #GtkSizeGroup that #EShellContent and #EShellSidebar use + * to keep the search bar and sidebar banner vertically aligned. The + * rest of the application should have no need for this. + * + * Returns: a #GtkSizeGroup for internal use + **/ +GtkSizeGroup * +e_shell_view_get_size_group (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->size_group; +} + +/** + * e_shell_view_get_shell_backend: + * @shell_view: an #EShellView + * + * Returns the corresponding #EShellBackend for @shell_view. + * + * Returns: the corresponding #EShellBackend for @shell_view + **/ +EShellBackend * +e_shell_view_get_shell_backend (EShellView *shell_view) +{ + EShellViewClass *class; + + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + class = E_SHELL_VIEW_GET_CLASS (shell_view); + g_return_val_if_fail (class->shell_backend != NULL, NULL); + + return class->shell_backend; +} + +/** + * e_shell_view_get_shell_content: + * @shell_view: an #EShellView + * + * Returns the #EShellContent instance for @shell_view. + * + * By default, #EShellView creates a plain #EShellContent during + * initialization. But #EShellView subclasses can override the + * <structfield>new_shell_content</structfield> factory method + * in #EShellViewClass to create a custom #EShellContent. + * + * Returns: the #EShellContent instance for @shell_view + **/ +EShellContent * +e_shell_view_get_shell_content (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return E_SHELL_CONTENT (shell_view->priv->shell_content); +} + +/** + * e_shell_view_get_shell_sidebar: + * @shell_view: an #EShellView + * + * Returns the #EShellSidebar instance for @shell_view. + * + * By default, #EShellView creates a plain #EShellSidebar during + * initialization. But #EShellView subclasses can override the + * <structfield>new_shell_sidebar</structfield> factory method + * in #EShellViewClass to create a custom #EShellSidebar. + * + * Returns: the #EShellSidebar instance for @shell_view + **/ +EShellSidebar * +e_shell_view_get_shell_sidebar (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return E_SHELL_SIDEBAR (shell_view->priv->shell_sidebar); +} + +/** + * e_shell_view_get_shell_taskbar: + * @shell_view: an #EShellView + * + * Returns the #EShellTaskbar instance for @shell_view. + * + * By default, #EShellView creates a plain #EShellTaskbar during + * initialization. But #EShellView subclasses can override the + * <structfield>new_shell_taskbar</structfield> factory method + * in #EShellViewClass to create a custom #EShellTaskbar. + * + * Returns: the #EShellTaskbar instance for @shell_view + **/ +EShellTaskbar * +e_shell_view_get_shell_taskbar (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return E_SHELL_TASKBAR (shell_view->priv->shell_taskbar); +} + +/** + * e_shell_view_get_state_key_file: + * @shell_view: an #EShellView + * + * Returns the #GKeyFile holding widget state data for @shell_view. + * + * Returns: the #GKeyFile for @shell_view + **/ +GKeyFile * +e_shell_view_get_state_key_file (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->state_key_file; +} + +/** + * e_shell_view_set_state_dirty: + * @shell_view: an #EShellView + * + * Marks the widget state data as modified (or "dirty") and schedules it + * to be saved to disk after a short delay. The delay caps the frequency + * of saving to disk. + **/ +void +e_shell_view_set_state_dirty (EShellView *shell_view) +{ + guint source_id; + + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + /* If a timeout is already scheduled, do nothing. */ + if (shell_view->priv->state_save_source_id > 0) + return; + + source_id = g_timeout_add_seconds ( + STATE_SAVE_TIMEOUT_SECONDS, (GSourceFunc) + shell_view_state_timeout_cb, shell_view); + + shell_view->priv->state_save_source_id = source_id; +} + +/** + * e_shell_view_update_actions: + * @shell_view: an #EShellView + * + * Emits the #EShellView::update-actions signal. + * + * #EShellView subclasses should implement the + * <structfield>update_actions</structfield> method in #EShellViewClass + * to update the various #GtkAction<!-- -->s based on the current + * #EShellSidebar and #EShellContent selections. The + * #EShellView::update-actions signal is typically emitted just before + * showing a popup menu or just after the user selects an item in the + * shell view. + **/ +void +e_shell_view_update_actions (EShellView *shell_view) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + g_signal_emit (shell_view, signals[UPDATE_ACTIONS], 0); +} + +/** + * e_shell_view_show_popup_menu: + * @shell_view: an #EShellView + * @widget_path: path in the UI definition + * @event: a #GdkEventButton + * + * Displays a context-sensitive (or "popup") menu that is described in + * the UI definition loaded into @shell_view<!-- -->'s user interface + * manager. The menu will be shown at the current mouse cursor position. + * + * The #EShellView::update-actions signal is emitted just prior to + * showing the menu to give @shell_view and any plugins that extend + * @shell_view a chance to update the menu's actions. + **/ +void +e_shell_view_show_popup_menu (EShellView *shell_view, + const gchar *widget_path, + GdkEventButton *event) +{ + EShellWindow *shell_window; + GtkWidget *menu; + + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + e_shell_view_update_actions (shell_view); + + shell_window = e_shell_view_get_shell_window (shell_view); + menu = e_shell_window_get_managed_widget (shell_window, widget_path); + g_return_if_fail (GTK_IS_MENU (menu)); + + if (event != NULL) + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button, event->time); + else + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time ()); +} + +/** + * e_shell_view_new_view_instance: + * @shell_view: an #EShellView + * @instance_id: a name for the #GalViewInstance + * + * Creates a new #GalViewInstance and configures it to keep + * @shell_view<!-- -->'s #EShellView:view-id property up-to-date. + * + * Returns: a new #GalViewInstance + **/ +GalViewInstance * +e_shell_view_new_view_instance (EShellView *shell_view, + const gchar *instance_id) +{ + EShellViewClass *class; + GalViewCollection *view_collection; + GalViewInstance *view_instance; + + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + class = E_SHELL_VIEW_GET_CLASS (shell_view); + + view_collection = class->view_collection; + view_instance = gal_view_instance_new (view_collection, instance_id); + + g_signal_connect_swapped ( + view_instance, "changed", + G_CALLBACK (shell_view_update_view_id), shell_view); + + return view_instance; +} diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index 1ca2656bb0..b9a12ab893 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -1,6 +1,5 @@ /* - * - * This is only a CORBA wrapper around e_shell_window. + * e-shell-view.h * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,46 +19,169 @@ * */ -#ifndef _E_SHELL_VIEW_H_ -#define _E_SHELL_VIEW_H_ - -#include <bonobo-activation/bonobo-activation.h> -#include <bonobo/bonobo-object.h> +/** + * SECTION: e-shell-view + * @short_description: views within the main window + * @include: shell/e-shell-view.h + **/ + +#ifndef E_SHELL_VIEW_H +#define E_SHELL_VIEW_H + +#include <shell/e-shell-common.h> +#include <shell/e-shell-backend.h> +#include <shell/e-shell-content.h> +#include <shell/e-shell-sidebar.h> +#include <shell/e-shell-taskbar.h> +#include <shell/e-shell-window.h> + +#include <widgets/menus/gal-view-collection.h> +#include <widgets/menus/gal-view-instance.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_VIEW \ + (e_shell_view_get_type ()) +#define E_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_VIEW, EShellView)) +#define E_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_VIEW, EShellViewClass)) +#define E_IS_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_VIEW)) +#define E_IS_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SHELL_VIEW)) +#define E_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_VIEW, EShellViewClass)) G_BEGIN_DECLS -struct _EShell; - -typedef struct _EShellView EShellView; +typedef struct _EShellView EShellView; +typedef struct _EShellViewClass EShellViewClass; typedef struct _EShellViewPrivate EShellViewPrivate; -typedef struct _EShellViewClass EShellViewClass; - -#include "Evolution.h" - -#define E_TYPE_SHELL_VIEW (e_shell_view_get_type ()) -#define E_SHELL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SHELL_VIEW, EShellView)) -#define E_SHELL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_VIEW, EShellViewClass)) -#define E_IS_SHELL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SHELL_VIEW)) -#define E_IS_SHELL_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_VIEW)) +/** + * EShellView: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ struct _EShellView { - BonoboObject parent; - - struct _EShellWindow *window; - + GObject parent; EShellViewPrivate *priv; }; +/** + * EShellViewClass: + * @parent_class: The parent class structure. + * @label: The initial value for the switcher action's + * #GtkAction:label property. See + * e_shell_view_get_action(). + * @icon_name: The initial value for the switcher action's + * #GtkAction:icon-name property. See + * e_shell_view_get_action(). + * @ui_definition: Base name of the UI definintion file to add + * when the shell view is activated. + * @ui_manager_id: The #GtkUIManager ID for #EPluginUI. Plugins + * should use to this ID in their "eplug" files to + * add menu and toolbar items to the shell view. + * @search_options: Widget path in the UI definition to the search + * options popup menu. The menu gets shown when the + * user clicks the "find" icon in the search entry. + * @search_rules: Base name of the XML file containing predefined + * search rules for this shell view. The XML files + * are usually named something like <filename> + * <emphasis>view</emphasis>types.xml</filename>. + * @view_collection: A unique #GalViewCollection instance is created + * for each subclass and shared across all instances + * of that subclass. That much is done automatically + * for subclasses, but subclasses are still responsible + * for adding the appropriate #GalView factories to the + * view collection. + * @shell_backend: The corresponding #EShellBackend for the shell view. + * @new_shell_content: Factory method for the shell view's #EShellContent. + * See e_shell_view_get_shell_content(). + * @new_shell_sidebar: Factory method for the shell view's #EShellSidebar. + * See e_shell_view_get_shell_sidebar(). + * @new_shell_taskbar: Factory method for the shell view's #EShellTaskbar. + * See e_shell_view_get_shell_taskbar(). + * @toggled: Class method for the #EShellView::toggled signal. + * Subclasses should rarely need to override the + * default behavior. + * @update_actions: Class method for the #EShellView::update_actions + * signal. There is no default behavior; subclasses + * should override this. + * + * #EShellViewClass contains a number of important settings for subclasses. + **/ struct _EShellViewClass { - BonoboObjectClass parent_class; + GObjectClass parent_class; - POA_GNOME_Evolution_ShellView__epv epv; + /* Initial switcher action values. */ + const gchar *label; + const gchar *icon_name; + + /* Base name of the UI definition file. */ + const gchar *ui_definition; + + /* GtkUIManager identifier for use with EPluginUI. + * Usually "org.gnome.evolution.$(VIEW_NAME)". */ + const gchar *ui_manager_id; + + /* Widget path to the search options popup menu. */ + const gchar *search_options; + + /* Base name of the search rule definition file. */ + const gchar *search_rules; + + /* A unique instance is created for each subclass. */ + GalViewCollection *view_collection; + + /* This is set by the corresponding EShellBackend. */ + EShellBackend *shell_backend; + + /* Factory Methods */ + GtkWidget * (*new_shell_content) (EShellView *shell_view); + GtkWidget * (*new_shell_sidebar) (EShellView *shell_view); + GtkWidget * (*new_shell_taskbar) (EShellView *shell_view); + + /* Signals */ + void (*toggled) (EShellView *shell_view); + void (*update_actions) (EShellView *shell_view); }; -GType e_shell_view_get_type (void); -EShellView *e_shell_view_new(struct _EShellWindow *window); +GType e_shell_view_get_type (void); +const gchar * e_shell_view_get_name (EShellView *shell_view); +GtkAction * e_shell_view_get_action (EShellView *shell_view); +const gchar * e_shell_view_get_title (EShellView *shell_view); +void e_shell_view_set_title (EShellView *shell_view, + const gchar *title); +const gchar * e_shell_view_get_view_id (EShellView *shell_view); +void e_shell_view_set_view_id (EShellView *shell_view, + const gchar *view_id); +gboolean e_shell_view_is_active (EShellView *shell_view); +gint e_shell_view_get_page_num (EShellView *shell_view); +void e_shell_view_set_page_num (EShellView *shell_view, + gint page_num); +GtkSizeGroup * e_shell_view_get_size_group (EShellView *shell_view); +EShellBackend * e_shell_view_get_shell_backend (EShellView *shell_view); +EShellContent * e_shell_view_get_shell_content (EShellView *shell_view); +EShellSidebar * e_shell_view_get_shell_sidebar (EShellView *shell_view); +EShellTaskbar * e_shell_view_get_shell_taskbar (EShellView *shell_view); +EShellWindow * e_shell_view_get_shell_window (EShellView *shell_view); +GKeyFile * e_shell_view_get_state_key_file (EShellView *shell_view); +void e_shell_view_set_state_dirty (EShellView *shell_view); +void e_shell_view_update_actions (EShellView *shell_view); +void e_shell_view_show_popup_menu (EShellView *shell_view, + const gchar *widget_path, + GdkEventButton *event); +GalViewInstance * + e_shell_view_new_view_instance (EShellView *shell_view, + const gchar *instance_id); G_END_DECLS -#endif /* _E_SHELL_VIEW_H_ */ - +#endif /* E_SHELL_VIEW_H */ diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c new file mode 100644 index 0000000000..77e50c50d4 --- /dev/null +++ b/shell/e-shell-window-actions.c @@ -0,0 +1,2242 @@ +/* + * e-shell-window-actions.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-window-private.h" + +#include <e-util/e-dialog-utils.h> +#include <e-util/e-error.h> +#include <e-util/e-print.h> +#include <gal-define-views-dialog.h> + +#include <libedataserverui/e-passwords.h> + +#include "e-shell-importer.h" + +#define EVOLUTION_COPYRIGHT \ + "Copyright \xC2\xA9 1999 - 2008 Novell, Inc. and Others" + +#define EVOLUTION_FAQ \ + "http://www.go-evolution.org/FAQ" + +#define EVOLUTION_WEBSITE \ + "http://www.gnome.org/projects/evolution/" + +/* Authors and Documenters + * + * The names below must be in UTF-8. The breaking of escaped strings + * is so the hexadecimal sequences don't swallow too many characters. + * + * SO THAT MEANS, FOR 8-BIT CHARACTERS USE \xXX HEX ENCODING ONLY! + * + * Not all environments are UTF-8 and not all editors can handle it. + */ +static const gchar *authors[] = { + "Aaron Weber", + "Abel Cheung", + "Abhishek Parwal", + "Adam Weinberger", + "Adi Attar", + "Ahmad Riza H Nst", + "Aidan Delaney", + "Aishwarya K", + "Akagic Amila", + "Akhil Laddha", + "Akira Tagoh", + "Alastair McKinstry", + "Alastair Tse", + "Alejandro Andres", + "Alessandro Decina", + "Alex Graveley", + "Alex Jiang", + "Alex Jones", + "Alex Kloss", + "Alexander Shopov", + "Alfred Peng", + "Ali Abdin", + "Ali Akcaagac", + "Almer S. Tigelaar", + "Amish", + "Anand V M", + "Anders Carlsson", + "Andre Klapper", + "Andrea Campi", + "Andreas Henriksson", + "Andreas Hyden", + "Andreas J. Guelzow", + "Andreas K\xC3\xB6hler", + "Andreas Köhler", + "Andrew Ruthven", + "Andrew T. Veliath", + "Andrew Wu", + "Ankit Patel", + "Anna Marie Dirks", + "Antonio Xu", + "Arafat Medini", + "Arangel Angov", + "Archit Baweja", + "Ariel Rios", + "Arik Devens", + "Armin Bauer", + "Arturo Espinosa Aldama", + "Arulanandan P", + "Arun Prakash", + "Arvind Sundararajan", + "Arvind", + "Ashish", + "B S Srinidhi", + "Bastien Nocera", + "Behnam Esfahbod", + "Ben Gamari", + "Benjamin Berg", + "Benjamin Kahn", + "Benoît Dejean", + "Bernard Leach", + "Bertrand Guiheneuf", + "Bharath Acharya", + "Bill Zhu", + "Bj\xC3\xB6rn Torkelsson", + "Björn Lindqvist", + "Bob Doan", + "Bob Mauchin", + "Boby Wang", + "Bolian Yin", + "Brian Mury", + "Brian Pepple", + "Bruce Tao", + "Calvin Liu", + "Cantona Su", + "Carl Sun", + "Carlos Garcia Campos", + "Carlos Garnacho Parro", + "Carlos Perell\xC3\xB3" " Mar\xC3\xAD" "n", + "Carsten Guenther", + "Carsten Schaar", + "Changwoo Ryu", + "Chao-Hsiung Liao", + "Charles Zhang", + "Chema Celorio", + "Chenthill Palanisamy", + "Chpe", + "Chris Halls", + "Chris Heath", + "Chris Phelps", + "Chris Toshok", + "Christian Hammond", + "Christian Kellner", + "Christian Kirbach", + "Christian Krause", + "Christian Kreibich", + "Christian Neumair", + "Christophe Fergeau", + "Christophe Merlet", + "Christopher Blizzard", + "Christopher J. Lahey", + "Christopher R. Gabriel", + "Claude Paroz", + "Claudio Saavedra", + "Clifford R. Conover", + "Cody Russell", + "Colin Leroy", + "Craig Small", + "Dafydd Harries", + "Damian Ivereigh", + "Damien Carbery", + "Damon Chaplin", + "Dan Berger", + "Dan Damian", + "Dan Nguyen", + "Dan Winship", + "Daniel Gryniewicz", + "Daniel Nylander", + "Daniel van Eeden", + "Daniel Veillard", + "Daniel Yacob", + "Danilo \xC5\xA0" "egan", + "Danilo Segan", + "Darin Adler", + "Dave Benson", + "Dave Camp", + "Dave Fallon", + "Dave Malcolm", + "Dave West", + "David Farning", + "David Kaelbling", + "David Malcolm", + "David Moore", + "David Mosberger", + "David Richards", + "David Trowbridge", + "David Turner", + "David Woodhouse", + "Denis Washington", + "Devashish Sharma", + "Diego Escalante Urrelo", + "Diego Gonzalez", + "Diego Sevilla Ruiz", + "Dietmar Maurer", + "Dinesh Layek", + "Djihed Afifi", + "Dmitry Mastrukov", + "Dodji Seketeli", + "Duarte Loreto", + "Dulmandakh Sukhbaatar", + "Duncan Mak", + "Ebby Wiselyn", + "Ed Catmur", + "Edd Dumbill", + "Edgar Luna Díaz", + "Edward Rudd", + "Elijah Newren", + "Elizabeth Greene", + "Elliot Lee", + "Elliot Turner", + "Eneko Lacunza", + "Enver Altin", + "Erdal Ronahi", + "Eric Busboom", + "Eric Zhao", + "Eskil Heyn Olsen", + "Ettore Perazzoli", + "Evan Yan", + "Fatih Demir", + "Fazlu & Hannah", + "Federico Mena Quintero", + "Fernando Herrera", + "Francisco Javier F. Serrador", + "Frank Arnold", + "Frank Belew", + "Frederic Crozat", + "Frederic Peters", + "Funda Wang", + "Gabor Kelemen", + "Ganesh", + "Gareth Owen", + "Gary Coady", + "Gary Ekker", + "Gavin Scott", + "Gediminas Paulauskas", + "Gerg\xC5\x91 \xC3\x89rdi", + "George Lebl", + "Gerardo Marin", + "Gert Kulyk", + "Giancarlo Capella", + "Gil Osher", + "Gilbert Fang", + "Gilles Dartiguelongue", + "Grahame Bowland", + "Greg Hudson", + "Gregory Leblanc", + "Gregory McLean", + "Grzegorz Goawski", + "Gustavo Gir\xC3\x8E" "ldez", + "Gustavo Maciel Dias Vieira", + "H P Nadig", + "H\xC3\xA9" "ctor Garc\xC3\xAD" "a \xC3\x81" "lvarez", + "Hans Petter Jansson", + "Hao Sheng", + "Hari Prasad Nadig", + "Harish K", + "Harish Krishnaswamy", + "Harry Lu", + "Hasbullah Bin Pit", + "Havoc Pennington", + "Heath Harrelson", + "Hein-Pieter van Braam", + "Herbert V. Riedel", + "Hiroyuki Ikezoe", + "Iain Buchanan", + "Iain Holmes", + "Ian Campbell", + "Ilkka Tuohela", + "Irene Huang", + "Ismael Olea", + "Israel Escalante", + "Iv\xC3\xA1" "n Frade", + "Iván Frade", + "J.H.M. Dassen (Ray)", + "JP Rosevear", + "J\xC3\xBC" "rg Billeter", + "Jürg Billeter", + "Jack Jia", + "Jacob Ulysses Berkman", + "Jacob Berkman", + "Jaka Mocnik", + "Jakub Steiner", + "James Doc Livingston", + "James Bowes", + "James Henstridge", + "James Willcox", + "Jan Arne Petersen", + "Jan Tichavsky", + "Jan Van Buggenhout", + "Jared Moore", + "Jarkko Ranta", + "Jason Leach", + "Jason Tackaberry", + "Jayaradha", + "Jean-Noel Guiheneuf", + "Jedy Wang", + "Jeff Bailey", + "Jeff Cai", + "Jeff Garzik", + "Jeffrey Stedfast", + "Jens Granseuer", + "Jens Seidel", + "Jeremy Katz", + "Jeremy Wise", + "Jerome Lacoste", + "Jerry Yu", + "Jes\xC3\xBA" "s Bravo \xC3\x81" "lvarez", + "Jesse Pavel", + "Ji Lee", + "Joan Sanfeliu", + "Jody Goldberg", + "Joe Marcus Clarke", + "Joe Shaw", + "John Gotts", + "Johnny Jacob", + "Johnny", + "Jon Ander Hernandez", + "Jon K Hellan", + "Jon Oberheide", + "Jon Trowbridge", + "Jonas Borgstr", + "Jonathan Blandford", + "Jonathan Dieter", + "Jos Dehaes", + "Josselin Mouette", + "JP Rosvear", + "Jukka Zitting", + "Jules Colding", + "Julian Missig", + "Julio M. Merino Vidal", + "Jürg Billeter", + "Karl Eichwalder", + "Karl Relton", + "Karsten Br\xC3\xA4" "ckelmann", + "Kaushal Kumar", + "Kenneth Christiansen", + "Kenny Graunke", + "Keshav Upadhyaya", + "Kevin Breit", + "Kevin Piche", + "Kevin Vandersloot", + "Khasim Shaheed", + "Kidd Wang", + "Kjartan Maraas", + "Krishnan R", + "Krisztian Pifko", + "Kyle Ambroff", + "Larry Ewing", + "Laszlo (Laca) Peter", + "Laurent Dhima", + "Lauris Kaplinski", + "Leon Zhang", + "Li Yuan", + "Loïc Minier", + "Loïc Minier", + "Lorenzo Gil Sanchez", + "Luca Ferretti", + "Lucky Wankhede", + "Luis Villa", + "Lutz M", + "M Victor Aloysius J", + "Maciej Stachowiak", + "Makuchaku", + "Malcolm Tredinnick", + "Marco Pesenti Gritti", + "Marius Andreiana", + "Marius Vollmer", + "Mark Crichton", + "Mark G. Adams", + "Mark Gordon", + "Mark McLoughlin", + "Mark Moulder", + "Mark Tearle", + "Martha Burke", + "Martin Baulig", + "Martin Hicks", + "Martin Meyer", + "Martin Norb\xC3\xA4" "ck", + "Martyn Russell", + "Masahiro Sakai", + "Mathieu Lacage", + "Matias Mutchinick", + "Matt Bissiri", + "Matt Brown", + "Matt Loper", + "Matt Martin", + "Matt Wilson", + "Matthew Barnes", + "Matthew Daniel", + "Matthew Hall", + "Matthew Loper", + "Matthew Wilson", + "Matthias Clasen", + "Max Horn", + "Maxx Cao", + "Mayank Jain", + "Meilof Veeningen", + "Mengjie Yu", + "Michael Granger", + "Michael M. Morrison", + "Michael MacDonald", + "Michael Meeks", + "Michael Monreal", + "Michael Terry", + "Michael Zucchi", + "Michel Daenzer", + "Miguel Angel Lopez Hernandez", + "Miguel de Icaza", + "Mikael Hallendal", + "Mikael Nilsson", + "Mike Castle", + "Mike Kestner", + "Mike McEwan", + "Mikhail Zabaluev", + "Milan Crha", + "Miles Lane", + "Mohammad Damt", + "Morten Welinder", + "Mubeen Jukaku", + "Murray Cumming", + "Naba Kumar", + "Nagappan Alagappan", + "Nancy Cai", + "Nat Friedman", + "Nathan Owens", + "Nicel KM", + "Nicholas J Kreucher", + "Nicholas Miell", + "Nick Sukharev", + "Nickolay V. Shmyrev", + "Nike Gerdts", + "Noel", + "Nuno Ferreira", + "Nyall Dawson", + "Ondrej Jirman", + "Oswald Rodrigues", + "Owen Taylor", + "Oystein Gisnas", + "P Chenthill", + "P S Chakravarthi", + "Pablo Gonzalo del Campo", + "Pablo Saratxaga", + "Pamplona Hackers", + "Paolo Molaro", + "Parag Goel", + "Parthasarathi Susarla", + "Pascal Terjan", + "Patrick Ohly", + "Paul Bolle", + "Paul Lindner", + "Pavel Cisler", + "Pavel Roskin", + "Pavithran", + "Pawan Chitrakar", + "Pedro Villavicencio", + "Peter Pouliot", + "Peter Teichman", + "Peter Williams", + "Peteris Krisjanis", + "Petta Pietikainen", + "Phil Goembel", + "Philip Van Hoof", + "Philip Zhao", + "Poornima Nayak", + "Pratik V. Parikh", + "Praveen Kumar", + "Priit Laes", + "Priyanshu Raj", + "Radek Doul\xC3\xADk", + "Raghavendran R", + "Raja R Harinath", + "Rajeev Ramanathan", + "Rajesh Ranjan", + "Rakesh k.g", + "Ramiro Estrugo", + "Ranjan Somani", + "Ray Strode", + "Rhys Jones", + "Ricardo Markiewicz", + "Richard Boulton", + "Richard Hult", + "Richard Li", + "Rob Bradford", + "Robert Brady", + "Robert Sedak", + "Robin Slomkowski", + "Rodney Dawes", + "Rodrigo Moya", + "Rohini S", + "Rohini", + "Roland Illig", + "Ronald Kuetemeier", + "Roozbeh Pournader", + "Ross Burton", + "Rouslan Solomakhin", + "Runa Bhattacharjee", + "Russell Steinthal", + "Rusty Conover", + "Ryan P. Skadberg", + "S Antony Vincent Pandian", + "S N Tejasvi", + "S. \xC3\x87" "a\xC4\x9F" "lar Onur", + "S.Antony Vincent Pandian", + "S. Caglar Onur", + "Sam Creasey", + "Sam Yang", + "Sam\xC3\xBA" "el J\xC3\xB3" "n Gunnarsson", + "Sankar P", + "Sanlig Badral", + "Sanshao Jiang", + "Sarfraaz Ahmed", + "Sayamindu Dasgupta", + "Sean Atkinson", + "Sean Gao", + "Sebastian Rittau", + "Sebastian Wilhelmi", + "Sebastien Bacher", + "Sergey Panov", + "Seth Alves", + "Seth Nickell", + "Shakti Sen", + "Shi Pu", + "Shilpa C", + "Shree Krishnan", + "Shreyas Srinivasan", + "Simon Zheng", + "Simos Xenitellis", + "Sivaiah Nallagatla", + "Srinivasa Ragavan", + "Stanislav Brabec", + "Stanislav Visnovsky", + "Stéphane Raimbault", + "Stephen Cook", + "Steve Murphy", + "Steven Zhang", + "Stuart Parmenter", + "Subodh Soni", + "Suman Manjunath", + "Sunil Mohan Adapa", + "Suresh Chandrasekharan", + "Sushma Rai", + "Sven Herzberg", + "Szabolcs Ban", + "T\xC3\xB5" "ivo Leedj\xC3\xA4" "rv", + "Takao Fujiwara", + "Takayuki Kusano", + "Takeshi Aihana", + "Tambet Ingo", + "Taylor Hayward", + "Ted Percival", + "Theppitak Karoonboonyanan", + "Thomas Cataldo", + "Thomas Klausner", + "Thomas Mirlacher", + "Thouis R. Jones", + "Tim Wo", + "Tim Yamin", + "Timo Hoenig", + "Timo Sirainen", + "Timothy Lee", + "Timur Bakeyev", + "Tino Meinen", + "Tobias Mueller", + "Tõivo Leedjärv", + "Tom Tromey", + "Tomas Ogren", + "Tomasz K\xC5\x82" "oczko", + "Tomislav Vujec", + "Tommi Komulainen", + "Tommi Vainikainen", + "Tony Tsui", + "Tor Lillqvist", + "Trent Lloyd", + "Tuomas J. Lukka", + "Tuomas Kuosmanen", + "Ulrich Neumann", + "Umesh Tiwari", + "Umeshtej", + "Ushveen Kaur", + "V Ravi Kumar Raju", + "Vadim Strizhevsky", + "Valek Filippov", + "Vandana Shenoy .B", + "Vardhman Jain", + "Veerapuram Varadhan", + "Vincent Noel", + "Vincent van Adrighem", + "Viren", + "Vivek Jain", + "Vladimer Sichinava", + "Vladimir Vukicevic", + "Wadim Dziedzic", + "Wang Jian", + "Wang Xin", + "Wayne Davis", + "William Jon McCann", + "Wouter Bolsterlee", + "Xan Lopez", + "Xiurong Simon Zheng", + "Yanko Kaneti", + "Yi Jin", + "Yong Sun", + "Yu Mengjie", + "Yuedong Du", + "Yukihiro Nakai", + "Yuri Pankov", + "Yuri Syrota", + "Zach Frey", + "Zan Lynx", + "Zbigniew Chyla", + "\xC3\x98ystein Gisn\xC3\xA5s", + "\xC5\xBDygimantas Beru\xC4\x8Dka", + NULL +}; + +static const gchar *documenters[] = { + "Aaron Weber", + "Binika Preet", + "Dan Winship", + "David Trowbridge", + "Jessica Prabhakar", + "JP Rosevear", + "Radhika Nair", + NULL +}; + +/** + * E_SHELL_WINDOW_ACTION_ABOUT: + * @window: an #EShellWindow + * + * Activation of this action displays the application's About dialog. + * + * Main menu item: Help -> About + **/ +static void +action_about_cb (GtkAction *action, + EShellWindow *shell_window) +{ + gchar *translator_credits; + + /* The translator-credits string is for translators to list + * per-language credits for translation, displayed in the + * about dialog. */ + translator_credits = _("translator-credits"); + if (strcmp (translator_credits, "translator-credits") == 0) + translator_credits = NULL; + + gtk_show_about_dialog ( + GTK_WINDOW (shell_window), + "program-name", "Evolution", + "version", VERSION, + "copyright", EVOLUTION_COPYRIGHT, + "comments", _("Groupware Suite"), + "website", EVOLUTION_WEBSITE, + "website-label", _("Evolution Website"), + "authors", authors, + "documenters", documenters, + "translator-credits", translator_credits, + "logo-icon-name", "evolution", + NULL); +} + +/** + * E_SHELL_WINDOW_ACTION_CLOSE: + * @window: an #EShellWindow + * + * Activation of this action closes @window. If this is the last window, + * the application initiates shutdown. + * + * Main menu item: File -> Close + **/ +static void +action_close_cb (GtkAction *action, + EShellWindow *shell_window) +{ + GtkWidget *widget = GTK_WIDGET (shell_window); + GdkEvent *event; + + /* Synthesize a delete_event on this window. */ + event = gdk_event_new (GDK_DELETE); + event->any.window = g_object_ref (widget->window); + event->any.send_event = TRUE; + gtk_main_do_event (event); + gdk_event_free (event); +} + +/** + * E_SHELL_WINDOW_ACTION_CONTENTS: + * @window: an #EShellWindow + * + * Activation of this action opens the application's user manual. + * + * Main menu item: Help -> Contents + **/ +static void +action_contents_cb (GtkAction *action, + EShellWindow *shell_window) +{ + e_display_help (GTK_WINDOW (shell_window), NULL); +} + +static void +action_custom_rule_cb (GtkAction *action, + EShellWindow *shell_window) +{ + FilterRule *rule; + EShellView *shell_view; + EShellContent *shell_content; + const gchar *view_name; + + rule = g_object_get_data (G_OBJECT (action), "rule"); + g_return_if_fail (rule != NULL); + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_content = e_shell_view_get_shell_content (shell_view); + + rule = g_object_get_data (G_OBJECT (action), "rule"); + g_return_if_fail (IS_FILTER_RULE (rule)); + + e_shell_content_set_search_rule (shell_content, rule); + gtk_action_activate (ACTION (SEARCH_EXECUTE)); +} + +/** + * E_SHELL_WINDOW_ACTION_FAQ: + * @window: an #EShellWindow + * + * Activation of this action opens a web page with answers to frequently + * asked questions about this application. + * + * Main menu item: Help -> Evolution FAQ + **/ +static void +action_faq_cb (GtkAction *action, + EShellWindow *shell_window) +{ + e_show_uri (GTK_WINDOW (shell_window), EVOLUTION_FAQ); +} + +/** + * E_SHELL_WINDOW_ACTION_FORGET_PASSWORDS: + * @window: an #EShellWindow + * + * Activation of this action deletes all stored passwords. + * + * Main menu item: File -> Forget Passwords + **/ +static void +action_forget_passwords_cb (GtkAction *action, + EShellWindow *shell_window) +{ + gint response; + + response = e_error_run ( + GTK_WINDOW (shell_window), "shell:forget-passwords", NULL); + + if (response == GTK_RESPONSE_OK) + e_passwords_forget_passwords (); +} + +/** + * E_SHELL_WINDOW_ACTION_GAL_DEFINE_VIEWS: + * @window: an #EShellWindow + * + * Activation of this action opens a dialog for editing GAL views for + * the current shell view. + * + * Main menu item: View -> Current View -> Define Views... + **/ +static void +action_gal_define_views_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellViewClass *shell_view_class; + GalViewCollection *view_collection; + GtkWidget *dialog; + const gchar *view_name; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + view_collection = shell_view_class->view_collection; + g_return_if_fail (view_collection != NULL); + + dialog = gal_define_views_dialog_new (view_collection); + gtk_dialog_run (GTK_DIALOG (dialog)); + gal_view_collection_save (view_collection); + gtk_widget_destroy (dialog); + + e_shell_window_update_view_menu (shell_window); +} + +/** + * E_SHELL_WINDOW_ACTION_GAL_CUSTOM_VIEW: + * @window: an #EShellWindow + * + * This radio action is selected when using a custom GAL view that has + * not been saved. + * + * Main menu item: View -> Current View -> Custom View + **/ +static void +action_gal_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + EShellWindow *shell_window) +{ + EShellView *shell_view; + const gchar *view_name; + const gchar *view_id; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + view_id = g_object_get_data (G_OBJECT (current), "view-id"); + e_shell_view_set_view_id (shell_view, view_id); +} + +/** + * E_SHELL_WINDOW_ACTION_GAL_SAVE_CUSTOM_VIEW: + * @window: an #EShellWindow + * + * Activation of this action saves a custom GAL view. + * + * Main menu item: View -> Current View -> Save Custom View... + **/ + +/** + * E_SHELL_WINDOW_ACTION_IMPORT: + * @window: an #EShellWindow + * + * Activation of this action opens the Evolution Import Assistant. + * + * Main menu item: File -> Import... + **/ +static void +action_import_cb (GtkAction *action, + EShellWindow *shell_window) +{ + e_shell_importer_start_import (shell_window); +} + +/** + * E_SHELL_WINDOW_ACTION_NEW_WINDOW: + * @window: an #EShellWindow + * + * Activation of this action opens a new shell window. + * + * Main menu item: File -> New Window + **/ +static void +action_new_window_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + const gchar *view_name; + + shell = e_shell_window_get_shell (shell_window); + view_name = e_shell_window_get_active_view (shell_window); + + e_shell_create_shell_window (shell, view_name); +} + +/** + * E_SHELL_WINDOW_ACTION_PAGE_SETUP: + * @window: an #EShellWindow + * + * Activation of this action opens the application's Page Setup dialog. + * + * Main menu item: File -> Page Setup... + **/ +static void +action_page_setup_cb (GtkAction *action, + EShellWindow *shell_window) +{ + e_print_run_page_setup_dialog (GTK_WINDOW (shell_window)); +} + +/** + * E_SHELL_WINDOW_ACTION_PREFERENCES: + * @window: an #EShellWindow + * + * Activation of this action opens the application's Preferences window. + * + * Main menu item: Edit -> Preferences + **/ +static void +action_preferences_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + GtkWidget *preferences_window; + + shell = e_shell_window_get_shell (shell_window); + preferences_window = e_shell_get_preferences_window (shell); + + gtk_window_set_transient_for ( + GTK_WINDOW (preferences_window), + GTK_WINDOW (shell_window)); + gtk_window_set_position ( + GTK_WINDOW (preferences_window), + GTK_WIN_POS_CENTER_ON_PARENT); + gtk_window_present (GTK_WINDOW (preferences_window)); + + /* FIXME Switch to a page appropriate for the current view. */ +} + +/** + * E_SHELL_WINDOW_ACTION_QUICK_REFERENCE: + * @window: an #EShellWindow + * + * Activation of this action opens a printable table of useful shortcut + * keys for this application. + * + * Main menu item: Help -> Quick Reference + **/ +static void +action_quick_reference_cb (GtkAction *action, + EShellWindow *shell_window) +{ + const gchar * const *language_names; + + language_names = g_get_language_names (); + while (*language_names != NULL) { + const gchar *language = *language_names++; + gchar *filename; + + /* This must be a valid language AND a language with + * no encoding suffix. The next language should have + * no encoding suffix. */ + if (language == NULL || strchr (language, '.') != NULL) + continue; + + filename = g_build_filename ( + EVOLUTION_HELPDIR, "quickref", + language, "quickref.pdf", NULL); + + if (g_file_test (filename, G_FILE_TEST_EXISTS)) { + GFile *file; + gchar *uri; + GError *error = NULL; + + file = g_file_new_for_path (filename); + uri = g_file_get_uri (file); + + g_app_info_launch_default_for_uri (uri, NULL, &error); + + if (error != NULL) { + /* FIXME Show an error dialog. */ + g_warning ("%s", error->message); + g_error_free (error); + } + + g_object_unref (file); + g_free (uri); + } + + g_free (filename); + } +} + +/** + * E_SHELL_WINDOW_ACTION_QUIT: + * @window: an #EShellWindow + * + * Activation of this action initiates application shutdown. + * + * Main menu item: File -> Quit + **/ +static void +action_quit_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + + shell = e_shell_window_get_shell (shell_window); + e_shell_quit (shell); +} + +/** + * E_SHELL_WINDOW_ACTION_SEARCH_ADVANCED: + * @window: an #EShellWindow + * + * Activation of this action opens an Advanced Search dialog. + * + * Main menu item: Search -> Advanced Search... + **/ +static void +action_search_advanced_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *view_name; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_content = e_shell_view_get_shell_content (shell_view); + + e_shell_content_run_advanced_search_dialog (shell_content); + e_shell_window_update_search_menu (shell_window); +} + +/** + * E_SHELL_WINDOW_ACTION_SEARCH_CLEAR: + * @window: an #EShellWindow + * + * Activation of this action clears the most recent search results. + * + * Main menu item: Search -> Clear + **/ +static void +action_search_clear_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *view_name; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_content = e_shell_view_get_shell_content (shell_view); + + e_shell_content_set_search_rule (shell_content, NULL); + e_shell_content_set_search_text (shell_content, NULL); + + gtk_action_activate (ACTION (SEARCH_EXECUTE)); + + e_shell_window_update_search_menu (shell_window); +} + +/** + * E_SHELL_WINDOW_ACTION_SEARCH_EDIT: + * @window: an #EShellWindow + * + * Activation of this action opens a dialog for editing saved searches. + * + * Main menu item: Search -> Edit Saved Searches... + **/ +static void +action_search_edit_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *view_name; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_content = e_shell_view_get_shell_content (shell_view); + + e_shell_content_run_edit_searches_dialog (shell_content); + e_shell_window_update_search_menu (shell_window); +} + +/** + * E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE: + * @window: an #EShellWindow + * + * Activation of this action executes the current search conditions. + * + * Main menu item: Search -> Find Now + **/ + +/** + * E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS: + * @window: an #EShellWindow + * + * Activation of this action displays a menu of search options. + * This appears as a "find" icon in the window's search entry. + **/ +static void +action_search_options_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellViewClass *shell_view_class; + const gchar *view_name; + const gchar *widget_path; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + + widget_path = shell_view_class->search_options; + e_shell_view_show_popup_menu (shell_view, widget_path, NULL); +} + +/** + * E_SHELL_WINDOW_ACTION_SEARCH_SAVE: + * @window: an #EShellWindow + * + * Activation of this action saves the current search conditions. + * + * Main menu item: Search -> Save Search... + **/ +static void +action_search_save_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellContent *shell_content; + const gchar *view_name; + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_content = e_shell_view_get_shell_content (shell_view); + + e_shell_content_run_save_search_dialog (shell_content); + e_shell_window_update_search_menu (shell_window); +} + +/** + * E_SHELL_WINDOW_ACTION_SEND_RECEIVE: + * @window: an #EShellWindow + * + * Activation of this action opens the Send & Receive Mail dialog. + * + * Main menu item: File -> Send / Receive + **/ +static void +action_send_receive_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + + shell = e_shell_window_get_shell (shell_window); + e_shell_send_receive (shell, GTK_WINDOW (shell_window)); +} + +/** + * E_SHELL_WINDOW_ACTION_SHOW_SIDEBAR: + * @window: an #EShellWindow + * + * This toggle action controls whether the side bar is visible. + * + * Main menu item: View -> Layout -> Show Side Bar + **/ +static void +action_show_sidebar_cb (GtkToggleAction *action, + EShellWindow *shell_window) +{ + GtkPaned *paned; + GtkWidget *widget; + gboolean active; + + paned = GTK_PANED (shell_window->priv->content_pane); + + widget = gtk_paned_get_child1 (paned); + active = gtk_toggle_action_get_active (action); + g_object_set (widget, "visible", active, NULL); +} + +/** + * E_SHELL_WINDOW_ACTION_SHOW_STATUSBAR: + * @window: an #EShellWindow + * + * This toggle action controls whether the status bar is visible. + * + * Main menu item: View -> Layout -> Show Status Bar + **/ +static void +action_show_statusbar_cb (GtkToggleAction *action, + EShellWindow *shell_window) +{ + GtkWidget *widget; + gboolean active; + + widget = shell_window->priv->status_area; + active = gtk_toggle_action_get_active (action); + g_object_set (widget, "visible", active, NULL); +} + +/** + * E_SHELL_WINDOW_ACTION_SHOW_SWITCHER: + * @window: an #EShellWindow + * + * This toggle action controls whether the switcher buttons are visible. + * + * Main menu item: View -> Switcher Appearance -> Show Buttons + **/ +static void +action_show_switcher_cb (GtkToggleAction *action, + EShellWindow *shell_window) +{ + EShellSwitcher *switcher; + gboolean active; + + switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); + active = gtk_toggle_action_get_active (action); + e_shell_switcher_set_visible (switcher, active); +} + +/** + * E_SHELL_WINDOW_ACTION_SHOW_TOOLBAR: + * @window: an #EShellWindow + * + * This toggle action controls whether the tool bar is visible. + * + * Main menu item: View -> Layout -> Show Tool Bar + **/ +static void +action_show_toolbar_cb (GtkToggleAction *action, + EShellWindow *shell_window) +{ + GtkWidget *widget; + gboolean active; + + widget = shell_window->priv->main_toolbar; + active = gtk_toggle_action_get_active (action); + g_object_set (widget, "visible", active, NULL); +} + +/** + * E_SHELL_WINDOW_ACTION_SUBMIT_BUG: + * @window: an #EShellWindow + * + * Activation of this action allows users to report a bug using + * Bug Buddy. + * + * Main menu item: Help -> Submit Bug Report + **/ +static void +action_submit_bug_cb (GtkAction *action, + EShellWindow *shell_window) +{ + const gchar *command_line; + GError *error = NULL; + + command_line = "bug-buddy --package=Evolution"; + + g_debug ("Spawning: %s", command_line); + g_spawn_command_line_async (command_line, &error); + + if (error != NULL) { + const gchar *message; + + if (error->code == G_SPAWN_ERROR_NOENT) + message = _("Bug Buddy is not installed."); + else + message = _("Bug Buddy could not be run."); + e_notice (shell_window, GTK_MESSAGE_ERROR, message); + g_error_free (error); + } +} + +static void +action_switcher_cb (GtkRadioAction *action, + GtkRadioAction *current, + EShellWindow *shell_window) +{ + const gchar *view_name; + + view_name = g_object_get_data (G_OBJECT (current), "view-name"); + e_shell_window_switch_to_view (shell_window, view_name); +} + +/** + * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_BOTH: + * @window: an #EShellWindow + * + * This radio action displays switcher buttons with icons and text. + * + * Main menu item: View -> Switcher Appearance -> Icons and Text + **/ + +/** + * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_ICONS: + * @window: an #EShellWindow + * + * This radio action displays switcher buttons with icons only. + * + * Main menu item: View -> Switcher Appearance -> Icons Only + **/ + +/** + * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_TEXT: + * @window: an #EShellWindow + * + * This radio action displays switcher buttons with text only. + * + * Main menu item: View -> Switcher Appearance -> Text Only + **/ + +/** + * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_USER: + * @window: an #EShellWindow + * + * This radio action displays switcher buttons according to the desktop + * toolbar setting. + * + * Main menu item: View -> Switcher Appearance -> Toolbar Style + **/ +static void +action_switcher_style_cb (GtkRadioAction *action, + GtkRadioAction *current, + EShellWindow *shell_window) +{ + EShellSwitcher *switcher; + GtkToolbarStyle style; + + switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); + style = gtk_radio_action_get_current_value (action); + + switch (style) { + case GTK_TOOLBAR_ICONS: + case GTK_TOOLBAR_TEXT: + case GTK_TOOLBAR_BOTH: + case GTK_TOOLBAR_BOTH_HORIZ: + e_shell_switcher_set_style (switcher, style); + break; + + default: + e_shell_switcher_unset_style (switcher); + break; + } +} + +/** + * E_SHELL_WINDOW_ACTION_SYNC_OPTIONS: + * @window: an #EShellWindow + * + * Activation of this action opens the Gnome Pilot settings. + * + * Main menu item: Edit -> Synchronization Options... + **/ +static void +action_sync_options_cb (GtkAction *action, + EShellWindow *shell_window) +{ + const gchar *command_line; + GError *error = NULL; + + command_line = "gpilotd-control-applet"; + + g_debug ("Spawning: %s", command_line); + g_spawn_command_line_async (command_line, &error); + + if (error != NULL) { + const gchar *message; + + if (error->code == G_SPAWN_ERROR_NOENT) + message = _("GNOME Pilot is not installed."); + else + message = _("GNOME Pilot could not be run."); + e_notice (shell_window, GTK_MESSAGE_ERROR, message); + g_error_free (error); + } +} + +/** + * E_SHELL_WINDOW_ACTION_WORK_OFFLINE: + * @window: an #EShellWindow + * + * Activation of this action puts the application into offline mode. + * + * Main menu item: File -> Work Offline + **/ +static void +action_work_offline_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + EShellSettings *shell_settings; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_set_online (shell, FALSE); + + /* XXX The sense of the setting is reversed. Would be more + * intuitive and less error-prone as "start-online". */ + e_shell_settings_set_boolean ( + shell_settings, "start-offline", TRUE); +} + +/** + * E_SHELL_WINDOW_ACTION_WORK_ONLINE: + * @window: an #EShellWindow + * + * Activation of this action puts the application into online mode. + * + * Main menu item: File -> Work Online + **/ +static void +action_work_online_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShell *shell; + EShellSettings *shell_settings; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_set_online (shell, TRUE); + + /* XXX The sense of the setting is reversed. Would be more + * intuitive and less error-prone as "start-online". */ + e_shell_settings_set_boolean ( + shell_settings, "start-offline", FALSE); +} + +/** + * E_SHELL_WINDOW_ACTION_GROUP_CUSTOM_RULES: + * @window: an #EShellWindow + **/ + +/** + * E_SHELL_WINDOW_ACTION_GROUP_GAL_VIEW: + * @window: an #EShellWindow + **/ + +/** + * E_SHELL_WINDOW_ACTION_GROUP_NEW_ITEM: + * @window: an #EShellWindow + **/ + +/** + * E_SHELL_WINDOW_ACTION_GROUP_NEW_SOURCE: + * @window: an #EShellWindow + **/ + +/** + * E_SHELL_WINDOW_ACTION_GROUP_SHELL: + * @window: an #EShellWindow + **/ + +/** + * E_SHELL_WINDOW_ACTION_GROUP_SWITCHER: + * @window: an #EShellWindow + **/ + +static GtkActionEntry shell_entries[] = { + + { "about", + GTK_STOCK_ABOUT, + NULL, + NULL, + N_("Show information about Evolution"), + G_CALLBACK (action_about_cb) }, + + { "close", + GTK_STOCK_CLOSE, + N_("_Close Window"), + "<Control>w", + N_("Close this window"), + G_CALLBACK (action_close_cb) }, + + { "contents", + GTK_STOCK_HELP, + N_("_Contents"), + "F1", + N_("Open the Evolution User Guide"), + G_CALLBACK (action_contents_cb) }, + + { "faq", + "help-faq", + N_("Evolution _FAQ"), + NULL, + N_("Open the Frequently Asked Questions webpage"), + G_CALLBACK (action_faq_cb) }, + + { "forget-passwords", + NULL, + N_("_Forget Passwords"), + NULL, + N_("Forget all remembered passwords"), + G_CALLBACK (action_forget_passwords_cb) }, + + { "import", + "stock_mail-import", + N_("I_mport..."), + NULL, + N_("Import data from other programs"), + G_CALLBACK (action_import_cb) }, + + { "new-window", + "window-new", + N_("New _Window"), + "<Control><Shift>w", + N_("Create a new window displaying this view"), + G_CALLBACK (action_new_window_cb) }, + + { "preferences", + GTK_STOCK_PREFERENCES, + NULL, + "<Control><Shift>s", + N_("Configure Evolution"), + G_CALLBACK (action_preferences_cb) }, + + { "quick-reference", + NULL, + N_("_Quick Reference"), + NULL, + N_("Show Evolution's shortcut keys"), + G_CALLBACK (action_quick_reference_cb) }, + + { "quit", + GTK_STOCK_QUIT, + NULL, + NULL, + N_("Exit the program"), + G_CALLBACK (action_quit_cb) }, + + { "search-advanced", + NULL, + N_("_Advanced Search..."), + NULL, + N_("Construct a more advanced search"), + G_CALLBACK (action_search_advanced_cb) }, + + { "search-clear", + GTK_STOCK_CLEAR, + NULL, + "<Control><Shift>q", + N_("Clear the current search parameters"), + G_CALLBACK (action_search_clear_cb) }, + + { "search-edit", + NULL, + N_("_Edit Saved Searches..."), + NULL, + N_("Manage your saved searches"), + G_CALLBACK (action_search_edit_cb) }, + + { "search-execute", + GTK_STOCK_FIND, + N_("_Find Now"), + "", /* Block the default Ctrl+F. */ + N_("Execute the current search parameters"), + NULL }, /* Handled by EShellContent and subclasses. */ + + { "search-options", + GTK_STOCK_FIND, + NULL, + NULL, + N_("Click here to change the search type"), + G_CALLBACK (action_search_options_cb) }, + + { "search-save", + NULL, + N_("_Save Search..."), + NULL, + N_("Save the current search parameters"), + G_CALLBACK (action_search_save_cb) }, + + { "send-receive", + "mail-send-receive", + N_("Send / _Receive"), + "F9", + N_("Send queued items and retrieve new items"), + G_CALLBACK (action_send_receive_cb) }, + + { "submit-bug", + NULL, + N_("Submit _Bug Report..."), + NULL, + N_("Submit a bug report using Bug Buddy"), + G_CALLBACK (action_submit_bug_cb) }, + + { "sync-options", + NULL, + N_("_Synchronization Options..."), + NULL, + N_("Set up Pilot configuration"), + G_CALLBACK (action_sync_options_cb) }, + + { "work-offline", + "stock_disconnect", + N_("_Work Offline"), + NULL, + N_("Put Evolution into offline mode"), + G_CALLBACK (action_work_offline_cb) }, + + { "work-online", + "stock_connect", + N_("_Work Online"), + NULL, + N_("Put Evolution into online mode"), + G_CALLBACK (action_work_online_cb) }, + + /*** Menus ***/ + + { "edit-menu", + NULL, + N_("_Edit"), + NULL, + NULL, + NULL }, + + { "file-menu", + NULL, + N_("_File"), + NULL, + NULL, + NULL }, + + { "help-menu", + NULL, + N_("_Help"), + NULL, + NULL, + NULL }, + + { "layout-menu", + NULL, + N_("Lay_out"), + NULL, + NULL, + NULL }, + + { "new-menu", + GTK_STOCK_NEW, + N_("_New"), + "", + NULL, + NULL }, + + { "search-menu", + NULL, + N_("_Search"), + NULL, + NULL, + NULL }, + + { "switcher-menu", + NULL, + N_("_Switcher Appearance"), + NULL, + NULL, + NULL }, + + { "view-menu", + NULL, + N_("_View"), + NULL, + NULL, + NULL }, + + { "window-menu", + NULL, + N_("_Window"), + NULL, + NULL, + NULL } +}; + +static GtkToggleActionEntry shell_toggle_entries[] = { + + { "show-sidebar", + NULL, + N_("Show Side _Bar"), + NULL, + N_("Show the side bar"), + G_CALLBACK (action_show_sidebar_cb), + TRUE }, + + { "show-statusbar", + NULL, + N_("Show _Status Bar"), + NULL, + N_("Show the status bar"), + G_CALLBACK (action_show_statusbar_cb), + TRUE }, + + { "show-switcher", + NULL, + N_("Show _Buttons"), + NULL, + N_("Show the switcher buttons"), + G_CALLBACK (action_show_switcher_cb), + TRUE }, + + { "show-toolbar", + NULL, + N_("Show _Tool Bar"), + NULL, + N_("Show the toolbar"), + G_CALLBACK (action_show_toolbar_cb), + TRUE } +}; + +static GtkRadioActionEntry shell_switcher_entries[] = { + + /* This action represents the initial active shell view. + * It should not be visible in the UI, nor should it be + * possible to switch to it from another shell view. */ + { "switcher-initial", + NULL, + NULL, + NULL, + NULL, + -1 } +}; + +static GtkRadioActionEntry shell_switcher_style_entries[] = { + + { "switcher-style-icons", + NULL, + N_("_Icons Only"), + NULL, + N_("Display window buttons with icons only"), + GTK_TOOLBAR_ICONS }, + + { "switcher-style-text", + NULL, + N_("_Text Only"), + NULL, + N_("Display window buttons with text only"), + GTK_TOOLBAR_TEXT }, + + { "switcher-style-both", + NULL, + N_("Icons _and Text"), + NULL, + N_("Display window buttons with icons and text"), + GTK_TOOLBAR_BOTH_HORIZ }, + + { "switcher-style-user", + NULL, + N_("Tool_bar Style"), + NULL, + N_("Display window buttons using the desktop toolbar setting"), + -1 } +}; + +static GtkActionEntry shell_gal_view_entries[] = { + + { "gal-define-views", + NULL, + N_("Define Views..."), + NULL, + N_("Create or edit views"), + G_CALLBACK (action_gal_define_views_cb) }, + + { "gal-save-custom-view", + NULL, + N_("Save Custom View..."), + NULL, + N_("Save current custom view"), + NULL }, /* Handled by subclasses. */ + + /*** Menus ***/ + + { "gal-view-menu", + NULL, + N_("C_urrent View"), + NULL, + NULL, + NULL } +}; + +static GtkRadioActionEntry shell_gal_view_radio_entries[] = { + + { "gal-custom-view", + NULL, + N_("Custom View"), + NULL, + N_("Current view is a customized view"), + -1 } +}; + +static GtkActionEntry shell_lockdown_print_setup_entries[] = { + + { "page-setup", + GTK_STOCK_PAGE_SETUP, + NULL, + NULL, + N_("Change the page settings for your current printer"), + G_CALLBACK (action_page_setup_cb) } +}; + +static void +shell_window_extract_actions (EShellWindow *shell_window, + GList **source_list, + GList **destination_list) +{ + const gchar *current_view; + GList *match_list = NULL; + GList *iter; + + /* Pick out the actions from the source list that are tagged + * as belonging to the current EShellView and move them to the + * destination list. */ + + current_view = e_shell_window_get_active_view (shell_window); + + /* Example: Suppose [A] and [C] are tagged for this EShellView. + * + * source_list = [A] -> [B] -> [C] + * ^ ^ + * | | + * match_list = [ ] --------> [ ] + * + * + * destination_list = [1] -> [2] (other actions) + */ + for (iter = *source_list; iter != NULL; iter = iter->next) { + GtkAction *action = iter->data; + const gchar *backend_name; + + backend_name = g_object_get_data ( + G_OBJECT (action), "backend-name"); + + if (strcmp (backend_name, current_view) != 0) + continue; + + if (g_object_get_data (G_OBJECT (action), "primary")) + match_list = g_list_prepend (match_list, iter); + else + match_list = g_list_append (match_list, iter); + } + + /* source_list = [B] match_list = [A] -> [C] */ + for (iter = match_list; iter != NULL; iter = iter->next) { + GList *link = iter->data; + + iter->data = link->data; + *source_list = g_list_delete_link (*source_list, link); + } + + /* destination_list = [1] -> [2] -> [A] -> [C] */ + *destination_list = g_list_concat (*destination_list, match_list); +} + +void +e_shell_window_actions_init (EShellWindow *shell_window) +{ + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + + ui_manager = e_shell_window_get_ui_manager (shell_window); + + e_load_ui_definition (ui_manager, "evolution-shell.ui"); + + /* Shell Actions */ + action_group = ACTION_GROUP (SHELL); + gtk_action_group_add_actions ( + action_group, shell_entries, + G_N_ELEMENTS (shell_entries), shell_window); + gtk_action_group_add_toggle_actions ( + action_group, shell_toggle_entries, + G_N_ELEMENTS (shell_toggle_entries), shell_window); + gtk_action_group_add_radio_actions ( + action_group, shell_switcher_style_entries, + G_N_ELEMENTS (shell_switcher_style_entries), + E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE, + G_CALLBACK (action_switcher_style_cb), shell_window); + gtk_action_group_add_actions ( + action_group, shell_gal_view_entries, + G_N_ELEMENTS (shell_gal_view_entries), shell_window); + gtk_action_group_add_radio_actions ( + action_group, shell_gal_view_radio_entries, + G_N_ELEMENTS (shell_gal_view_radio_entries), + 0, G_CALLBACK (action_gal_view_cb), shell_window); + + /* Switcher Actions */ + action_group = ACTION_GROUP (SWITCHER); + gtk_action_group_add_radio_actions ( + action_group, shell_switcher_entries, + G_N_ELEMENTS (shell_switcher_entries), + -1, G_CALLBACK (action_switcher_cb), shell_window); + + /* Lockdown Print Setup Actions */ + action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP); + gtk_action_group_add_actions ( + action_group, shell_lockdown_print_setup_entries, + G_N_ELEMENTS (shell_lockdown_print_setup_entries), + shell_window); + + /* Fine tuning. */ + + g_object_set (ACTION (SEND_RECEIVE), "is-important", TRUE, NULL); +} + +GtkWidget * +e_shell_window_create_new_menu (EShellWindow *shell_window) +{ + GtkActionGroup *action_group; + GList *new_item_actions; + GList *new_source_actions; + GList *iter, *list = NULL; + GtkWidget *menu; + GtkWidget *separator; + + /* Get sorted lists of "new item" and "new source" actions. */ + + action_group = ACTION_GROUP (NEW_ITEM); + + new_item_actions = g_list_sort ( + gtk_action_group_list_actions (action_group), + (GCompareFunc) e_action_compare_by_label); + + action_group = ACTION_GROUP (NEW_SOURCE); + + new_source_actions = g_list_sort ( + gtk_action_group_list_actions (action_group), + (GCompareFunc) e_action_compare_by_label); + + /* Give priority to actions that belong to this shell view. */ + + shell_window_extract_actions ( + shell_window, &new_item_actions, &list); + + shell_window_extract_actions ( + shell_window, &new_source_actions, &list); + + /* Convert the actions to menu item proxy widgets. */ + + for (iter = list; iter != NULL; iter = iter->next) + iter->data = gtk_action_create_menu_item (iter->data); + + for (iter = new_item_actions; iter != NULL; iter = iter->next) + iter->data = gtk_action_create_menu_item (iter->data); + + for (iter = new_source_actions; iter != NULL; iter = iter->next) + iter->data = gtk_action_create_menu_item (iter->data); + + /* Add menu separators. */ + + separator = gtk_separator_menu_item_new (); + new_item_actions = g_list_prepend (new_item_actions, separator); + gtk_widget_show (GTK_WIDGET (separator)); + + separator = gtk_separator_menu_item_new (); + new_source_actions = g_list_prepend (new_source_actions, separator); + gtk_widget_show (GTK_WIDGET (separator)); + + /* Merge everything into one list, reflecting the menu layout. */ + + list = g_list_concat (list, new_item_actions); + new_item_actions = NULL; /* just for clarity */ + + list = g_list_concat (list, new_source_actions); + new_source_actions = NULL; /* just for clarity */ + + /* And finally, build the menu. */ + + menu = gtk_menu_new (); + + for (iter = list; iter != NULL; iter = iter->next) + gtk_menu_shell_append (GTK_MENU_SHELL (menu), iter->data); + + g_list_free (list); + + return menu; +} + +void +e_shell_window_create_switcher_actions (EShellWindow *shell_window) +{ + GSList *group = NULL; + GtkRadioAction *action; + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + EShellSwitcher *switcher; + EShell *shell; + GList *list, *iter; + guint merge_id; + guint ii = 0; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + + action_group = ACTION_GROUP (SWITCHER); + switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); + ui_manager = e_shell_window_get_ui_manager (shell_window); + merge_id = gtk_ui_manager_new_merge_id (ui_manager); + shell = e_shell_window_get_shell (shell_window); + list = e_shell_get_shell_backends (shell); + + /* Construct a group of radio actions from the various EShellView + * subclasses and register them with the EShellSwitcher. These + * actions are manifested as switcher buttons and View->Window + * menu items. */ + + action = GTK_RADIO_ACTION (ACTION (SWITCHER_INITIAL)); + gtk_radio_action_set_group (action, group); + group = gtk_radio_action_get_group (action); + + for (iter = list; iter != NULL; iter = iter->next) { + EShellBackend *shell_backend = iter->data; + EShellBackendClass *backend_class; + EShellViewClass *class; + GType view_type; + const gchar *view_name; + gchar *accelerator; + gchar *action_name; + gchar *tooltip; + + /* The backend name is also the view name. */ + backend_class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + view_type = backend_class->shell_view_type; + view_name = backend_class->name; + + if (!g_type_is_a (view_type, E_TYPE_SHELL_VIEW)) { + g_critical ( + "%s is not a subclass of %s", + g_type_name (view_type), + g_type_name (E_TYPE_SHELL_VIEW)); + continue; + } + + class = g_type_class_ref (view_type); + + if (class->label == NULL) { + g_critical ( + "Label member not set on %s", + G_OBJECT_CLASS_NAME (class)); + continue; + } + + action_name = g_strdup_printf (SWITCHER_FORMAT, view_name); + tooltip = g_strdup_printf (_("Switch to %s"), class->label); + + /* Note, we have to set "icon-name" separately because + * gtk_radio_action_new() expects a "stock-id". Sadly, + * GTK+ still distinguishes between the two. */ + + action = gtk_radio_action_new ( + action_name, class->label, + tooltip, NULL, ii++); + + g_object_set ( + G_OBJECT (action), + "icon-name", class->icon_name, NULL); + + g_object_set_data ( + G_OBJECT (action), + "view-name", (gpointer) view_name); + + gtk_radio_action_set_group (action, group); + group = gtk_radio_action_get_group (action); + + /* The first nine views have accelerators Ctrl+(1-9). */ + if (ii < 10) + accelerator = g_strdup_printf ("<Control>%d", ii); + else + accelerator = g_strdup (""); + + gtk_action_group_add_action_with_accel ( + action_group, GTK_ACTION (action), accelerator); + + e_shell_switcher_add_action (switcher, GTK_ACTION (action)); + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, + "/main-menu/view-menu/window-menu", + action_name, action_name, + GTK_UI_MANAGER_AUTO, FALSE); + + g_free (accelerator); + g_free (action_name); + g_free (tooltip); + + g_type_class_unref (class); + } +} + +void +e_shell_window_update_view_menu (EShellWindow *shell_window) +{ + EShellView *shell_view; + EShellViewClass *shell_view_class; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + GalViewCollection *view_collection; + GtkRadioAction *radio_action; + GtkAction *action; + GSList *radio_group; + gboolean visible; + const gchar *path; + const gchar *view_id; + const gchar *view_name; + guint merge_id; + gint count, ii; + + ui_manager = e_shell_window_get_ui_manager (shell_window); + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + g_return_if_fail (shell_view != NULL); + + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + view_collection = shell_view_class->view_collection; + view_id = e_shell_view_get_view_id (shell_view); + g_return_if_fail (view_collection != NULL); + + action_group = ACTION_GROUP (GAL_VIEW); + merge_id = shell_window->priv->gal_view_merge_id; + + /* Unmerge the previous menu. */ + gtk_ui_manager_remove_ui (ui_manager, merge_id); + e_action_group_remove_all_actions (action_group); + + /* We have a view ID, so forge ahead. */ + count = gal_view_collection_get_count (view_collection); + path = "/main-menu/view-menu/gal-view-menu/gal-view-list"; + + /* Prevent spurious activations. */ + action = ACTION (GAL_CUSTOM_VIEW); + g_signal_handlers_block_matched ( + action, G_SIGNAL_MATCH_FUNC, 0, 0, + NULL, action_gal_view_cb, NULL); + + /* Default to "Custom View", unless we find our view ID. */ + radio_action = GTK_RADIO_ACTION (ACTION (GAL_CUSTOM_VIEW)); + gtk_radio_action_set_group (radio_action, NULL); + radio_group = gtk_radio_action_get_group (radio_action); + gtk_radio_action_set_current_value (radio_action, -1); + + /* Add a menu item for each view collection item. */ + for (ii = 0; ii < count; ii++) { + GalViewCollectionItem *item; + gchar *action_name; + gchar *tooltip; + + item = gal_view_collection_get_view_item (view_collection, ii); + + action_name = g_strdup_printf ( + "gal-view-%s-%d", view_name, ii); + tooltip = g_strdup_printf ("Select view: %s", item->title); + + radio_action = gtk_radio_action_new ( + action_name, item->title, tooltip, NULL, ii); + + action = GTK_ACTION (radio_action); + gtk_radio_action_set_group (radio_action, radio_group); + radio_group = gtk_radio_action_get_group (radio_action); + + g_object_set_data_full ( + G_OBJECT (radio_action), "view-id", + g_strdup (item->id), (GDestroyNotify) g_free); + + if (view_id != NULL && strcmp (item->id, view_id) == 0) + gtk_radio_action_set_current_value (radio_action, ii); + + gtk_action_group_add_action (action_group, action); + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, path, action_name, + action_name, GTK_UI_MANAGER_AUTO, FALSE); + + g_free (action_name); + g_free (tooltip); + } + + /* Doesn't matter which radio action we check. */ + visible = (gtk_radio_action_get_current_value (radio_action) < 0); + + action = ACTION (GAL_CUSTOM_VIEW); + gtk_action_set_visible (action, visible); + g_signal_handlers_unblock_matched ( + action, G_SIGNAL_MATCH_FUNC, 0, 0, + NULL, action_gal_view_cb, NULL); + + action = ACTION (GAL_SAVE_CUSTOM_VIEW); + gtk_action_set_visible (action, visible); +} + +void +e_shell_window_update_search_menu (EShellWindow *shell_window) +{ + EShellContent *shell_content; + EShellView *shell_view; + EShellViewClass *shell_view_class; + RuleContext *context; + FilterRule *rule; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + const gchar *source; + const gchar *view_name; + gboolean sensitive; + guint merge_id; + gint ii = 0; + + ui_manager = e_shell_window_get_ui_manager (shell_window); + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + shell_content = e_shell_view_get_shell_content (shell_view); + context = e_shell_content_get_search_context (shell_content); + shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + source = FILTER_SOURCE_INCOMING; + + /* Update sensitivity of search actions. */ + + sensitive = (e_shell_content_get_search_rule (shell_content) != NULL); + gtk_action_set_sensitive (ACTION (SEARCH_CLEAR), sensitive); + gtk_action_set_sensitive (ACTION (SEARCH_SAVE), sensitive); + + sensitive = (shell_view_class->search_options != NULL); + gtk_action_set_sensitive (ACTION (SEARCH_OPTIONS), sensitive); + + /* Add custom rules to the Search menu. */ + + action_group = ACTION_GROUP (CUSTOM_RULES); + merge_id = shell_window->priv->custom_rule_merge_id; + + /* Unmerge the previous menu. */ + gtk_ui_manager_remove_ui (ui_manager, merge_id); + e_action_group_remove_all_actions (action_group); + + rule = rule_context_next_rule (context, NULL, source); + while (rule != NULL) { + GtkAction *action; + gchar *action_name; + gchar *action_label; + + action_name = g_strdup_printf ("custom-rule-%d", ii++); + if (ii < 10) + action_label = g_strdup_printf ( + "_%d. %s", ii, rule->name); + else + action_label = g_strdup (rule->name); + + action = gtk_action_new ( + action_name, action_label, + _("Execute these search parameters"), NULL); + + g_object_set_data_full ( + G_OBJECT (action), + "rule", g_object_ref (rule), + (GDestroyNotify) g_object_unref); + + g_signal_connect ( + action, "activate", + G_CALLBACK (action_custom_rule_cb), shell_window); + + gtk_action_group_add_action (action_group, action); + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, + "/main-menu/search-menu/custom-rules", + action_name, action_name, + GTK_UI_MANAGER_AUTO, FALSE); + + g_free (action_name); + g_free (action_label); + + rule = rule_context_next_rule (context, rule, source); + } +} diff --git a/shell/e-shell-window-actions.h b/shell/e-shell-window-actions.h new file mode 100644 index 0000000000..3b8774a494 --- /dev/null +++ b/shell/e-shell-window-actions.h @@ -0,0 +1,123 @@ +/* + * e-shell-window-actions.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_SHELL_WINDOW_ACTIONS_H +#define E_SHELL_WINDOW_ACTIONS_H + +#define E_SHELL_WINDOW_ACTION(window, name) \ + (e_shell_window_get_action (E_SHELL_WINDOW (window), (name))) + +#define E_SHELL_WINDOW_ACTION_GROUP(window, name) \ + (e_shell_window_get_action_group (E_SHELL_WINDOW (window), (name))) + +/* Actions */ +#define E_SHELL_WINDOW_ACTION_ABOUT(window) \ + E_SHELL_WINDOW_ACTION ((window), "about") +#define E_SHELL_WINDOW_ACTION_CLOSE(window) \ + E_SHELL_WINDOW_ACTION ((window), "close") +#define E_SHELL_WINDOW_ACTION_CONTENTS(window) \ + E_SHELL_WINDOW_ACTION ((window), "contents") +#define E_SHELL_WINDOW_ACTION_FAQ(window) \ + E_SHELL_WINDOW_ACTION ((window), "faq") +#define E_SHELL_WINDOW_ACTION_FORGET_PASSWORDS(window) \ + E_SHELL_WINDOW_ACTION ((window), "forget-passwords") +#define E_SHELL_WINDOW_ACTION_GAL_CUSTOM_VIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-custom-view") +#define E_SHELL_WINDOW_ACTION_GAL_DEFINE_VIEWS(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-define-views") +#define E_SHELL_WINDOW_ACTION_GAL_SAVE_CUSTOM_VIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-save-custom-view") +#define E_SHELL_WINDOW_ACTION_IMPORT(window) \ + E_SHELL_WINDOW_ACTION ((window), "import") +#define E_SHELL_WINDOW_ACTION_NEW_WINDOW(window) \ + E_SHELL_WINDOW_ACTION ((window), "new-window") +#define E_SHELL_WINDOW_ACTION_PAGE_SETUP(window) \ + E_SHELL_WINDOW_ACTION ((window), "page-setup") +#define E_SHELL_WINDOW_ACTION_PREFERENCES(window) \ + E_SHELL_WINDOW_ACTION ((window), "preferences") +#define E_SHELL_WINDOW_ACTION_QUICK_REFERENCE(window) \ + E_SHELL_WINDOW_ACTION ((window), "quick-reference") +#define E_SHELL_WINDOW_ACTION_QUIT(window) \ + E_SHELL_WINDOW_ACTION ((window), "quit") +#define E_SHELL_WINDOW_ACTION_SEARCH_ADVANCED(window) \ + E_SHELL_WINDOW_ACTION ((window), "search-advanced") +#define E_SHELL_WINDOW_ACTION_SEARCH_CLEAR(window) \ + E_SHELL_WINDOW_ACTION ((window), "search-clear") +#define E_SHELL_WINDOW_ACTION_SEARCH_EDIT(window) \ + E_SHELL_WINDOW_ACTION ((window), "search-edit") +#define E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE(window) \ + E_SHELL_WINDOW_ACTION ((window), "search-execute") +#define E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS(window) \ + E_SHELL_WINDOW_ACTION ((window), "search-options") +#define E_SHELL_WINDOW_ACTION_SEARCH_SAVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "search-save") +#define E_SHELL_WINDOW_ACTION_SEND_RECEIVE(window) \ + E_SHELL_WINDOW_ACTION ((window), "send-receive") +#define E_SHELL_WINDOW_ACTION_SHOW_SIDEBAR(window) \ + E_SHELL_WINDOW_ACTION ((window), "show-sidebar") +#define E_SHELL_WINDOW_ACTION_SHOW_STATUSBAR(window) \ + E_SHELL_WINDOW_ACTION ((window), "show-statusbar") +#define E_SHELL_WINDOW_ACTION_SHOW_SWITCHER(window) \ + E_SHELL_WINDOW_ACTION ((window), "show-switcher") +#define E_SHELL_WINDOW_ACTION_SHOW_TOOLBAR(window) \ + E_SHELL_WINDOW_ACTION ((window), "show-toolbar") +#define E_SHELL_WINDOW_ACTION_SUBMIT_BUG(window) \ + E_SHELL_WINDOW_ACTION ((window), "submit-bug") +#define E_SHELL_WINDOW_ACTION_SWITCHER_INITIAL(window) \ + E_SHELL_WINDOW_ACTION ((window), "switcher-initial") +#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_BOTH(window) \ + E_SHELL_WINDOW_ACTION ((window), "switcher-style-both") +#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_ICONS(window) \ + E_SHELL_WINDOW_ACTION ((window), "switcher-style-icons") +#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_TEXT(window) \ + E_SHELL_WINDOW_ACTION ((window), "switcher-style-text") +#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_USER(window) \ + E_SHELL_WINDOW_ACTION ((window), "switcher-style-user") +#define E_SHELL_WINDOW_ACTION_SYNC_OPTIONS(window) \ + E_SHELL_WINDOW_ACTION ((window), "sync-options") +#define E_SHELL_WINDOW_ACTION_WORK_OFFLINE(window) \ + E_SHELL_WINDOW_ACTION ((window), "work-offline") +#define E_SHELL_WINDOW_ACTION_WORK_ONLINE(window) \ + E_SHELL_WINDOW_ACTION ((window), "work-online") + +/* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_CUSTOM_RULES(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "custom-rules") +#define E_SHELL_WINDOW_ACTION_GROUP_GAL_VIEW(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "gal-view") +#define E_SHELL_WINDOW_ACTION_GROUP_LOCKDOWN_APPLICATION_HANDLERS(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "lockdown-application-handlers") +#define E_SHELL_WINDOW_ACTION_GROUP_LOCKDOWN_PRINTING(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "lockdown-printing") +#define E_SHELL_WINDOW_ACTION_GROUP_LOCKDOWN_PRINT_SETUP(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "lockdown-print-setup") +#define E_SHELL_WINDOW_ACTION_GROUP_LOCKDOWN_SAVE_TO_DISK(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "lockdown-save-to-disk") +#define E_SHELL_WINDOW_ACTION_GROUP_NEW_ITEM(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "new-item") +#define E_SHELL_WINDOW_ACTION_GROUP_NEW_SOURCE(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "new-source") +#define E_SHELL_WINDOW_ACTION_GROUP_SHELL(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "shell") +#define E_SHELL_WINDOW_ACTION_GROUP_SWITCHER(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "switcher") + +#endif /* E_SHELL_WINDOW_ACTIONS_H */ diff --git a/shell/e-shell-window-commands.c b/shell/e-shell-window-commands.c deleted file mode 100644 index 731f17b49b..0000000000 --- a/shell/e-shell-window-commands.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include <config.h> - -#include <string.h> - -#include <gtk/gtk.h> -#include <glib/gprintf.h> - -#include <glib/gi18n.h> - -#include <gio/gio.h> - -#include <bonobo/bonobo-ui-component.h> - -#include <libedataserverui/e-passwords.h> - -#include <gconf/gconf-client.h> - -#include "e-util/e-dialog-utils.h" -#include "e-util/e-error.h" -#include "e-util/e-icon-factory.h" -#include "e-util/e-print.h" -#include "e-util/e-util.h" -#include "e-util/e-util-private.h" - -#include "e-shell-window-commands.h" -#include "e-shell-window.h" -#include "evolution-shell-component-utils.h" - -#include "e-shell-importer.h" - -#define EVOLUTION_COPYRIGHT \ - "Copyright \xC2\xA9 1999 - 2009 Novell, Inc. and Others" - -#define EVOLUTION_WEBSITE \ - "http://www.gnome.org/projects/evolution/" - -/* Utility functions. */ - -static void -launch_pilot_settings (void) -{ - GError* error = NULL; - - gchar * args = g_find_program_in_path ("gpilotd-control-applet"); - if (args == NULL) { - e_notice (NULL, GTK_MESSAGE_ERROR, - _("The GNOME Pilot tools do not appear to be installed on this system.")); - return; - } - - g_spawn_command_line_async (args, &error); - g_free (args); - - if (error != NULL) { - e_notice (NULL, GTK_MESSAGE_ERROR, - _("Error executing %s. (%s)"), args, error->message); - g_error_free (error); - } -} - -/* Command callbacks. */ - -static void -command_import (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - e_shell_importer_start_import (window); -} - -static void -command_page_setup (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - e_print_run_page_setup_dialog (GTK_WINDOW (window)); -} - -static void -command_close (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - if (e_shell_request_close_window (e_shell_window_peek_shell (window), window)) - gtk_widget_destroy (GTK_WIDGET (window)); -} - -static void -command_quit (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - EShell *shell = e_shell_window_peek_shell (window); - - e_shell_quit(shell); -} - -static void -command_submit_bug (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - const gchar *command_line; - GError *error = NULL; - - command_line = "bug-buddy --sm-disable --package=Evolution"; - - g_debug ("Spawning: %s", command_line); - - if (!g_spawn_command_line_async (command_line, &error)) { - if (error->code == G_SPAWN_ERROR_NOENT) - e_notice (NULL, GTK_MESSAGE_ERROR, - _("Bug buddy is not installed.")); - else - e_notice (NULL, GTK_MESSAGE_ERROR, - _("Bug buddy could not be run.")); - g_error_free (error); - } -} - -/* must be in utf8, the weird breaking of escaped strings - is so the hex escape strings dont swallow too many chars - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - So that means, 8 bit characters, use \xXX hex encoding ONLY -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - No all environments are utf8 and not all editors can handle it. -*/ -static const gchar *authors[] = { - "Aaron Weber", - "Abel Cheung", - "Abhishek Parwal", - "Adam Weinberger", - "Adi Attar", - "Ahmad Riza H Nst", - "Aidan Delaney", - "Aishwarya K", - "Akagic Amila", - "Akhil Laddha", - "Akira Tagoh", - "Alastair McKinstry", - "Alastair Tse", - "Alejandro Andres", - "Ales Nyakhaychyk", - "Alessandro Decina", - "Alessio Frusciante", - "Alex Graveley", - "Alex Jiang", - "Alex Jones", - "Alex Kloss", - "Alex Rostovtsev", - "Alexander Didebulidze", - "Alexander Shopov", - "Alexander Winston", - "Alexandre Folle de Menezes", - "Alfred Peng", - "Ali Abdin", - "Ali Akcaagac", - "Alireza Kheirkhahan", - "Almer S. Tigelaar", - "Alp Toker", - "Amanpreet Singh Alam", - "Ambuj Chitranshi", - "Amish", - "Amitakhya Phukan", - "Anand V M", - "Anders Carlsson", - "Andras Timar", - "Andrea Campi", - "Andreas Henriksson", - "Andreas Hyden", - "Andreas J. Guelzow", - "Andreas Köhler", - "Andrew Ruthven", - "Andre Klapper", - "Andrew T. Veliath", - "Andrew V. Samoilov", - "Andrew Wu", - "Ani Peter", - "Ankit Patel", - "Anna Marie Dirks", - "Antonio Xu", - "Arafat Medini", - "Arangel Angov", - "Archit Baweja", - "Ariel Rios", - "Arik Devens", - "Armin Bauer", - "Arjan Scherpenisse", - "Arkadiusz Lipiec", - "Artis Trops", - "Artur Flinta", - "Arturo Espinosa Aldama", - "Arulanandan P", - "Arun Prakash", - "Arvind Sundararajan", - "Ashish Shrivastava", - "Åsmund Skjæveland", - "Audrey Simons", - "Baptiste Mille-Mathias", - "Baris Cicek", - "Bastien Nocera", - "Behnam Esfahbod", - "Benedikt Roth", - "Ben Gamari", - "Benjamin Berg", - "Benjamin Kahn", - "Benoît Dejean", - "Bernard Leach", - "Bertrand Guiheneuf", - "Bharath Acharya", - "Bharat Kumar", - "Bharathi Gauthaman", - "Big Iain Holmes", - "Bill Zhu", - "Björn Torkelsson", - "Björn Lindqvist", - "Bob Doan", - "Bob Mauchin", - "Boby Wang", - "Bolian Yin", - "Borislav Aleksandrov", - "Boulton", - "Brian Mury", - "Brian Pepple", - "Brigitte Le Grand", - "Bruce Tao", - "B S Srinidhi", - "Calvin Liu", - "Cantona Su", - "Carlos Garcia Campos", - "Carlos Garnacho Parro", - "Carlos Perelló Marín", - "Carl Sun", - "Carsten Guenther", - "Carsten Schaar", - "Changwoo Ryu", - "Chao-Hsiung Liao", - "Charles Zhang", - "Chema Celorio", - "Chenthill Palanisamy", - "Christian Persch", - "Chris Halls", - "Chris Heath", - "Chris Lahey", - "Christian Hammond", - "Christian Kellner", - "Christian Kintner", - "Christian Kirbach", - "Christian Krause", - "Christian Kreibich", - "Christian Meyer", - "Christian Neumair", - "Christian Persch", - "Christian Rose", - "Christophe Fergeau", - "Christophe Merlet", - "Christopher Blizzard", - "Christopher James Lahey", - "Christopher R. Gabriel", - "Chris Phelps", - "Chris Toshok", - "Clara Tattoni", - "Claude Paroz", - "Claudio Saavedra", - "Clifford R. Conover", - "Clytie Siddall", - "Cody Russell", - "Colin Leroy", - "Craig Jeffares", - "Craig Small", - "Cyprien Le Pannérer", - "Dafydd Harries", - "Damian Ivereigh", - "Damien Carbery", - "Damon Chaplin", - "Daniel Gryniewicz", - "Daniel Nylander", - "Daniel van Eeden", - "Daniel Veillard", - "Daniel Yacob", - "Danilo Šegan", - "Danishka Navin", - "Dan Korostelev", - "Danny Baumann", - "Dan Berger", - "Dan Damian", - "Dan Nguyen", - "Dan Williams", - "Dan Winship", - "Darin Adler", - "Dave Benson", - "Dave Camp", - "Dave Fallon", - "Dave Malcolm", - "Dave West", - "David Farning", - "David Kaelbling", - "David Lodge", - "David Malcolm", - "David Moore", - "David Mosberger", - "David O'Callaghan", - "David Richards", - "David Trowbridge", - "David Turner", - "David Woodhouse", - "Denis Washington", - "Devashish Sharma", - "Diego Escalante Urrelo", - "Diego Gonzalez", - "Diego Sevilla Ruiz", - "Dietmar Maurer", - "Dinesh Layek", - "Dirk-Jan C. Binnema", - "Djihed Afifi", - "Dmitrijs Ledkovs", - "Dmitry Mastrukov", - "Dodji Seketeli", - "Duarte Loreto", - "Dulmandakh Sukhbaatar", - "Duncan Mak", - "Ebby Wiselyn", - "Ed Catmur", - "Edd Dumbill", - "Edgar Luna Díaz", - "Edward Rudd", - "Elijah Newren", - "Elizabeth Greene", - "Elliot Lee", - "Elliot Turner", - "Emil Hessman", - "Eneko Lacunza", - "Enver Altin", - "Erdal Ronahi", - "Erdi Gergo", - "Eric Busboom", - "Eric Zhao", - "Eskild Hustvedt" - "Eskil Heyn Olsen", - "Espen Stefansen", - "Ettore Perazzoli", - "Evandro Fernandes Giovanini", - "Evan Yan", - "Fatih Demir", - "Fazlu & Hannah", - "Federico Mena Quintero", - "Fernando Herrera", - "Ferretti", - "F. Priyadharshini", - "Francisco Javier Fernandez Serrador", - "Frank Arnold", - "Frank Belew", - "Frederic Crozat", - "Frederic Peters", - "Frederic Riss", - "Fredrik Wendt", - "Funda Wang", - "Gabor Kelemen", - "Ganesh", - "Göran Uddeborg", - "Gareth Owen", - "Gary Coady", - "Gary Ekker", - "Gavin Scott", - "Gediminas Paulauskas", - "George Lebl", - "Gerardo Marin", - "Gergő Érdi", - "Gert Kulyk", - "Giancarlo Capella", - "Gilbert Fang", - "Gildas Guillemot", - "Gil Forcada", - "Gilles Dartiguelongue", - "Gil Osher", - "Gintautas Miliauskas", - "Goran Rakić", - "Grahame Bowland", - "Greg Hudson", - "Gregory Leblanc", - "Gregory McLean", - "Grzegorz Goawski", - "Guilherme de S. Pastore", - "Guntupalli Karunakar", - "Gustavo GirÎldez", - "Gustavo Maciel Dias Vieira", - "Gustavo Noronha Silva", - "Hamed Malek", - "Hannah & Fazlu", - "Hans Petter Jansson", - "Hao Sheng", - "Hari Prasad Nadig", - "Harish Krishnaswamy", - "Harry Lu", - "Hasbullah Bin Pit", - "Havoc Pennington", - "Heath Harrelson", - "Hein-Pieter van Braam", - "Héctor García Álvarez", - "Helgi Þormar Þorbjörnsson", - "Hendrik Brandt", - "Hendrik Richter", - "Herbert V. Riedel", - "Hessam M. Armandehi", - "Hiroyuki Ikezoe", - "Iain Buchanan", - "Iain Holmes", - "Ian Campbell", - "Iassen Pramatarov", - "Iestyn Pryce", - "I.Felix", - "Ignacio Casal Quinteiro", - "Igor Nestorović", - "Ihar Hrachyshka", - "Ilkka Tuohela", - "Imam Musthaqim", - "Iñaki Larrañaga", - "Inaki Larranaga Murgoitio", - "Indu", - "Irene Huang", - "Ismael Olea", - "Israel Escalante", - "Ivan Stojmirov", - "Ivar Smolin", - "Ivelina Karcheva", - "Iván Frade", - "J.H.M. Dassen (Ray)", - "Jaap A. Haitsma", - "Jack Jia", - "Jacob Berkman", - "Jacob Brown", - "Jacobo Tarrio Barreiro", - "Jacob Ulysses Berkman", - "Jaka Mocnik", - "Jakub Friedl", - "Jakub Steiner", - "James Bowes", - "James Doc Livingston", - "James Henstridge", - "James Westby", - "James Willcox", - "Jamil Ahmed", - "Jan Arne Petersen", - "Jan Tichavsky", - "Jan Van Buggenhout", - "JÃ�rg Billeter", - "Jared Moore", - "Jarkko Ranta", - "Jason Leach", - "Jason Tackaberry", - "Jayaradha", - "Jean-Noel Guiheneuf", - "Jedy Wang", - "Jeff Bailey", - "Jeff Cai", - "Jeff Garzik", - "Jeffrey Stedfast", - "Jens Granseuer", - "Jens Seidel", - "Jeremy Katz", - "Jeremy Messenger", - "Jeremy Wise", - "Jerome Lacoste", - "Jerry Yu", - "Jesse Pavel", - "Jesus Bravo Alvarez", - "Jesse Pavel", - "Ji Lee", - "Joan Sanfeliu", - "João Vale", - "Joaquim Fellmann", - "Jody Goldberg", - "Joe Man", - "Joe Marcus Clarke", - "Joe Shaw", - "Johan Dahlin", - "Johan Euphrosine", - "John Gotts", - "Johnny Jacob", - "Jon Ander Hernandez", - "Jonas Borgstr�m", - "Jonathan Blandford", - "Jonathan Dieter", - "Jonathan Ernst", - "Jonh Wendell", - "Jon K Hellan", - "Jon Oberheide", - "Jon Trowbridge", - "Jonas Borgstr", - "Jonathan Blandford", - "Jonathan Dieter", - "Joop Stakenborg", - "Jordi Mallach", - "Jordi Mas", - "Jorge Gonzalez", - "Jörgen Scheibengruber", - "Jos Dehaes", - "Josep Puigdemont Casamajó", - "Josselin Mouette", - "Jovan Naumovski", - "JP Rosevear", - "Juan Manuel GarcÃa Molina", - "Juan Pizarro", - "Jukka Zitting", - "Jules Colding", - "Julian Missig", - "Julien Puydt", - "Julio M. Merino Vidal", - "Juraj Kubelka", - "Jürg Billeter", - "Justina Klingaitė", - "Kai Lahmann", - "Kang Jeong-Hee", - "Karl Eichwalder", - "Karl Relton", - "Karsten Bräckelmann", - "Kaushal Kumar", - "Keith Packard", - "Keld Simonsen", - "Kenneth Christiansen", - "Kenneth Nielsen", - "Kenneth Rohde Christiansen", - "Kenny Graunke", - "Keshav Upadhyaya", - "Kevin Breit", - "Kevin Piche", - "Kevin Vandersloot", - "Khasim Shaheed", - "Kidd Wang", - "Kjartan Maraas", - "Krishnan R", - "Kostas Papadimas", - "Krishna Babu K", - "Krisztian Pifko", - "Kyle Ambroff", - "Larry Ewing", - "Laszlo Dvornik", - "Laszlo (Laca) Peter", - "Laurent Dhima", - "Lauris Kaplinski", - "Leonardo Ferreira Fontenelle", - "Leonid Kanter", - "Leon Zhang", - "Li Yuan", - "Loïc Minier", - "Lorenzo Gil Sanchez", - "Luca Ferretti", - "Lucas Rocha", - "Lucian Langa", - "Lucky Wankhede", - "Luis Villa", - "Lukas Novotny", - "Lutz M", - "Maciej Piechotka", - "Maciej Stachowiak", - "Makuchaku", - "Malcolm Tredinnick", - "Manuel A. Fernández Montecelo", - "Manuel Borchers", - "Marcel Telka", - "Marco Ciampa", - "Marco Pesenti Gritti", - "Marius Andreiana", - "Marius Vollmer", - "Mark Crichton", - "Mark G. Adams", - "Mark Gordon", - "Mark McLoughlin", - "Mark Moulder", - "Mark Tearle", - "Martha Burke", - "Martin Baulig", - "Martin Hicks", - "Martin Meyer", - "Martin Norbäck", - "Martin Willemoes Hansen", - "Martyn Russell", - "Masahiro Sakai", - "Matej Urbančič", - "Mathieu Lacage", - "Matias Mutchinick", - "Matic Žgur", - "Matt Bissiri", - "Matt Brown", - "Matthew Barnes", - "Matthew Daniel", - "Matthew Hall", - "Matthew Loper", - "Matthew Wilson", - "Matthias Braun", - "Matthias Clasen", - "Matthias Warkus", - "Matt Loper", - "Matt Martin", - "Matt McCutchen", - "Matt Wilson", - "Max Horn", - "Maxim Dziumanenko", - "Maxx Cao", - "Mayank Jain", - "Meelad Zakaria", - "Meilof Veeningen", - "Mendel Mobach", - "Mengjie Yu", - "Metin Amiroff", - "Michael Granger", - "Michael M. Morrison", - "Michael MacDonald", - "Michael Meeks", - "Michael Monreal", - "Michael Terry", - "Michael Zucchi", - "Michal Bukovjan", - "Michel Daenzer", - "Miguel Angel Lopez Hernandez", - "Miguel de Icaza", - "Mikael Hallendal", - "Mikael Nilsson", - "Mike Castle", - "Mike Kestner", - "Mike McEwan", - "Mikhail Zabaluev", - "Milan Crha", - "Miles Lane", - "Miloslav Trmač", - "MIMOS Open Source Development Group", - "Mohammad Damt", - "Moritz Mertinkat", - "Morten Welinder", - "Mubeen Jukaku", - "Mugurel Tudor", - "Murray Cumming", - "M Victor Aloysius J", - "Naba Kumar", - "Nagappan Alagappan", - "Nancy Cai", - "Naresh N", - "Nat Friedman", - "Nathan Owens", - "Nguyễn Thái Ngọc Duy", - "Nicel KM", - "Nicholas J Kreucher", - "Nicholas Miell", - "Nickolay V. Shmyrev", - "Nick Sukharev", - "Nike Gerdts", - "Nikos Charonitakis", - "Noel", - "Nuno Ferreira", - "Nyall Dawson", - "Og Maciel", - "Ole Laursen", - "Ondrej Jirman", - "Oswald Rodrigues", - "Owen Taylor", - "Øystein Gisnås", - "Pablo Gonzalo del Campo", - "Pablo Saratxaga", - "Pamplona Hackers", - "Pauli Virtanen", - "Paolo Borelli", - "Paolo Molaro", - "Parag Goel", - "Parthasarathi Susarla", - "Pascal Terjan", - "Patrick Ohly", - "Paul Bolle", - "Paul Duffy", - "Paul Iadonisi", - "Paul Lindner", - "Paul Smith", - "Paulo Gomes Vanzuita", - "Pavel Cholakov", - "Pavel Cisler", - "Pavel Roskin", - "Pavithran", - "Pawan Chitrakar", - "Pedro Villavicencio", - "Pema Geyleg", - "Peteris Krisjanis", - "Peter Bach", - "Peter Pouliot", - "Peter Teichman", - "Peter Williams", - "Petr Kovar", - "Petta Pietikainen", - "Phil Goembel", - "Philipp Kerling", - "Philip Van Hoof", - "Philip Withnall", - "Philip Zhao", - "Poornima Nayak", - "Pramod", - "Prasad Kandepu", - "Pratik V. Parikh", - "Praveen Arimbrathodiyil", - "Praveen Kumar", - "Priit Laes", - "Priyanshu Raj", - "P S Chakravarthi", - "Radek Doulik", - "Raghavendran R", - "Rahul Bhalerao", - "Raivis Dejus", - "Raja R Harinath", - "Rajeev Ramanathan", - "Rajesh Ranjan", - "Rakesh k.g", - "Ramiro Estrugo", - "Ranjan Somani", - "Raphael Higino", - "Ray Strode", - "Reinout van Schouwen", - "Rhys Jones", - "Ricardo Markiewicz", - "Richard Boulton", - "Richard Hult", - "Richard Li", - "Rob Bradford", - "Robert-André Mauchin", - "Robert Brady", - "Robert Sedak", - "Robin Slomkowski", - "Rodney Dawes", - "Rodrigo Moya", - "Roger Zauner", - "Rohini S", - "Roland Illig", - "Ronald Kuetemeier", - "Roozbeh Pournader", - "Roshan Kumar Singh", - "Ross Burton", - "Rostislav Raykov", - "Rouslan Solomakhin", - "Roy-Magne Mo", - "Runa Bhattacharjee", - "Russell Steinthal", - "Russian team", - "Rusty Conover", - "Ryan P. Skadberg", - "Sam Creasey", - "Sami Pesonen", - "Samúel Jón Gunnarsson", - "Sam Yang", - "Sankar P", - "Sanlig Badral", - "Sanshao Jiang", - "S.Antony Vincent Pandian", - "Sarfraaz Ahmed", - "Satoru SATOH", - "Sayamindu Dasgupta", - "S. Caglar Onur", - "Sean Atkinson", - "Seán de Búrca", - "Sean Gao", - "Sebastian Rittau", - "Sebastian Wilhelmi", - "Sebastien Bacher", - "Sergey Panov", - "Sergio Villar Senín", - "Seth Alves", - "Seth Nickell", - "Shakti Sen", - "Shankar Prasad", - "Shi Pu", - "Shilpa C", - "Shree Krishnan", - "Shreyas Srinivasan", - "Shuai Liu", - "Sigurd Gartmann", - "Simon Zheng", - "Simos Xenitellis", - "Sitic Vulnerability Advisory", - "Sivaiah Nallagatla", - "Slobodan D. Sredojevic", - "S N Tejasvi", - "Spiros Papadimitriou", - "Srinivasa Ragavan", - "Stanislav Brabec", - "Stanislav Slusny", - "Stanislav Visnovsky", - "Stéphane Raimbault", - "Stephen Cook", - "Steve Murphy", - "Steven Zhang", - "Stuart Parmenter", - "Subhransu Behera", - "Subodh Soni", - "Suman Manjunath", - "Sunil Mohan Adapa", - "Supranee Thirawatthanasuk", - "Suresh Chandrasekharan", - "Sushma Rai", - "Sven Herzberg", - "Sweta Kothari", - "Szabolcs Ban", - "Takao Fujiwara", - "Takayuki Kusano", - "Takeshi Aihana", - "Takuo Kitame", - "Tambet Ingo", - "Taylor Hayward", - "Ted Percival", - "Telsa Gwynne", - "Terance Sola", - "Theppitak Karoonboonyanan", - "Thierry Moisan", - "Thierry Randrianiriana", - "Thomas Cataldo", - "Thomas Klausner", - "Thomas Mirlacher", - "Thouis R. Jones", - "Tiago Antao", - "Timo Jyrinki", - "Timur Bakeyev", - "Tim Wo", - "Tim Yamin", - "Timo Hoenig", - "Timo Sirainen", - "Timothy Lee", - "Timur Bakeyev", - "Tino Meinen", - "Tobias Mueller", - "Tõivo Leedjärv", - "Tom Tromey", - "Tomas Ogren", - "Tomasz Kłoczko", - "Tomislav Vujec", - "Tommi Komulainen", - "Tommi Vainikainen", - "Tony Tsui", - "Tor Lillqvist", - "Trent Lloyd", - "Tristan Tarrant", - "Tuomas J. Lukka", - "Tuomas Kuosmanen", - "Udomsak Chundang", - "Ulrich Neumann", - "Umeshtej", - "Umesh Tiwari", - "Ushveen Kaur", - "Vadim Strizhevsky", - "Valek Filippov", - "Vandana Shenoy .B", - "Vardhman Jain", - "Vasiliy Faronov", - "Veerapuram Varadhan", - "Vincent Carriere", - "Vincent Noel", - "Vincent Renardias", - "Vincent Untz", - "Vincent van Adrighem", - "Viren.L", - "Vivek Jain", - "Vladimer Sichinava", - "Vladimir Petkov", - "Vladimir Vukicevic", - "Vladimir Melo", - "V Ravi Kumar Raju", - "Wadim Dziedzic", - "Wang Jian", - "Wang Li", - "Wang Xin", - "Washington Lins", - "Wayne Davis", - "William Jon McCann", - "Woodman Tuen", - "Wouter Bolsterlee", - "Xan Lopez", - "Xavier Conde Rueda", - "Xiurong Simon Zheng", - "Yair Hershkovitz", - "Yanko Kaneti", - "Yannig Marchegay", - "Yavor Doganov", - "Yi Jin", - "Yong Sun", - "Yuedong Du", - "Yukihiro Nakai", - "Yu Mengjie", - "Yuri Pankov", - "Yuri Syrota", - "Yuriy Penkin", - "Zach Frey", - "Zan Lynx", - "Zbigniew Chyla", - "Zhe Su", - "Zipeco", - "Žygimantas Beručka", - NULL -}; - -static const gchar *documentors[] = { - "Aaron Weber", - "Binika Preet", - "Dan Winship", - "David Trowbridge", - "Jessica Prabhakar", - "JP Rosevear", - "Radhika Nair", - NULL -}; - -static void -command_about (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - gchar *translator_credits; - - /* The translator-credits string is for translators to list - * per-language credits for translation, displayed in the - * about dialog. */ - translator_credits = _("translator-credits"); - if (strcmp (translator_credits, "translator-credits") == 0) - translator_credits = NULL; - - gtk_show_about_dialog ( - GTK_WINDOW (window), - "program-name", "Evolution", - "version", VERSION, - "copyright", EVOLUTION_COPYRIGHT, - "comments", _("Groupware Suite"), - "website", EVOLUTION_WEBSITE, - "website-label", _("Evolution Website"), - "authors", authors, - "documenters", documentors, - "translator-credits", translator_credits, - "logo-icon-name", "evolution", - NULL); -} - -static void -command_open_faq (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - const gchar *uri; - - uri = "http://www.go-evolution.org/FAQ"; - e_show_uri (GTK_WINDOW (window), uri); -} - -static void -command_quick_reference (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - gchar *quickref; - const gchar * const *language_names; - - language_names = g_get_language_names (); - while (*language_names != NULL) { - const gchar *lang = *language_names++; - - /* This has to be a valid language AND a language with - * no encoding postfix. The language will come up without - * encoding next */ - if (lang == NULL || strchr (lang, '.') != NULL) - continue; - - quickref = g_build_filename (EVOLUTION_HELPDIR, "quickref", lang, "quickref.pdf", NULL); - if (g_file_test (quickref, G_FILE_TEST_EXISTS)) { - GFile *file = g_file_new_for_path (quickref); - - if (file) { - GError *error = NULL; - gchar *uri = g_file_get_uri (file); - - g_app_info_launch_default_for_uri (uri, NULL, &error); - - if (error) { - g_warning ("%s", error->message); - g_error_free (error); - } - - g_object_unref (file); - g_free (uri); - } - - g_free (quickref); - return; - } - - g_free (quickref); - } -} - -static void -command_work_offline (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - EShell *shell; - - shell = e_shell_window_peek_shell (window); - e_shell_set_line_status (shell, GNOME_Evolution_USER_OFFLINE); -} - -static void -command_work_online (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - EShell *shell; - - shell = e_shell_window_peek_shell (window); - e_shell_set_line_status (shell, GNOME_Evolution_USER_ONLINE); -} - -static void -command_open_new_window (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - e_shell_create_window (e_shell_window_peek_shell (window), - e_shell_window_peek_current_component_id (window), - window); -} - -/* Actions menu. */ - -static void -command_send_receive (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - e_shell_send_receive (e_shell_window_peek_shell (window)); -} - -static void -command_forget_passwords (BonoboUIComponent *ui_component, - gpointer data, - const gchar *path) -{ - if (e_error_run (NULL, "shell:forget-passwords", NULL) == GTK_RESPONSE_OK) - e_passwords_forget_passwords(); -} - -/* Tools menu. */ - -static void -command_settings (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - e_shell_window_show_settings (window); -} - -static void -command_pilot_settings (BonoboUIComponent *uih, - EShellWindow *window, - const gchar *path) -{ - launch_pilot_settings (); -} - -static BonoboUIVerb file_verbs [] = { - BONOBO_UI_VERB ("FileImporter", (BonoboUIVerbFn) command_import), - BONOBO_UI_VERB ("FilePageSetup", (BonoboUIVerbFn) command_page_setup), - BONOBO_UI_VERB ("FileClose", (BonoboUIVerbFn) command_close), - BONOBO_UI_VERB ("FileExit", (BonoboUIVerbFn) command_quit), - - BONOBO_UI_VERB ("WorkOffline", (BonoboUIVerbFn) command_work_offline), - BONOBO_UI_VERB ("WorkOnline", (BonoboUIVerbFn) command_work_online), - - BONOBO_UI_VERB_END -}; - -static BonoboUIVerb new_verbs [] = { - BONOBO_UI_VERB ("OpenNewWindow", (BonoboUIVerbFn) command_open_new_window), - - BONOBO_UI_VERB_END -}; - -static BonoboUIVerb actions_verbs[] = { - BONOBO_UI_VERB ("SendReceive", (BonoboUIVerbFn) command_send_receive), - BONOBO_UI_VERB ("ForgetPasswords", command_forget_passwords), - - BONOBO_UI_VERB_END -}; - -static BonoboUIVerb tools_verbs[] = { - BONOBO_UI_VERB ("Settings", (BonoboUIVerbFn) command_settings), - BONOBO_UI_VERB ("PilotSettings", (BonoboUIVerbFn) command_pilot_settings), - - BONOBO_UI_VERB_END -}; - -static BonoboUIVerb help_verbs [] = { - BONOBO_UI_VERB ("QuickReference", (BonoboUIVerbFn) command_quick_reference), - BONOBO_UI_VERB ("HelpOpenFAQ", (BonoboUIVerbFn) command_open_faq), - BONOBO_UI_VERB ("HelpSubmitBug", (BonoboUIVerbFn) command_submit_bug), - BONOBO_UI_VERB ("HelpAbout", (BonoboUIVerbFn) command_about), - - BONOBO_UI_VERB_END -}; - -static EPixmap pixmaps [] = { - E_PIXMAP ("/Toolbar/SendReceive", "mail-send-receive", GTK_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/menu/File/OpenNewWindow", "window-new", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/File/SendReceive", "mail-send-receive", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/File/FileImporter", "stock_mail-import", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/File/Print/FilePageSetup", "stock_print-setup", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/File/ToggleOffline", "stock_disconnect", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/File/FileClose", "window-close", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/File/FileExit", "application-exit", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/Edit/Settings", "preferences-desktop", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/menu/Help/HelpOpenFAQ", "help-faq", GTK_ICON_SIZE_MENU), - - E_PIXMAP_END -}; - -static EPixmap offline_pixmaps [] = { - E_PIXMAP ("/menu/File/ToggleOffline", "stock_disconnect", GTK_ICON_SIZE_MENU), - E_PIXMAP_END -}; - -static EPixmap online_pixmaps [] = { - E_PIXMAP ("/menu/File/ToggleOffline", "stock_connect", GTK_ICON_SIZE_MENU), - E_PIXMAP_END -}; - -/* The Work Online / Work Offline menu item. */ - -static void -update_offline_menu_item (EShellWindow *shell_window, - EShellLineStatus line_status) -{ - BonoboUIComponent *ui_component; - - ui_component = e_shell_window_peek_bonobo_ui_component (shell_window); - - switch (line_status) { - case E_SHELL_LINE_STATUS_OFFLINE: - case E_SHELL_LINE_STATUS_FORCED_OFFLINE: - bonobo_ui_component_set_prop (ui_component, - "/menu/File/ToggleOffline", - "label", _("_Work Online"), NULL); - bonobo_ui_component_set_prop (ui_component, - "/menu/File/ToggleOffline", - "verb", "WorkOnline", NULL); - bonobo_ui_component_set_prop (ui_component, - "/commands/ToggleOffline", - "sensitive", "1", NULL); - e_pixmaps_update (ui_component, online_pixmaps); - break; - - case E_SHELL_LINE_STATUS_ONLINE: - bonobo_ui_component_set_prop (ui_component, - "/menu/File/ToggleOffline", - "label", _("_Work Offline"), NULL); - bonobo_ui_component_set_prop (ui_component, - "/menu/File/ToggleOffline", - "verb", "WorkOffline", NULL); - bonobo_ui_component_set_prop (ui_component, - "/commands/ToggleOffline", - "sensitive", "1", NULL); - e_pixmaps_update (ui_component, offline_pixmaps); - break; - - case E_SHELL_LINE_STATUS_GOING_OFFLINE: - bonobo_ui_component_set_prop (ui_component, - "/menu/File/ToggleOffline", - "label", _("Work Offline"), NULL); - bonobo_ui_component_set_prop (ui_component, - "/menu/File/ToggleOffline", - "verb", "WorkOffline", NULL); - bonobo_ui_component_set_prop (ui_component, - "/commands/ToggleOffline", - "sensitive", "0", NULL); - e_pixmaps_update (ui_component, offline_pixmaps); - break; - - default: - g_return_if_reached(); - } -} - -static void -shell_line_status_changed_cb (EShell *shell, - EShellLineStatus new_status, - EShellWindow *shell_window) -{ - update_offline_menu_item (shell_window, new_status); -} - -static void -view_buttons_icontext_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - ESidebar *sidebar; - - sidebar = e_shell_window_peek_sidebar (shell_window); - e_sidebar_set_mode (sidebar, E_SIDEBAR_MODE_BOTH); -} - -static void -view_buttons_icon_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - ESidebar *sidebar; - - sidebar = e_shell_window_peek_sidebar (shell_window); - e_sidebar_set_mode (sidebar, E_SIDEBAR_MODE_ICON); -} - -static void -view_buttons_text_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - ESidebar *sidebar; - - sidebar = e_shell_window_peek_sidebar (shell_window); - e_sidebar_set_mode (sidebar, E_SIDEBAR_MODE_TEXT); -} - -static void -view_buttons_toolbar_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - ESidebar *sidebar; - - sidebar = e_shell_window_peek_sidebar (shell_window); - e_sidebar_set_mode (sidebar, E_SIDEBAR_MODE_TOOLBAR); -} - -static void -view_buttons_hide_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - ESidebar *sidebar; - gboolean is_visible; - - sidebar = e_shell_window_peek_sidebar (shell_window); - - is_visible = state[0] == '0'; - - e_sidebar_set_show_buttons (sidebar, is_visible); -} - -static void -view_toolbar_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - gboolean is_visible; - - is_visible = state[0] == '1'; - - bonobo_ui_component_set_prop (ui_component, "/Toolbar", - "hidden", is_visible ? "0" : "1", NULL); -} - -static void -view_statusbar_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - GtkWidget *status_bar = e_shell_window_peek_statusbar (shell_window); - gboolean is_visible; - GConfClient *gconf_client; - - is_visible = state[0] == '1'; - if (is_visible) - gtk_widget_show (status_bar); - else - gtk_widget_hide (status_bar); - gconf_client = gconf_client_get_default (); - gconf_client_set_bool (gconf_client,"/apps/evolution/shell/view_defaults/statusbar_visible", is_visible, NULL); - g_object_unref (gconf_client); -} - -static void -view_sidebar_item_toggled_handler (BonoboUIComponent *ui_component, - const gchar *path, - Bonobo_UIComponent_EventType type, - const gchar *state, - EShellWindow *shell_window) -{ - GtkWidget *side_bar = GTK_WIDGET(e_shell_window_peek_sidebar (shell_window)); - gboolean is_visible; - GConfClient *gconf_client; - - is_visible = state[0] == '1'; - if (is_visible) - gtk_widget_show (side_bar); - else - gtk_widget_hide (side_bar); - gconf_client = gconf_client_get_default (); - gconf_client_set_bool (gconf_client_get_default (),"/apps/evolution/shell/view_defaults/sidebar_visible", is_visible, NULL); - g_object_unref (gconf_client); -} - -/* Public API. */ - -void -e_shell_window_commands_setup (EShellWindow *shell_window) -{ - BonoboUIComponent *uic; - EShell *shell; - - g_return_if_fail (shell_window != NULL); - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - uic = e_shell_window_peek_bonobo_ui_component (shell_window); - shell = e_shell_window_peek_shell (shell_window); - - bonobo_ui_component_add_verb_list_with_data (uic, file_verbs, shell_window); - bonobo_ui_component_add_verb_list_with_data (uic, new_verbs, shell_window); - bonobo_ui_component_add_verb_list_with_data (uic, actions_verbs, shell_window); - bonobo_ui_component_add_verb_list_with_data (uic, tools_verbs, shell_window); - bonobo_ui_component_add_verb_list_with_data (uic, help_verbs, shell_window); - bonobo_ui_component_add_listener (uic, "ViewButtonsIconText", - (BonoboUIListenerFn)view_buttons_icontext_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewButtonsIcon", - (BonoboUIListenerFn)view_buttons_icon_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewButtonsText", - (BonoboUIListenerFn)view_buttons_text_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewButtonsToolbar", - (BonoboUIListenerFn)view_buttons_toolbar_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewButtonsHide", - (BonoboUIListenerFn)view_buttons_hide_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewToolbar", - (BonoboUIListenerFn)view_toolbar_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewStatusBar", - (BonoboUIListenerFn)view_statusbar_item_toggled_handler, - (gpointer)shell_window); - bonobo_ui_component_add_listener (uic, "ViewSideBar", - (BonoboUIListenerFn)view_sidebar_item_toggled_handler, - (gpointer)shell_window); - - e_pixmaps_update (uic, pixmaps); - - /* Set up the work online / work offline menu item. */ - g_signal_connect_object (shell, "line_status_changed", - G_CALLBACK (shell_line_status_changed_cb), shell_window, 0); - update_offline_menu_item (shell_window, e_shell_get_line_status (shell)); -} diff --git a/shell/e-shell-window-private.c b/shell/e-shell-window-private.c new file mode 100644 index 0000000000..6ee997ddef --- /dev/null +++ b/shell/e-shell-window-private.c @@ -0,0 +1,602 @@ +/* + * e-shell-window-private.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-shell-window-private.h" + +static void +shell_window_save_switcher_style_cb (GtkRadioAction *action, + GtkRadioAction *current, + EShellWindow *shell_window) +{ + EShell *shell; + GConfClient *client; + GtkToolbarStyle style; + const gchar *key; + const gchar *string; + GError *error = NULL; + + shell = e_shell_window_get_shell (shell_window); + client = e_shell_get_gconf_client (shell); + + style = gtk_radio_action_get_current_value (action); + key = "/apps/evolution/shell/view_defaults/buttons_style"; + + switch (style) { + case GTK_TOOLBAR_ICONS: + string = "icons"; + break; + + case GTK_TOOLBAR_TEXT: + string = "text"; + break; + + case GTK_TOOLBAR_BOTH: + case GTK_TOOLBAR_BOTH_HORIZ: + string = "both"; + break; + + default: + string = "toolbar"; + break; + } + + if (!gconf_client_set_string (client, key, string, &error)) { + g_warning ("%s", error->message); + g_error_free (error); + } +} + +static void +shell_window_init_switcher_style (EShellWindow *shell_window) +{ + EShell *shell; + GtkAction *action; + GConfClient *client; + GtkToolbarStyle style; + const gchar *key; + gchar *string; + GError *error = NULL; + + /* XXX GConfBridge doesn't let you convert between numeric properties + * and string keys, so we have to create the binding manually. */ + + shell = e_shell_window_get_shell (shell_window); + client = e_shell_get_gconf_client (shell); + + action = ACTION (SWITCHER_STYLE_ICONS); + key = "/apps/evolution/shell/view_defaults/buttons_style"; + string = gconf_client_get_string (client, key, &error); + + if (string != NULL) { + if (strcmp (string, "icons") == 0) + style = GTK_TOOLBAR_ICONS; + else if (strcmp (string, "text") == 0) + style = GTK_TOOLBAR_TEXT; + else if (strcmp (string, "both") == 0) + style = GTK_TOOLBAR_BOTH_HORIZ; + else + style = -1; + + gtk_radio_action_set_current_value ( + GTK_RADIO_ACTION (action), style); + } + + g_signal_connect ( + action, "changed", + G_CALLBACK (shell_window_save_switcher_style_cb), + shell_window); +} + +static void +shell_window_menu_item_select_cb (EShellWindow *shell_window, + GtkWidget *menu_item) +{ + GtkAction *action; + GtkLabel *label; + gchar *tooltip = NULL; + + action = g_object_get_data (G_OBJECT (menu_item), "action"); + g_return_if_fail (GTK_IS_ACTION (action)); + + g_object_get (action, "tooltip", &tooltip, NULL); + + if (tooltip == NULL) + return; + + label = GTK_LABEL (shell_window->priv->tooltip_label); + gtk_label_set_text (label, tooltip); + g_free (tooltip); + + gtk_widget_show (shell_window->priv->tooltip_label); + gtk_widget_hide (shell_window->priv->status_notebook); +} + +static void +shell_window_menu_item_deselect_cb (EShellWindow *shell_window) +{ + gtk_widget_hide (shell_window->priv->tooltip_label); + gtk_widget_show (shell_window->priv->status_notebook); +} + +static void +shell_window_connect_proxy_cb (EShellWindow *shell_window, + GtkAction *action, + GtkWidget *proxy) +{ + if (!GTK_IS_MENU_ITEM (proxy)) + return; + + g_object_set_data_full ( + G_OBJECT (proxy), + "action", g_object_ref (action), + (GDestroyNotify) g_object_unref); + + g_signal_connect_swapped ( + proxy, "select", + G_CALLBACK (shell_window_menu_item_select_cb), + shell_window); + + g_signal_connect_swapped ( + proxy, "deselect", + G_CALLBACK (shell_window_menu_item_deselect_cb), + shell_window); +} + +static void +shell_window_online_button_clicked_cb (EOnlineButton *button, + EShellWindow *shell_window) +{ + if (e_online_button_get_online (button)) + gtk_action_activate (ACTION (WORK_OFFLINE)); + else + gtk_action_activate (ACTION (WORK_ONLINE)); +} + +void +e_shell_window_private_init (EShellWindow *shell_window) +{ + EShellWindowPrivate *priv = shell_window->priv; + GHashTable *loaded_views; + GArray *signal_handler_ids; + GtkAccelGroup *accel_group; + GtkToolItem *item; + GtkWidget *container; + GtkWidget *widget; + guint merge_id; + gint height; + + loaded_views = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_object_unref); + + signal_handler_ids = g_array_new (FALSE, FALSE, sizeof (gulong)); + + priv->ui_manager = gtk_ui_manager_new (); + priv->loaded_views = loaded_views; + priv->active_view = "unknown"; + priv->signal_handler_ids = signal_handler_ids; + + e_shell_window_add_action_group (shell_window, "shell"); + e_shell_window_add_action_group (shell_window, "gal-view"); + e_shell_window_add_action_group (shell_window, "new-item"); + e_shell_window_add_action_group (shell_window, "new-source"); + e_shell_window_add_action_group (shell_window, "custom-rules"); + e_shell_window_add_action_group (shell_window, "switcher"); + e_shell_window_add_action_group (shell_window, "lockdown-application-handlers"); + e_shell_window_add_action_group (shell_window, "lockdown-printing"); + e_shell_window_add_action_group (shell_window, "lockdown-print-setup"); + e_shell_window_add_action_group (shell_window, "lockdown-save-to-disk"); + + merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager); + priv->custom_rule_merge_id = merge_id; + + merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager); + priv->gal_view_merge_id = merge_id; + + gtk_window_set_title (GTK_WINDOW (shell_window), _("Evolution")); + + e_shell_window_actions_init (shell_window); + + accel_group = gtk_ui_manager_get_accel_group (priv->ui_manager); + gtk_window_add_accel_group (GTK_WINDOW (shell_window), accel_group); + + g_signal_connect_swapped ( + priv->ui_manager, "connect-proxy", + G_CALLBACK (shell_window_connect_proxy_cb), shell_window); + + /* Construct window widgets. */ + + widget = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (shell_window), widget); + gtk_widget_show (widget); + + container = widget; + + widget = e_shell_window_get_managed_widget ( + shell_window, "/main-menu"); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->main_menu = g_object_ref (widget); + gtk_widget_show (widget); + + widget = e_shell_window_get_managed_widget ( + shell_window, "/main-toolbar"); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->main_toolbar = g_object_ref (widget); + gtk_widget_show (widget); + + /* XXX Having this separator in the UI definition doesn't work + * because GtkUIManager is unaware of the "New" button, so + * it makes the separator invisible. One possibility is to + * define a GtkAction subclass for which create_tool_item() + * returns an EMenuToolButton. Then both this separator + * and the "New" button could be added to the UI definition. + * Tempting, but the "New" button and its dynamically + * generated menu is already a complex beast, and I'm not + * convinced having it proxy some new type of GtkAction + * is worth the extra effort. */ + item = gtk_separator_tool_item_new (); + gtk_toolbar_insert (GTK_TOOLBAR (widget), item, 0); + gtk_widget_show (GTK_WIDGET (item)); + + item = e_menu_tool_button_new (_("New")); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE); + gtk_widget_add_accelerator ( + GTK_WIDGET (item), "clicked", + gtk_ui_manager_get_accel_group (priv->ui_manager), + GDK_N, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + gtk_toolbar_insert (GTK_TOOLBAR (widget), item, 0); + priv->menu_tool_button = g_object_ref (item); + gtk_widget_show (GTK_WIDGET (item)); + + widget = gtk_hpaned_new (); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->content_pane = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_hbox_new (FALSE, 3); + gtk_container_set_border_width (GTK_CONTAINER (widget), 3); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->status_area = g_object_ref (widget); + gtk_widget_show (widget); + + /* Make the status area as large as the task bar. */ + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height); + gtk_widget_set_size_request (widget, -1, (height * 2) + 6); + + container = priv->content_pane; + + widget = e_shell_switcher_new (); + gtk_paned_pack1 (GTK_PANED (container), widget, FALSE, FALSE); + priv->switcher = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); + gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, FALSE); + priv->content_notebook = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->switcher; + + widget = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); + gtk_container_add (GTK_CONTAINER (container), widget); + priv->sidebar_notebook = g_object_ref (widget); + gtk_widget_show (widget); + + container = priv->status_area; + + widget = e_online_button_new (); + g_signal_connect ( + widget, "clicked", + G_CALLBACK (shell_window_online_button_clicked_cb), + shell_window); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0); + priv->online_button = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->tooltip_label = g_object_ref (widget); + gtk_widget_hide (widget); + + widget = gtk_notebook_new (); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + priv->status_notebook = g_object_ref (widget); + gtk_widget_show (widget); +} + +void +e_shell_window_private_constructed (EShellWindow *shell_window) +{ + EShellWindowPrivate *priv = shell_window->priv; + EShellSettings *shell_settings; + EShell *shell; + GConfBridge *bridge; + GtkAction *action; + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + GObject *object; + const gchar *key; + const gchar *id; + + shell = e_shell_window_get_shell (shell_window); + shell_settings = e_shell_get_shell_settings (shell); + + e_shell_watch_window (shell, GTK_WINDOW (shell_window)); + + /* Create the switcher actions before we set the initial + * shell view, because the shell view relies on them for + * default settings during construction. */ + e_shell_window_create_switcher_actions (shell_window); + + /* Support lockdown. */ + + action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-printing", + G_OBJECT (action_group), "sensitive"); + + action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP); + + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-print-setup", + G_OBJECT (action_group), "sensitive"); + + action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); + + e_binding_new_with_negation ( + G_OBJECT (shell_settings), "disable-save-to-disk", + G_OBJECT (action_group), "sensitive"); + + /* Bind GObject properties to GObject properties. */ + + action = ACTION (SEND_RECEIVE); + + e_binding_new ( + G_OBJECT (shell), "online", + G_OBJECT (action), "sensitive"); + + action = ACTION (WORK_OFFLINE); + + e_binding_new ( + G_OBJECT (shell), "online", + G_OBJECT (action), "visible"); + + e_binding_new ( + G_OBJECT (shell), "network-available", + G_OBJECT (action), "sensitive"); + + action = ACTION (WORK_ONLINE); + + e_binding_new_with_negation ( + G_OBJECT (shell), "online", + G_OBJECT (action), "visible"); + + e_binding_new ( + G_OBJECT (shell), "network-available", + G_OBJECT (action), "sensitive"); + + e_binding_new ( + G_OBJECT (shell), "online", + G_OBJECT (priv->online_button), "online"); + + e_binding_new ( + G_OBJECT (shell), "network-available", + G_OBJECT (priv->online_button), "sensitive"); + + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + key = "/apps/evolution/shell/view_defaults/window"; + gconf_bridge_bind_window ( + bridge, key, GTK_WINDOW (shell_window), TRUE, TRUE); + + object = G_OBJECT (shell_window); + key = "/apps/evolution/shell/view_defaults/component_id"; + gconf_bridge_bind_property (bridge, key, object, "active-view"); + + object = G_OBJECT (priv->content_pane); + key = "/apps/evolution/shell/view_defaults/folder_bar/width"; + gconf_bridge_bind_property_delayed (bridge, key, object, "position"); + + object = G_OBJECT (ACTION (SHOW_SIDEBAR)); + key = "/apps/evolution/shell/view_defaults/sidebar_visible"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (SHOW_STATUSBAR)); + key = "/apps/evolution/shell/view_defaults/statusbar_visible"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (SHOW_SWITCHER)); + key = "/apps/evolution/shell/view_defaults/buttons_visible"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + object = G_OBJECT (ACTION (SHOW_TOOLBAR)); + key = "/apps/evolution/shell/view_defaults/toolbar_visible"; + gconf_bridge_bind_property (bridge, key, object, "active"); + + shell_window_init_switcher_style (shell_window); + + id = "org.gnome.evolution.shell"; + ui_manager = e_shell_window_get_ui_manager (shell_window); + e_plugin_ui_register_manager (ui_manager, id, shell_window); + e_plugin_ui_enable_manager (ui_manager, id); +} + +void +e_shell_window_private_dispose (EShellWindow *shell_window) +{ + EShellWindowPrivate *priv = shell_window->priv; + + /* Need to disconnect handlers before we unref the shell. */ + if (priv->signal_handler_ids != NULL) { + GArray *array = priv->signal_handler_ids; + gulong handler_id; + guint ii; + + for (ii = 0; ii < array->len; ii++) { + handler_id = g_array_index (array, gulong, ii); + g_signal_handler_disconnect (priv->shell, handler_id); + } + + g_array_free (array, TRUE); + priv->signal_handler_ids = NULL; + } + + if (priv->shell != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell), &priv->shell); + priv->shell = NULL; + } + + DISPOSE (priv->ui_manager); + + g_hash_table_remove_all (priv->loaded_views); + + DISPOSE (priv->main_menu); + DISPOSE (priv->main_toolbar); + DISPOSE (priv->menu_tool_button); + DISPOSE (priv->content_pane); + DISPOSE (priv->content_notebook); + DISPOSE (priv->sidebar_notebook); + DISPOSE (priv->switcher); + DISPOSE (priv->status_area); + DISPOSE (priv->online_button); + DISPOSE (priv->tooltip_label); + DISPOSE (priv->status_notebook); + + priv->destroyed = TRUE; +} + +void +e_shell_window_private_finalize (EShellWindow *shell_window) +{ + EShellWindowPrivate *priv = shell_window->priv; + + g_hash_table_destroy (priv->loaded_views); +} + +void +e_shell_window_switch_to_view (EShellWindow *shell_window, + const gchar *view_name) +{ + GtkNotebook *notebook; + EShellView *shell_view; + gint page_num; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + g_return_if_fail (view_name != NULL); + + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + + page_num = e_shell_view_get_page_num (shell_view); + g_return_if_fail (page_num >= 0); + + notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook); + gtk_notebook_set_current_page (notebook, page_num); + + notebook = GTK_NOTEBOOK (shell_window->priv->sidebar_notebook); + gtk_notebook_set_current_page (notebook, page_num); + + notebook = GTK_NOTEBOOK (shell_window->priv->status_notebook); + gtk_notebook_set_current_page (notebook, page_num); + + shell_window->priv->active_view = view_name; + g_object_notify (G_OBJECT (shell_window), "active-view"); + + e_shell_window_update_icon (shell_window); + e_shell_window_update_title (shell_window); + e_shell_window_update_new_menu (shell_window); + e_shell_window_update_view_menu (shell_window); + e_shell_window_update_search_menu (shell_window); + + e_shell_view_update_actions (shell_view); +} + +void +e_shell_window_update_icon (EShellWindow *shell_window) +{ + EShellView *shell_view; + GtkAction *action; + const gchar *view_name; + gchar *icon_name = NULL; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + + action = e_shell_view_get_action (shell_view); + g_object_get (action, "icon-name", &icon_name, NULL); + gtk_window_set_icon_name (GTK_WINDOW (shell_window), icon_name); + g_free (icon_name); +} + +void +e_shell_window_update_title (EShellWindow *shell_window) +{ + EShellView *shell_view; + const gchar *view_title; + const gchar *view_name; + gchar *window_title; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + + view_name = e_shell_window_get_active_view (shell_window); + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + view_title = e_shell_view_get_title (shell_view); + + /* Translators: This is used for the main window title. */ + window_title = g_strdup_printf (_("%s - Evolution"), view_title); + gtk_window_set_title (GTK_WINDOW (shell_window), window_title); + g_free (window_title); +} + +void +e_shell_window_update_new_menu (EShellWindow *shell_window) +{ + GtkWidget *menu; + GtkWidget *widget; + const gchar *path; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + + /* Update the "File -> New" submenu. */ + path = "/main-menu/file-menu/new-menu"; + menu = e_shell_window_create_new_menu (shell_window); + widget = e_shell_window_get_managed_widget (shell_window, path); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu); + gtk_widget_show (widget); + + /* Update the "New" menu tool button submenu. */ + menu = e_shell_window_create_new_menu (shell_window); + widget = shell_window->priv->menu_tool_button; + gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (widget), menu); +} diff --git a/shell/e-shell-window-private.h b/shell/e-shell-window-private.h new file mode 100644 index 0000000000..5314a3679f --- /dev/null +++ b/shell/e-shell-window-private.h @@ -0,0 +1,128 @@ +/* + * e-shell-window-private.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_SHELL_WINDOW_PRIVATE_H +#define E_SHELL_WINDOW_PRIVATE_H + +#include "e-shell-window.h" + +#include <string.h> +#include <glib/gi18n.h> + +#include <e-util/e-util.h> +#include <e-util/e-binding.h> +#include <e-util/e-plugin-ui.h> +#include <e-util/gconf-bridge.h> +#include <widgets/misc/e-menu-tool-button.h> +#include <widgets/misc/e-online-button.h> + +#include <e-shell.h> +#include <e-shell-content.h> +#include <e-shell-view.h> +#include <e-shell-switcher.h> +#include <e-shell-window-actions.h> + +#define E_SHELL_WINDOW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_WINDOW, EShellWindowPrivate)) + +/* Shorthand, requires a variable named "shell_window". */ +#define ACTION(name) \ + (E_SHELL_WINDOW_ACTION_##name (shell_window)) +#define ACTION_GROUP(name) \ + (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + +/* For use in dispose() methods. */ +#define DISPOSE(obj) \ + G_STMT_START { \ + if ((obj) != NULL) { g_object_unref (obj); (obj) = NULL; } \ + } G_STMT_END + +/* Format for switcher action names. + * The last part is the shell view name. + * (e.g. switch-to-mail, switch-to-calendar) */ +#define SWITCHER_FORMAT "switch-to-%s" + +G_BEGIN_DECLS + +struct _EShellWindowPrivate { + + gpointer shell; /* weak pointer */ + + /*** UI Management ***/ + + GtkUIManager *ui_manager; + guint custom_rule_merge_id; + guint gal_view_merge_id; + + /*** Shell Views ***/ + + GHashTable *loaded_views; + const gchar *active_view; + + /*** Widgetry ***/ + + GtkWidget *main_menu; + GtkWidget *main_toolbar; + GtkWidget *menu_tool_button; + GtkWidget *content_pane; + GtkWidget *content_notebook; + GtkWidget *sidebar_notebook; + GtkWidget *switcher; + GtkWidget *status_area; + GtkWidget *online_button; + GtkWidget *tooltip_label; + GtkWidget *status_notebook; + + /* Miscellaneous */ + + /* Shell signal handlers. */ + GArray *signal_handler_ids; + + guint destroyed : 1; /* XXX Do we still need this? */ + guint safe_mode : 1; +}; + +void e_shell_window_private_init (EShellWindow *shell_window); +void e_shell_window_private_constructed + (EShellWindow *shell_window); +void e_shell_window_private_dispose (EShellWindow *shell_window); +void e_shell_window_private_finalize (EShellWindow *shell_window); + +/* Private Utilities */ + +void e_shell_window_actions_init (EShellWindow *shell_window); +void e_shell_window_switch_to_view (EShellWindow *shell_window, + const gchar *view_name); +GtkWidget * e_shell_window_create_new_menu (EShellWindow *shell_window); +void e_shell_window_create_switcher_actions + (EShellWindow *shell_window); +void e_shell_window_update_gal_view (EShellWindow *shell_window); +void e_shell_window_update_icon (EShellWindow *shell_window); +void e_shell_window_update_title (EShellWindow *shell_window); +void e_shell_window_update_new_menu (EShellWindow *shell_window); +void e_shell_window_update_view_menu (EShellWindow *shell_window); +void e_shell_window_update_search_menu + (EShellWindow *shell_window); + +G_END_DECLS + +#endif /* E_SHELL_WINDOW_PRIVATE_H */ diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index 69980dc5c5..19392094ee 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -1,4 +1,6 @@ /* + * e-shell-window.c + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -13,1248 +15,859 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-shell-window.h" -#include "e-shell-view.h" - -#include "Evolution.h" - -#include "e-util/e-util-private.h" -#include "widgets/misc/e-online-button.h" - -#include "e-component-registry.h" -#include "e-shell-window-commands.h" -#include "e-sidebar.h" -#include "es-menu.h" -#include "es-event.h" - -#include <gtk/gtk.h> - -#include <bonobo/bonobo-exception.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-ui-util.h> -#include <bonobo/bonobo-widget.h> - -#include <glib/gi18n.h> +#include "e-shell-window-private.h" #include <gconf/gconf-client.h> -#include <string.h> +#include <e-util/e-plugin-ui.h> +#include <e-util/e-util-private.h> -#if defined(NM_SUPPORT) && NM_SUPPORT -gboolean e_shell_dbus_initialise (EShell *shell); -#endif - -/* A view for each component. These are all created when EShellWindow is - instantiated, but with the widget pointers to NULL and the page number set - to -1. When the views are created the first time, the widget pointers as - well as the notebook page value get set. */ -struct _ComponentView { - gint button_id; - gchar *component_id; - gchar *component_alias; - - GNOME_Evolution_ComponentView component_view; - gchar *title; - - GtkWidget *sidebar_widget; - GtkWidget *view_widget; - GtkWidget *statusbar_widget; - - gint notebook_page_num; +enum { + PROP_0, + PROP_ACTIVE_VIEW, + PROP_SAFE_MODE, + PROP_SHELL, + PROP_UI_MANAGER }; -typedef struct _ComponentView ComponentView; - -struct _EShellWindowPrivate { - union { - EShell *eshell; - gpointer pointer; - } shell; - - EShellView *shell_view; /* CORBA wrapper for this, just a placeholder */ - - /* plugin menu manager */ - ESMenu *menu; - /* All the ComponentViews. */ - GSList *component_views; +static gpointer parent_class; - /* The paned widget for the sidebar and component views */ - GtkWidget *paned; - - /* The sidebar. */ - GtkWidget *sidebar; - - /* Notebooks used to switch between components. */ - GtkWidget *sidebar_notebook; - GtkWidget *view_notebook; - GtkWidget *statusbar_notebook; - - /* Bonobo foo. */ - BonoboUIComponent *ui_component; - - /* The current view (can be NULL initially). */ - ComponentView *current_view; - - /* The status bar widgetry. */ - GtkWidget *status_bar; - GtkWidget *offline_toggle; - GtkWidget *menu_hint_label; +static EShellView * +shell_window_new_view (EShellBackend *shell_backend, + EShellWindow *shell_window) +{ + GHashTable *loaded_views; + EShellView *shell_view; + GtkNotebook *notebook; + GtkAction *action; + GtkWidget *widget; + const gchar *name; + gint page_num; + GType type; - /* The timeout for saving the window size */ - guint store_window_gsizeimer; - gboolean destroyed; -}; + name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + type = E_SHELL_BACKEND_GET_CLASS (shell_backend)->shell_view_type; -enum { - COMPONENT_CHANGED, - LAST_SIGNAL -}; + /* First off, start the shell backend. */ + e_shell_backend_start (shell_backend); -static guint signals[LAST_SIGNAL] = { 0 }; + /* Determine the page number for the new shell view. */ + notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook); + page_num = gtk_notebook_get_n_pages (notebook); -G_DEFINE_TYPE (EShellWindow, e_shell_window, BONOBO_TYPE_WINDOW) + /* Get the switcher action for this view. */ + action = e_shell_window_get_shell_view_action (shell_window, name); -static gboolean store_window_size (GtkWidget* widget); + /* Create the shell view. */ + shell_view = g_object_new ( + type, "action", action, "page-num",page_num, + "shell-window", shell_window, NULL); -/* ComponentView handling. */ + /* Register the shell view. */ + loaded_views = shell_window->priv->loaded_views; + g_hash_table_insert (loaded_views, g_strdup (name), shell_view); -static ComponentView * -component_view_new (const gchar *id, const gchar *alias, gint button_id) -{ - ComponentView *view = g_new0 (ComponentView, 1); + /* Add pages to the various shell window notebooks. */ - view->component_id = g_strdup (id); - view->component_alias = g_strdup (alias); - view->button_id = button_id; - view->notebook_page_num = -1; + /* We can't determine the shell view's page number until after the + * shell view is fully initialized because the shell view may load + * other shell views during initialization, and those other shell + * views will append their widgets to the notebooks before us. */ + page_num = gtk_notebook_get_n_pages (notebook); + e_shell_view_set_page_num (shell_view, page_num); - return view; -} + notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook); + widget = GTK_WIDGET (e_shell_view_get_shell_content (shell_view)); + gtk_notebook_append_page (notebook, widget, NULL); -static void -component_view_free (ComponentView *view) -{ - if (view->component_view) { - CORBA_Environment ev = { NULL }; + notebook = GTK_NOTEBOOK (shell_window->priv->sidebar_notebook); + widget = GTK_WIDGET (e_shell_view_get_shell_sidebar (shell_view)); + gtk_notebook_append_page (notebook, widget, NULL); - CORBA_Object_release(view->component_view, &ev); - CORBA_exception_free(&ev); - } + notebook = GTK_NOTEBOOK (shell_window->priv->status_notebook); + widget = GTK_WIDGET (e_shell_view_get_shell_taskbar (shell_view)); + gtk_notebook_append_page (notebook, widget, NULL); - g_free (view->component_id); - g_free (view->component_alias); - g_free (view->title); - g_free (view); -} + /* Listen for changes that affect the shell window. */ -static void -component_view_deactivate (ComponentView *view) -{ - BonoboControlFrame *view_control_frame; - BonoboControlFrame *sidebar_control_frame; + g_signal_connect_swapped ( + action, "notify::icon-name", + G_CALLBACK (e_shell_window_update_icon), shell_window); - g_return_if_fail (view->sidebar_widget != NULL); - g_return_if_fail (view->view_widget != NULL); + g_signal_connect_swapped ( + shell_view, "notify::title", + G_CALLBACK (e_shell_window_update_title), shell_window); - view_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->view_widget)); - bonobo_control_frame_control_deactivate (view_control_frame); + g_signal_connect_swapped ( + shell_view, "notify::view-id", + G_CALLBACK (e_shell_window_update_view_menu), shell_window); - sidebar_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->sidebar_widget)); - bonobo_control_frame_control_deactivate (sidebar_control_frame); + return shell_view; } static void -component_view_activate (ComponentView *view) +shell_window_update_close_action_cb (EShellWindow *shell_window) { - BonoboControlFrame *view_control_frame; - BonoboControlFrame *sidebar_control_frame; + EShell *shell; + GList *watched_windows; + gint n_shell_windows = 0; - g_return_if_fail (view->sidebar_widget != NULL); - g_return_if_fail (view->view_widget != NULL); + shell = e_shell_window_get_shell (shell_window); + watched_windows = e_shell_get_watched_windows (shell); - view_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->view_widget)); - bonobo_control_frame_control_activate (view_control_frame); + /* Count the shell windows. */ + while (watched_windows != NULL) { + if (E_IS_SHELL_WINDOW (watched_windows->data)) + n_shell_windows++; + watched_windows = g_list_next (watched_windows); + } - sidebar_control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET (view->sidebar_widget)); - bonobo_control_frame_control_activate (sidebar_control_frame); + /* Disable Close Window if there's only one shell window. + * Helps prevent users from accidentally quitting. */ + gtk_action_set_sensitive (ACTION (CLOSE), n_shell_windows > 1); } static void -init_view (EShellWindow *window, - ComponentView *view) +shell_window_set_shell (EShellWindow *shell_window, + EShell *shell) { - EShellWindowPrivate *priv = window->priv; - EComponentRegistry *registry = e_shell_peek_component_registry (window->priv->shell.eshell); - GNOME_Evolution_Component component_iface; - GNOME_Evolution_ComponentView component_view; - Bonobo_UIContainer container; - Bonobo_Control sidebar_control; - Bonobo_Control view_control; - Bonobo_Control statusbar_control; - CORBA_boolean select_item; - CORBA_Environment ev; - gint sidebar_notebook_page_num; - gint view_notebook_page_num; - - g_return_if_fail (view->view_widget == NULL); - g_return_if_fail (view->sidebar_widget == NULL); - g_return_if_fail (view->notebook_page_num == -1); - - select_item = !e_shell_get_crash_recovery (priv->shell.eshell); - e_shell_set_crash_recovery (priv->shell.eshell, FALSE); - - CORBA_exception_init (&ev); - - /* 1. Activate component. (FIXME: Shouldn't do this here.) */ - - component_iface = e_component_registry_activate (registry, view->component_id, &ev); - if (BONOBO_EX (&ev) || component_iface == CORBA_OBJECT_NIL) { - gchar *ex_text = bonobo_exception_get_text (&ev); - g_warning ("Cannot activate component %s: %s", view->component_id, ex_text); - g_free (ex_text); - CORBA_exception_free (&ev); - return; - } - - /* 2. Set up view. */ - - /* The rest of the code assumes that the component is valid and can create - controls; if this fails something is really wrong in the component - (e.g. methods not implemented)... So handle it as if there was no - component at all. */ - - component_view = GNOME_Evolution_Component_createView(component_iface, BONOBO_OBJREF(priv->shell_view), select_item, &ev); - if (component_view == NULL || BONOBO_EX (&ev)) { - g_warning ("Cannot create view for %s", view->component_id); - bonobo_object_release_unref (component_iface, NULL); - CORBA_exception_free (&ev); - return; - } - - GNOME_Evolution_ComponentView_getControls(component_view, &sidebar_control, &view_control, &statusbar_control, &ev); - if (BONOBO_EX (&ev)) { - g_warning ("Cannot create view for %s", view->component_id); - bonobo_object_release_unref (component_iface, NULL); - CORBA_exception_free (&ev); - return; - } - - view->component_view = component_view; - - CORBA_exception_free (&ev); + GArray *array; + gulong handler_id; - container = bonobo_ui_component_get_container (priv->ui_component); + g_return_if_fail (shell_window->priv->shell == NULL); - view->sidebar_widget = bonobo_widget_new_control_from_objref (sidebar_control, container); - gtk_widget_show (view->sidebar_widget); - bonobo_object_release_unref (sidebar_control, NULL); + shell_window->priv->shell = shell; - view->view_widget = bonobo_widget_new_control_from_objref (view_control, container); - gtk_widget_show (view->view_widget); - bonobo_object_release_unref (view_control, NULL); + g_object_add_weak_pointer ( + G_OBJECT (shell), &shell_window->priv->shell); - view->statusbar_widget = bonobo_widget_new_control_from_objref (statusbar_control, container); - gtk_widget_show (view->statusbar_widget); - bonobo_object_release_unref (statusbar_control, NULL); + /* Need to disconnect these when the window is closing. */ - gtk_notebook_append_page (GTK_NOTEBOOK (priv->sidebar_notebook), view->sidebar_widget, NULL); - gtk_notebook_append_page (GTK_NOTEBOOK (priv->view_notebook), view->view_widget, NULL); - gtk_notebook_append_page (GTK_NOTEBOOK (priv->statusbar_notebook), view->statusbar_widget, NULL); + array = shell_window->priv->signal_handler_ids; - sidebar_notebook_page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->sidebar_notebook), view->sidebar_widget); - view_notebook_page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->view_notebook), view->view_widget); + handler_id = g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (shell_window_update_close_action_cb), + shell_window); - /* Since we always add a view page and a sidebar page at the same time... */ - g_return_if_fail (sidebar_notebook_page_num == view_notebook_page_num); + g_array_append_val (array, handler_id); - view->notebook_page_num = view_notebook_page_num; + handler_id = g_signal_connect_swapped ( + shell, "window-destroyed", + G_CALLBACK (shell_window_update_close_action_cb), + shell_window); - /* 3. Switch to the new page. */ + g_array_append_val (array, handler_id); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->view_notebook), view_notebook_page_num); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->sidebar_notebook), view_notebook_page_num); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->statusbar_notebook), view_notebook_page_num); - - if (priv->current_view != NULL) - component_view_deactivate (priv->current_view); - priv->current_view = view; - component_view_activate (view); - - bonobo_object_release_unref (component_iface, NULL); + g_object_notify (G_OBJECT (shell), "online"); } static void -switch_view (EShellWindow *window, ComponentView *component_view) +shell_window_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - EShellWindowPrivate *priv = window->priv; - GConfClient *gconf_client = gconf_client_get_default (); - EComponentRegistry *registry = e_shell_peek_component_registry (window->priv->shell.eshell); - EComponentInfo *info = e_component_registry_peek_info (registry, - ECR_FIELD_ID, - component_view->component_id); - gchar *title; - - if (component_view->sidebar_widget == NULL) { - init_view (window, component_view); - } else { - if (priv->current_view != NULL) - component_view_deactivate (priv->current_view); - priv->current_view = component_view; - component_view_activate (component_view); - - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->view_notebook), component_view->notebook_page_num); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->sidebar_notebook), component_view->notebook_page_num); - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->statusbar_notebook), component_view->notebook_page_num); - } - - if (component_view->title == NULL) { - /* To translators: This is the window title and %s is the - component name. Most translators will want to keep it as is. */ - title = g_strdup_printf (_("%s - Evolution"), info->button_label); - gtk_window_set_title (GTK_WINDOW (window), title); - g_free (title); - } else - gtk_window_set_title (GTK_WINDOW (window), component_view->title); - - if (info->icon_name) - gtk_window_set_icon_name (GTK_WINDOW (window), info->icon_name); - - gconf_client_set_string (gconf_client, "/apps/evolution/shell/view_defaults/component_id", - (component_view->component_alias != NULL - ? component_view->component_alias - : component_view->component_id), - NULL); - - g_object_unref (gconf_client); - - /** @Event: Shell component activated or switched to. - * @Id: component.activated - * @Target: ESEventTargetComponent - * - * This event is emitted whenever the shell successfully activates component - * view. - */ - e_event_emit ((EEvent *) es_event_peek (), "component.activated", (EEventTarget *) es_event_target_new_component (es_event_peek (), component_view->component_id)); - - g_signal_emit (window, signals[COMPONENT_CHANGED], 0); -} + switch (property_id) { + case PROP_ACTIVE_VIEW: + e_shell_window_set_active_view ( + E_SHELL_WINDOW (object), + g_value_get_string (value)); + return; -/* Functions to update the sensitivity of buttons and menu items depending on the status. */ + case PROP_SAFE_MODE: + e_shell_window_set_safe_mode ( + E_SHELL_WINDOW (object), + g_value_get_boolean (value)); + return; -static void -update_offline_toggle_status (EShellWindow *window) -{ - EShellWindowPrivate *priv; - GtkWidget *widget; - const gchar *tooltip; - gboolean online; - gboolean sensitive; - guint32 flags = 0; - ESMenuTargetShell *t; - - priv = window->priv; - - switch (e_shell_get_line_status (priv->shell.eshell)) { - case E_SHELL_LINE_STATUS_ONLINE: - online = TRUE; - sensitive = TRUE; - tooltip = _("Evolution is currently online.\n" - "Click on this button to work offline."); - flags = ES_MENU_SHELL_ONLINE; - break; - case E_SHELL_LINE_STATUS_GOING_OFFLINE: - online = TRUE; - sensitive = FALSE; - tooltip = _("Evolution is in the process of going offline."); - flags = ES_MENU_SHELL_OFFLINE; - break; - case E_SHELL_LINE_STATUS_OFFLINE: - case E_SHELL_LINE_STATUS_FORCED_OFFLINE: - online = FALSE; - sensitive = TRUE; - tooltip = _("Evolution is currently offline.\n" - "Click on this button to work online."); - flags = ES_MENU_SHELL_OFFLINE; - break; - default: - g_return_if_reached (); + case PROP_SHELL: + shell_window_set_shell ( + E_SHELL_WINDOW (object), + g_value_get_object (value)); + return; } - widget = window->priv->offline_toggle; - gtk_widget_set_sensitive (widget, sensitive); - gtk_widget_set_tooltip_text (widget, tooltip); - e_online_button_set_online (E_ONLINE_BUTTON (widget), online); - - /* TODO: If we get more shell flags, this should be centralised */ - t = es_menu_target_new_shell(priv->menu, flags); - t->target.widget = (GtkWidget *)window; - e_menu_update_target((EMenu *)priv->menu, t); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -update_send_receive_sensitivity (EShellWindow *window) +shell_window_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - if (e_shell_get_line_status (window->priv->shell.eshell) == E_SHELL_LINE_STATUS_OFFLINE || - e_shell_get_line_status (window->priv->shell.eshell) == E_SHELL_LINE_STATUS_FORCED_OFFLINE) - bonobo_ui_component_set_prop (window->priv->ui_component, - "/commands/SendReceive", - "sensitive", "0", NULL); - else - bonobo_ui_component_set_prop (window->priv->ui_component, - "/commands/SendReceive", - "sensitive", "1", NULL); -} + switch (property_id) { + case PROP_ACTIVE_VIEW: + g_value_set_string ( + value, e_shell_window_get_active_view ( + E_SHELL_WINDOW (object))); + return; -/* Callbacks. */ + case PROP_SAFE_MODE: + g_value_set_boolean ( + value, e_shell_window_get_safe_mode ( + E_SHELL_WINDOW (object))); + return; -static ComponentView * -get_component_view (EShellWindow *window, gint id) -{ - GSList *p; + case PROP_SHELL: + g_value_set_object ( + value, e_shell_window_get_shell ( + E_SHELL_WINDOW (object))); + return; - for (p = window->priv->component_views; p; p = p->next) { - if (((ComponentView *) p->data)->button_id == id) - return p->data; + case PROP_UI_MANAGER: + g_value_set_object ( + value, e_shell_window_get_ui_manager ( + E_SHELL_WINDOW (object))); + return; } - g_warning ("Unknown component button id %d", id); - return NULL; -} - -static void -sidebar_button_selected_callback (ESidebar *sidebar, - gint button_id, - EShellWindow *window) -{ - ComponentView *component_view; - - if ((component_view = get_component_view (window, button_id))) - switch_view (window, component_view); -} - -static gboolean -sidebar_button_pressed_callback (ESidebar *sidebar, - GdkEventButton *event, - gint button_id, - EShellWindow *window) -{ - if (event->type == GDK_BUTTON_PRESS && - event->button == 2) { - /* open it in a new window */ - ComponentView *component_view; - - if ((component_view = get_component_view (window, button_id))) { - e_shell_create_window (window->priv->shell.eshell, - component_view->component_id, - window); - } - return TRUE; - } - return FALSE; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -offline_toggle_clicked_cb (EShellWindow *window) +shell_window_dispose (GObject *object) { - EShell *shell; - GNOME_Evolution_ShellState shell_state; - - shell = window->priv->shell.eshell; - - switch (e_shell_get_line_status (shell)) { - case E_SHELL_LINE_STATUS_ONLINE: - shell_state = GNOME_Evolution_USER_OFFLINE; - break; - case E_SHELL_LINE_STATUS_OFFLINE: - case E_SHELL_LINE_STATUS_FORCED_OFFLINE: - shell_state = GNOME_Evolution_USER_ONLINE; - break; - default: - g_return_if_reached(); - } + e_shell_window_private_dispose (E_SHELL_WINDOW (object)); - e_shell_set_line_status (shell, shell_state); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -shell_line_status_changed_callback (EShell *shell, - EShellLineStatus new_status, - EShellWindow *window) +shell_window_finalize (GObject *object) { - update_offline_toggle_status (window); - update_send_receive_sensitivity (window); -} + e_shell_window_private_finalize (E_SHELL_WINDOW (object)); -static void -ui_engine_add_hint_callback (BonoboUIEngine *engine, - const gchar *hint, - EShellWindow *window) -{ - gtk_label_set_text (GTK_LABEL (window->priv->menu_hint_label), hint); - gtk_widget_show (window->priv->menu_hint_label); - gtk_widget_hide (window->priv->statusbar_notebook); + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -ui_engine_remove_hint_callback (BonoboUIEngine *engine, - EShellWindow *window) +shell_window_constructed (GObject *object) { - gtk_widget_hide (window->priv->menu_hint_label); - gtk_widget_show (window->priv->statusbar_notebook); + e_shell_window_private_constructed (E_SHELL_WINDOW (object)); } -/* Widgetry. */ - static void -setup_offline_toggle (EShellWindow *window) +shell_window_class_init (EShellWindowClass *class) { - GtkWidget *widget; + GObjectClass *object_class; - g_return_if_fail (window->priv->status_bar != NULL); + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellWindowPrivate)); - widget = e_online_button_new (); - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (offline_toggle_clicked_cb), window); - gtk_box_pack_start ( - GTK_BOX (window->priv->status_bar), - widget, FALSE, TRUE, 0); - window->priv->offline_toggle = widget; - gtk_widget_show (widget); - - update_offline_toggle_status (window); -} + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_window_set_property; + object_class->get_property = shell_window_get_property; + object_class->dispose = shell_window_dispose; + object_class->finalize = shell_window_finalize; + object_class->constructed = shell_window_constructed; -static void -setup_menu_hint_label (EShellWindow *window) -{ - EShellWindowPrivate *priv; - - priv = window->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); + /** + * EShellWindow:active-view + * + * Name of the active #EShellView. + **/ + g_object_class_install_property ( + object_class, + PROP_ACTIVE_VIEW, + g_param_spec_string ( + "active-view", + _("Active Shell View"), + _("Name of the active shell view"), + NULL, + G_PARAM_READWRITE)); + + /** + * EShellWindow:safe-mode + * + * Whether the shell window is in safe mode. + **/ + g_object_class_install_property ( + object_class, + PROP_SAFE_MODE, + g_param_spec_boolean ( + "safe-mode", + _("Safe Mode"), + _("Whether the shell window is in safe mode"), + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * EShellWindow:shell + * + * The #EShell singleton. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL, + g_param_spec_object ( + "shell", + _("Shell"), + _("The EShell singleton"), + E_TYPE_SHELL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + /** + * EShellWindow:ui-manager + * + * The shell window's #GtkUIManager. + **/ + g_object_class_install_property ( + object_class, + PROP_UI_MANAGER, + g_param_spec_object ( + "ui-manager", + _("UI Manager"), + _("The shell window's GtkUIManager"), + GTK_TYPE_UI_MANAGER, + G_PARAM_READABLE)); } static void -setup_statusbar_notebook (EShellWindow *window) +shell_window_init (EShellWindow *shell_window) { - EShellWindowPrivate *priv; - - priv = window->priv; + shell_window->priv = E_SHELL_WINDOW_GET_PRIVATE (shell_window); - priv->statusbar_notebook = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->statusbar_notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->statusbar_notebook), FALSE); - - gtk_box_pack_start (GTK_BOX (priv->status_bar), priv->statusbar_notebook, TRUE, TRUE, 0); - gtk_widget_show (priv->statusbar_notebook); -} - -static void -setup_nm_support (EShellWindow *window) -{ -#if defined(NM_SUPPORT) && NM_SUPPORT - e_shell_dbus_initialise (window->priv->shell.eshell); -#endif + e_shell_window_private_init (shell_window); } -static void -setup_status_bar (EShellWindow *window) +GType +e_shell_window_get_type (void) { - EShellWindowPrivate *priv; - BonoboUIEngine *ui_engine; - GConfClient *gconf_client; - gint height; - - priv = window->priv; - - priv->status_bar = gtk_hbox_new (FALSE, 2); + static GType type = 0; - /* Make the status bar as large as the task bar. */ - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height); - gtk_widget_set_size_request (GTK_WIDGET (priv->status_bar), -1, height * 2); + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EShellWindowClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_window_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellWindow), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_window_init, + NULL /* value_table */ + }; - gconf_client = gconf_client_get_default (); - if (gconf_client_get_bool (gconf_client,"/apps/evolution/shell/view_defaults/statusbar_visible",NULL)) - gtk_widget_show (priv->status_bar); - g_object_unref (gconf_client); - - /* setup dbus interface here*/ - setup_nm_support (window); - - setup_offline_toggle (window); - setup_menu_hint_label (window); - setup_statusbar_notebook (window); - - ui_engine = bonobo_window_get_ui_engine (BONOBO_WINDOW (window)); + type = g_type_register_static ( + GTK_TYPE_WINDOW, "EShellWindow", &type_info, 0); + } - g_signal_connect (ui_engine, "add_hint", G_CALLBACK (ui_engine_add_hint_callback), window); - g_signal_connect (ui_engine, "remove_hint", G_CALLBACK (ui_engine_remove_hint_callback), window); + return type; } -static void -menu_component_selected (BonoboUIComponent *uic, - EShellWindow *window, - const gchar *path) +/** + * e_shell_window_new: + * @shell: an #EShell + * @safe_mode: whether to initialize the window to "safe mode" + * + * Returns a new #EShellWindow. + * + * It's up to the various #EShellView<!-- -->'s to define exactly + * what "safe mode" means, but the #EShell usually puts the initial + * #EShellWindow into "safe mode" if detects the previous Evolution + * session crashed. + * + * The initial view for the window is determined by GConf key + * <filename>/apps/evolution/shell/view_defaults/component_id</filename>. + * Or, if the GConf key is not set or can't be read, the first view + * in the switcher is used. + * + * Returns: a new #EShellWindow + **/ +GtkWidget * +e_shell_window_new (EShell *shell, + gboolean safe_mode) { - gchar *component_id; - - component_id = strchr(path, '-'); - if (component_id) - e_shell_window_switch_to_component (window, component_id+1); + return g_object_new ( + E_TYPE_SHELL_WINDOW, + "shell", shell, "safe-mode", safe_mode, NULL); } -static GConfEnumStringPair button_styles[] = { - { E_SIDEBAR_MODE_TEXT, "text" }, - { E_SIDEBAR_MODE_ICON, "icons" }, - { E_SIDEBAR_MODE_BOTH, "both" }, - { E_SIDEBAR_MODE_TOOLBAR, "toolbar" }, - { -1, NULL } -}; - -static void -setup_widgets (EShellWindow *window) +/** + * e_shell_window_get_shell: + * @shell_window: an #EShellWindow + * + * Returns the #EShell that was passed to e_shell_window_new(). + * + * Returns: the #EShell + **/ +EShell * +e_shell_window_get_shell (EShellWindow *shell_window) { - EShellWindowPrivate *priv = window->priv; - EComponentRegistry *registry = e_shell_peek_component_registry (priv->shell.eshell); - GConfClient *gconf_client = gconf_client_get_default (); - GtkWidget *contents_vbox; - GSList *p; - GString *xml; - gint button_id; - gboolean visible; - gchar *style; - gint mode; - - priv->paned = gtk_hpaned_new (); - gtk_widget_show (priv->paned); - - priv->sidebar = e_sidebar_new (); - g_signal_connect (priv->sidebar, "button_selected", - G_CALLBACK (sidebar_button_selected_callback), window); - g_signal_connect (priv->sidebar, "button_pressed", - G_CALLBACK (sidebar_button_pressed_callback), window); - gtk_paned_pack1 (GTK_PANED (priv->paned), priv->sidebar, FALSE, FALSE); - gtk_widget_show (priv->sidebar); - - priv->sidebar_notebook = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->sidebar_notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->sidebar_notebook), FALSE); - e_sidebar_set_selection_widget (E_SIDEBAR (priv->sidebar), priv->sidebar_notebook); - gtk_widget_show (priv->sidebar_notebook); - - priv->view_notebook = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->view_notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->view_notebook), FALSE); - gtk_paned_pack2 (GTK_PANED (priv->paned), priv->view_notebook, TRUE, FALSE); - gtk_widget_show (priv->view_notebook); - - gtk_paned_set_position (GTK_PANED (priv->paned), - gconf_client_get_int (gconf_client, "/apps/evolution/shell/view_defaults/folder_bar/width", NULL)); - - /* The buttons */ - visible = gconf_client_get_bool (gconf_client, - "/apps/evolution/shell/view_defaults/buttons_visible", - NULL); - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewButtonsHide", - "state", - visible ? "0" : "1", - NULL); - - e_sidebar_set_show_buttons (E_SIDEBAR (priv->sidebar), visible); - - style = gconf_client_get_string (gconf_client, - "/apps/evolution/shell/view_defaults/buttons_style", - NULL); - - if (gconf_string_to_enum (button_styles, style, &mode)) { - switch (mode) { - case E_SIDEBAR_MODE_TEXT: - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewButtonsText", - "state", "1", NULL); - break; - case E_SIDEBAR_MODE_ICON: - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewButtonsIcon", - "state", "1", NULL); - break; - case E_SIDEBAR_MODE_BOTH: - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewButtonsIconText", - "state", "1", NULL); - break; - - case E_SIDEBAR_MODE_TOOLBAR: - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewButtonsToolbar", - "state", "1", NULL); - break; - } - - e_sidebar_set_mode (E_SIDEBAR (priv->sidebar), mode); - } - g_free (style); - - /* Status Bar*/ - visible = gconf_client_get_bool (gconf_client, - "/apps/evolution/shell/view_defaults/statusbar_visible", - NULL); - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewStatusBar", - "state", - visible ? "1" : "0", - NULL); - - /* Side Bar*/ - visible = gconf_client_get_bool (gconf_client, - "/apps/evolution/shell/view_defaults/sidebar_visible", - NULL); - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewSideBar", - "state", - visible ? "1" : "0", - NULL); - - /* The tool bar */ - visible = gconf_client_get_bool (gconf_client, - "/apps/evolution/shell/view_defaults/toolbar_visible", - NULL); - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewToolbar", - "state", - visible ? "1" : "0", - NULL); - bonobo_ui_component_set_prop (e_shell_window_peek_bonobo_ui_component (window), - "/Toolbar", - "hidden", - visible ? "0" : "1", - NULL); - - button_id = 0; - xml = g_string_new(""); - for (p = e_component_registry_peek_list (registry); p != NULL; p = p->next) { - gchar *tmp, *tmp2; - EComponentInfo *info = p->data; - ComponentView *view = component_view_new (info->id, info->alias, button_id); - GtkIconInfo *icon_info; - gint width; - - window->priv->component_views = g_slist_prepend (window->priv->component_views, view); - - if (!info->button_label || !info->menu_label) - continue; - e_sidebar_add_button (E_SIDEBAR (priv->sidebar), info->button_label, info->button_tooltips, info->icon_name, button_id); - - g_string_printf(xml, "SwitchComponent-%s", info->alias); - bonobo_ui_component_add_verb (e_shell_window_peek_bonobo_ui_component (window), - xml->str, - (BonoboUIVerbFn)menu_component_selected, - window); - - g_string_printf(xml, "<submenu name=\"View\">" - "<submenu name=\"Window\">" - "<placeholder name=\"WindowComponent\">" - "<menuitem name=\"SwitchComponent-%s\" " - "verb=\"\" label=\"%s\" accel=\"%s\" tip=\"", - info->alias, - info->menu_label, - info->menu_accelerator); - tmp = g_strdup_printf (_("Switch to %s"), info->button_label); - tmp2 = g_markup_escape_text (tmp, -1); - g_string_append (xml, tmp2); - g_free (tmp2); - g_free (tmp); - - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, NULL); - icon_info = gtk_icon_theme_lookup_icon ( - gtk_icon_theme_get_default (), - info->icon_name, width, 0); - g_string_append_printf(xml, "\" pixtype=\"filename\" pixname=\"%s\"/>" - "</placeholder></submenu></submenu>\n", - icon_info ? gtk_icon_info_get_filename (icon_info) : ""); - gtk_icon_info_free (icon_info); - bonobo_ui_component_set_translate (e_shell_window_peek_bonobo_ui_component (window), - "/menu", - xml->str, - NULL); - g_string_printf(xml, "<cmd name=\"SwitchComponent-%s\"/>\n", info->alias); - bonobo_ui_component_set_translate (e_shell_window_peek_bonobo_ui_component (window), - "/commands", - xml->str, - NULL); - button_id ++; - } - g_string_free(xml, TRUE); + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); - setup_status_bar (window); - - contents_vbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (contents_vbox), priv->paned, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (contents_vbox), priv->status_bar, FALSE, TRUE, 0); - gtk_widget_show (contents_vbox); - - /* We only display this when a menu item is actually selected. */ - gtk_widget_hide (priv->menu_hint_label); - - bonobo_window_set_contents (BONOBO_WINDOW (window), contents_vbox); - g_object_unref (gconf_client); + return E_SHELL (shell_window->priv->shell); } -/* GObject methods. */ - -static void -impl_dispose (GObject *object) +/** + * e_shell_window_get_shell_view: + * @shell_window: an #EShellWindow + * @view_name: name of a shell view + * + * Returns the #EShellView named @view_name (see the + * <structfield>name</structfield> field in #EShellBackendInfo). This + * will also instantiate the #EShellView the first time it's requested. + * To reduce resource consumption, Evolution tries to delay instantiating + * shell views until the user switches to them. So in general, only the + * active view name, as returned by e_shell_window_get_active_view(), + * should be requested. + * + * Returns: the requested #EShellView, or %NULL if no such view is + * registered + **/ +EShellView * +e_shell_window_get_shell_view (EShellWindow *shell_window, + const gchar *view_name) { - EShellWindow *self = E_SHELL_WINDOW (object); - EShellWindowPrivate *priv = self->priv; + EShell *shell; + EShellView *shell_view; + EShellBackend *shell_backend; + GHashTable *loaded_views; - priv->destroyed = TRUE; + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + g_return_val_if_fail (view_name != NULL, NULL); - if (priv->shell.eshell != NULL) { - g_object_remove_weak_pointer (G_OBJECT (priv->shell.eshell), &priv->shell.pointer); - priv->shell.eshell = NULL; - } + loaded_views = shell_window->priv->loaded_views; + shell_view = g_hash_table_lookup (loaded_views, view_name); - if (priv->ui_component != NULL) { - bonobo_object_unref (BONOBO_OBJECT (priv->ui_component)); - priv->ui_component = NULL; - } + if (shell_view != NULL) + return shell_view; - if (priv->store_window_gsizeimer) { - g_source_remove (priv->store_window_gsizeimer); - self->priv->store_window_gsizeimer = 0; + shell = e_shell_window_get_shell (shell_window); + shell_backend = e_shell_get_backend_by_name (shell, view_name); - /* There was a timer. Let us store the settings.*/ - store_window_size (GTK_WIDGET (self)); + if (shell_backend == NULL) { + g_critical ("Unknown shell view name: %s", view_name); + return NULL; } - (* G_OBJECT_CLASS (e_shell_window_parent_class)->dispose) (object); + return shell_window_new_view (shell_backend, shell_window); } -static void -impl_finalize (GObject *object) +/** + * e_shell_window_get_shell_view_action: + * @shell_window: an #EShellWindow + * @view_name: name of a shell view + * + * Returns the switcher action for @view_name. + * + * An #EShellWindow creates a #GtkRadioAction for each registered subclass + * of #EShellView. This action gets passed to the #EShellSwitcher, which + * displays a button that proxies the action. When the #EShellView named + * @view_name is active, the action's icon becomes the @shell_window icon. + * + * Returns: the switcher action for the #EShellView named @view_name, + * or %NULL if no such shell view exists + **/ +GtkAction * +e_shell_window_get_shell_view_action (EShellWindow *shell_window, + const gchar *view_name) { - EShellWindowPrivate *priv = E_SHELL_WINDOW (object)->priv; - - g_slist_foreach (priv->component_views, (GFunc) component_view_free, NULL); - g_slist_free (priv->component_views); - - g_object_unref(priv->menu); + GtkAction *action; + gchar *action_name; - g_free (priv); + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + g_return_val_if_fail (view_name != NULL, NULL); - (* G_OBJECT_CLASS (e_shell_window_parent_class)->finalize) (object); -} + action_name = g_strdup_printf (SWITCHER_FORMAT, view_name); + action = e_shell_window_get_action (shell_window, action_name); + g_free (action_name); -/* GtkWidget methods */ -static void -e_shell_window_remove_regsizeimer (EShellWindow* self) -{ - if (self->priv->store_window_gsizeimer) { - g_source_remove (self->priv->store_window_gsizeimer); - self->priv->store_window_gsizeimer = 0; - } + return action; } -static gboolean -impl_window_state (GtkWidget *widget, GdkEventWindowState* ev) +/** + * e_shell_window_get_ui_manager: + * @shell_window: an #EShellWindow + * + * Returns @shell_window<!-- -->'s user interface manager, which + * manages the window's menus and toolbars via #GtkAction<!-- -->s. + * This is the mechanism by which shell views and plugins can extend + * Evolution's menus and toolbars. + * + * Returns: the #GtkUIManager for @shell_window + **/ +GtkUIManager * +e_shell_window_get_ui_manager (EShellWindow *shell_window) { - gboolean retval = FALSE; - - /* store only if the window state really changed */ - if ((ev->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0) { - GConfClient* client = gconf_client_get_default (); - gconf_client_set_bool (client, "/apps/evolution/shell/view_defaults/maximized", - (ev->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0, NULL); - g_object_unref(client); - } - - if ((ev->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0) { - e_shell_window_remove_regsizeimer (E_SHELL_WINDOW (widget)); - } - - if (GTK_WIDGET_CLASS (e_shell_window_parent_class)->window_state_event) { - retval |= GTK_WIDGET_CLASS (e_shell_window_parent_class)->window_state_event (widget, ev); - } - - return retval; -} + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); -static gboolean -store_window_size (GtkWidget* widget) -{ - GConfClient* client = gconf_client_get_default (); - gconf_client_set_int (client, "/apps/evolution/shell/view_defaults/width", - widget->allocation.width, NULL); - gconf_client_set_int (client, "/apps/evolution/shell/view_defaults/height", - widget->allocation.height, NULL); - g_object_unref(client); - - E_SHELL_WINDOW (widget)->priv->store_window_gsizeimer = 0; - return FALSE; /* remove this timeout */ + return shell_window->priv->ui_manager; } -static void -impl_size_alloc (GtkWidget* widget, GtkAllocation* alloc) +/** + * e_shell_window_get_action: + * @shell_window: an #EShellWindow + * @action_name: the name of an action + * + * Returns the #GtkAction named @action_name in @shell_window<!-- -->'s + * user interface manager, or %NULL if no such action exists. + * + * Returns: the #GtkAction named @action_name + **/ +GtkAction * +e_shell_window_get_action (EShellWindow *shell_window, + const gchar *action_name) { - EShellWindow* self = E_SHELL_WINDOW (widget); - e_shell_window_remove_regsizeimer(self); - - if (GTK_WIDGET_REALIZED(widget) && !(gdk_window_get_state(widget->window) & GDK_WINDOW_STATE_MAXIMIZED)) { - /* update the size storage timer */ - self->priv->store_window_gsizeimer = g_timeout_add_seconds (1, (GSourceFunc)store_window_size, self); - } + GtkUIManager *ui_manager; - if (GTK_WIDGET_CLASS (e_shell_window_parent_class)->size_allocate) { - GTK_WIDGET_CLASS (e_shell_window_parent_class)->size_allocate (widget, alloc); - } -} + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + g_return_val_if_fail (action_name != NULL, NULL); -/* Initialization. */ + ui_manager = e_shell_window_get_ui_manager (shell_window); -static void -e_shell_window_class_init (EShellWindowClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; - - widget_class->window_state_event = impl_window_state; - widget_class->size_allocate = impl_size_alloc; - - signals[COMPONENT_CHANGED] = g_signal_new ("component_changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EShellWindowClass, component_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + return e_lookup_action (ui_manager, action_name); } -static void -e_shell_window_init (EShellWindow *shell_window) +/** + * e_shell_window_get_action_group: + * @shell_window: an #EShellWindow + * @group_name: the name of an action group + * + * Returns the #GtkActionGroup named @group_name in + * @shell_window<!-- -->'s user interface manager, or %NULL if no + * such action group exists. + * + * Returns: the #GtkActionGroup named @group_name + **/ +GtkActionGroup * +e_shell_window_get_action_group (EShellWindow *shell_window, + const gchar *group_name) { - EShellWindowPrivate *priv = g_new0 (EShellWindowPrivate, 1); + GtkUIManager *ui_manager; - priv->shell_view = e_shell_view_new(shell_window); - priv->destroyed = FALSE; + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + g_return_val_if_fail (group_name != NULL, NULL); - shell_window->priv = priv; - - /** @HookPoint: Shell Main Menu - * @Id: org.gnome.evolution.shell - * @Type: ESMenu - * @Target: ESMenuTargetShell - * - * This hook point is used to add bonobo menu's to the main - * evolution shell window, used for global commands not - * requiring a specific component. - */ - priv->menu = es_menu_new("org.gnome.evolution.shell"); + ui_manager = e_shell_window_get_ui_manager (shell_window); + return e_lookup_action_group (ui_manager, group_name); } -/* Instantiation. */ - +/** + * e_shell_window_get_managed_widget: + * @shell_window: an #EShellWindow + * @widget_path: path in the UI definintion + * + * Looks up a widget in @shell_window<!-- -->'s user interface manager by + * following a path. See gtk_ui_manager_get_widget() for more information + * about paths. + * + * Returns: the widget found by following the path, or %NULL if no widget + * was found + **/ GtkWidget * -e_shell_window_new (EShell *shell, - const gchar *component_id) +e_shell_window_get_managed_widget (EShellWindow *shell_window, + const gchar *widget_path) { - EShellWindow *window = g_object_new (e_shell_window_get_type (), NULL); - EShellWindowPrivate *priv = window->priv; - GConfClient *gconf_client = gconf_client_get_default (); - BonoboUIContainer *ui_container; - gchar *default_component_id = NULL; - gchar *xmlfile; - gint width, height; - - if (bonobo_window_construct (BONOBO_WINDOW (window), - bonobo_ui_container_new (), - "evolution", "Evolution") == NULL) { - g_object_unref (window); - g_object_unref (gconf_client); - return NULL; - } - - window->priv->shell.eshell = shell; - g_object_add_weak_pointer (G_OBJECT (shell), &window->priv->shell.pointer); - - /* FIXME TODO: Add system_exception signal handling and all the other - stuff from e_shell_view_construct(). */ - - ui_container = bonobo_window_get_ui_container (BONOBO_WINDOW (window)); - - priv->ui_component = bonobo_ui_component_new ("evolution"); - bonobo_ui_component_set_container (priv->ui_component, - bonobo_object_corba_objref (BONOBO_OBJECT (ui_container)), - NULL); - - xmlfile = g_build_filename (EVOLUTION_UIDIR, "evolution.xml", NULL); - bonobo_ui_util_set_ui (priv->ui_component, - PREFIX, - xmlfile, - "evolution", NULL); - g_free (xmlfile); - - e_shell_window_commands_setup (window); - e_menu_activate((EMenu *)priv->menu, priv->ui_component, TRUE); - - setup_widgets (window); - - if (gconf_client_get_bool (gconf_client,"/apps/evolution/shell/view_defaults/sidebar_visible",NULL)) - gtk_widget_show (priv->sidebar); - else - gtk_widget_hide (priv->sidebar); - - update_send_receive_sensitivity (window); - g_signal_connect_object (shell, "line_status_changed", G_CALLBACK (shell_line_status_changed_callback), window, 0); - - gtk_window_set_default_size (GTK_WINDOW (window), 640, 480); + GtkUIManager *ui_manager; + GtkWidget *widget; - if (component_id == NULL) { - component_id = default_component_id = - gconf_client_get_string (gconf_client, - "/apps/evolution/shell/view_defaults/component_id", - NULL); - if (component_id == NULL) - component_id = "mail"; - } + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); + g_return_val_if_fail (widget_path != NULL, NULL); - e_shell_window_switch_to_component (window, component_id); - g_free(default_component_id); - g_object_unref (gconf_client); + ui_manager = e_shell_window_get_ui_manager (shell_window); + widget = gtk_ui_manager_get_widget (ui_manager, widget_path); - width = gconf_client_get_int (gconf_client, "/apps/evolution/shell/view_defaults/width", NULL); - height = gconf_client_get_int (gconf_client, "/apps/evolution/shell/view_defaults/height", NULL); - gtk_window_set_default_size (GTK_WINDOW (window), (width >= 0) ? width : 0, - (height >= 0) ? height : 0); - if (gconf_client_get_bool (gconf_client, "/apps/evolution/shell/view_defaults/maximized", NULL)) { - gtk_window_maximize (GTK_WINDOW (window)); - } + g_return_val_if_fail (widget != NULL, NULL); - g_object_unref (gconf_client); - return GTK_WIDGET (window); + return widget; } -void -e_shell_window_switch_to_component (EShellWindow *window, const gchar *component_id) +/** + * e_shell_window_get_active_view: + * @shell_window: an #EShellWindow + * + * Returns the name of the active #EShellView. + * + * Returns: the name of the active view + **/ +const gchar * +e_shell_window_get_active_view (EShellWindow *shell_window) { - EShellWindowPrivate *priv = window->priv; - ComponentView *view = NULL; - GSList *p; - - g_return_if_fail (E_IS_SHELL_WINDOW (window)); - g_return_if_fail (component_id != NULL); - - for (p = priv->component_views; p != NULL; p = p->next) { - ComponentView *this_view = p->data; - - if (strcmp (this_view->component_id, component_id) == 0 - || (this_view->component_alias != NULL - && strcmp (this_view->component_alias, component_id) == 0)) - { - view = p->data; - break; - } - } - - if (view == NULL) { - g_warning ("Unknown component %s", component_id); - return; - } + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); - e_sidebar_select_button (E_SIDEBAR (priv->sidebar), view->button_id); + return shell_window->priv->active_view; } -const gchar * -e_shell_window_peek_current_component_id (EShellWindow *window) +/** + * e_shell_window_set_active_view: + * @shell_window: an #EShellWindow + * @view_name: the name of the shell view to switch to + * + * Switches @shell_window to the #EShellView named @view_name, causing + * the entire content of @shell_window to change. This is typically + * called as a result of the user clicking one of the switcher buttons. + * + * The name of the newly activated shell view is also written to GConf key + * <filename>/apps/evolution/shell/view_defaults/component_id</filename>. + * This makes the active shell view persistent across Evolution sessions. + * It also causes new shell windows created within the current Evolution + * session to open to the most recently selected shell view. + **/ +void +e_shell_window_set_active_view (EShellWindow *shell_window, + const gchar *view_name) { - g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL); + GtkAction *action; + EShellView *shell_view; - if (window->priv->current_view == NULL) - return NULL; + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + g_return_if_fail (view_name != NULL); - return window->priv->current_view->component_id; + shell_view = e_shell_window_get_shell_view (shell_window, view_name); + g_return_if_fail (shell_view != NULL); + + action = e_shell_view_get_action (shell_view); + gtk_action_activate (action); } -EShell * -e_shell_window_peek_shell (EShellWindow *window) +/** + * e_shell_window_get_safe_mode: + * @shell_window: an #EShellWindow + * + * Returns %TRUE if @shell_window is in "safe mode". + * + * It's up to the various #EShellView<!-- -->'s to define exactly + * what "safe mode" means. The @shell_window simply manages the + * "safe mode" state. + * + * Returns: %TRUE if @shell_window is in "safe mode" + **/ +gboolean +e_shell_window_get_safe_mode (EShellWindow *shell_window) { - g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL); + g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - return window->priv->shell.eshell; + return shell_window->priv->safe_mode; } -BonoboUIComponent * -e_shell_window_peek_bonobo_ui_component (EShellWindow *window) +/** + * e_shell_window_set_safe_mode: + * @shell_window: an #EShellWindow + * @safe_mode: whether to put @shell_window into "safe mode" + * + * If %TRUE, puts @shell_window into "safe mode". + * + * It's up to the various #EShellView<!-- -->'s to define exactly + * what "safe mode" means. The @shell_window simply manages the + * "safe mode" state. + **/ +void +e_shell_window_set_safe_mode (EShellWindow *shell_window, + gboolean safe_mode) { - g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL); + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - return window->priv->ui_component; + shell_window->priv->safe_mode = safe_mode; + + g_object_notify (G_OBJECT (shell_window), "safe-mode"); } -ESidebar * -e_shell_window_peek_sidebar (EShellWindow *window) +/** + * e_shell_window_add_action_group: + * @shell_window: an #EShellWindow + * @group_name: the name of the new action group + * + * Creates a new #GtkActionGroup and adds it to @shell_window<!-- -->'s + * user interface manager. This also takes care of details like setting + * the translation domain. + **/ +void +e_shell_window_add_action_group (EShellWindow *shell_window, + const gchar *group_name) { - g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL); + GtkActionGroup *action_group; + GtkUIManager *ui_manager; + const gchar *domain; - return E_SIDEBAR (window->priv->sidebar); -} + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + g_return_if_fail (group_name != NULL); -GtkWidget * -e_shell_window_peek_statusbar (EShellWindow *window) -{ - return window->priv->status_bar; + ui_manager = e_shell_window_get_ui_manager (shell_window); + domain = GETTEXT_PACKAGE; + + action_group = gtk_action_group_new (group_name); + gtk_action_group_set_translation_domain (action_group, domain); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + g_object_unref (action_group); } +/** + * e_shell_window_register_new_item_actions: + * @shell_window: an #EShellWindow + * @backend_name: name of an #EShellBackend + * @entries: an array of #GtkActionEntry<!-- -->s + * @n_entries: number of elements in the array + * + * Registers a list of #GtkAction<!-- -->s to appear in + * @shell_window<!-- -->'s "New" menu and toolbar button. This + * function should be called from an #EShell<!-- -->'s + * #EShell::window-created signal handler. The #EShellBackend calling + * this function should pass its own name for the @backend_name argument + * (i.e. the <structfield>name</structfield> field from its own + * #EShellBackendInfo). + * + * The registered #GtkAction<!-- -->s should be for creating individual + * items such as an email message or a calendar appointment. The action + * labels should be marked for translation with the "New" context using + * the NC_() macro. + **/ void -e_shell_window_save_defaults (EShellWindow *window) -{ - GConfClient *client = gconf_client_get_default (); - gchar *prop; - const gchar *style; - gboolean visible; - - gconf_client_set_int (client, "/apps/evolution/shell/view_defaults/folder_bar/width", - gtk_paned_get_position (GTK_PANED (window->priv->paned)), NULL); - - /* The button styles */ - if ((style = gconf_enum_to_string (button_styles, e_sidebar_get_mode (E_SIDEBAR (window->priv->sidebar))))) { - gconf_client_set_string (client, - "/apps/evolution/shell/view_defaults/buttons_style", - style, NULL); - } +e_shell_window_register_new_item_actions (EShellWindow *shell_window, + const gchar *backend_name, + GtkActionEntry *entries, + guint n_entries) +{ + GtkActionGroup *action_group; + GtkAccelGroup *accel_group; + GtkUIManager *ui_manager; + guint ii; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + g_return_if_fail (backend_name != NULL); + g_return_if_fail (entries != NULL); + + action_group = ACTION_GROUP (NEW_ITEM); + ui_manager = e_shell_window_get_ui_manager (shell_window); + accel_group = gtk_ui_manager_get_accel_group (ui_manager); + backend_name = g_intern_string (backend_name); + + /* XXX The action label translations are retrieved from the + * message context "New", but gtk_action_group_add_actions() + * does not support message contexts. So we have to fetch + * the label translations ourselves before adding them to + * the action group. + * + * gtk_action_group_set_translate_func() does not help here + * because the action tooltips do not use a message context + * (though I suppose they could). */ + for (ii = 0; ii < n_entries; ii++) + entries[ii].label = g_dpgettext2 ( + GETTEXT_PACKAGE, "New", entries[ii].label); - /* Button hiding setting */ - prop = bonobo_ui_component_get_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewButtonsHide", - "state", - NULL); - if (prop) { - visible = prop[0] == '0'; - gconf_client_set_bool (client, - "/apps/evolution/shell/view_defaults/buttons_visible", - visible, - NULL); - g_free (prop); - } + gtk_action_group_add_actions ( + action_group, entries, n_entries, shell_window); - /* Toolbar visibility setting */ - prop = bonobo_ui_component_get_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewToolbar", - "state", - NULL); - if (prop) { - visible = prop[0] == '1'; - gconf_client_set_bool (client, - "/apps/evolution/shell/view_defaults/toolbar_visible", - visible, - NULL); - g_free (prop); - } + /* Tag each action with the name of the shell backend that + * registered it. This is used to help sort actions in the + * "New" menu. */ - /* SideBar visibility setting */ - prop = bonobo_ui_component_get_prop (e_shell_window_peek_bonobo_ui_component (window), - "/commands/ViewSideBar", - "state", - NULL); - if (prop) { - visible = prop[0] == '1'; - gconf_client_set_bool (client, - "/apps/evolution/shell/view_defaults/sidebar_visible", - visible, - NULL); - g_free (prop); - } + for (ii = 0; ii < n_entries; ii++) { + const gchar *action_name; + GtkAction *action; - g_object_unref (client); -} + action_name = entries[ii].name; -void -e_shell_window_show_settings (EShellWindow *window) -{ - g_return_if_fail (E_IS_SHELL_WINDOW (window)); + action = gtk_action_group_get_action ( + action_group, action_name); - e_shell_show_settings (window->priv->shell.eshell, window->priv->current_view ? window->priv->current_view->component_alias : NULL, window); -} + gtk_action_set_accel_group (action, accel_group); -void -e_shell_window_set_title(EShellWindow *window, const gchar *component_id, const gchar *title) -{ - EShellWindowPrivate *priv = window->priv; - ComponentView *view = NULL; - GSList *p; - - if (priv->destroyed) - return; - - for (p = priv->component_views; p != NULL; p = p->next) { - ComponentView *this_view = p->data; - - if (strcmp (this_view->component_id, component_id) == 0 - || (this_view->component_alias != NULL - && strcmp (this_view->component_alias, component_id) == 0)) { - view = p->data; - break; - } - } + g_object_set_data ( + G_OBJECT (action), + "backend-name", (gpointer) backend_name); - if (view) { - g_free(view->title); - view->title = g_strdup(title); - if (view->title && view == priv->current_view) - gtk_window_set_title((GtkWindow *)window, title); + /* The first action becomes the first item in the "New" + * menu, and consequently its icon is shown in the "New" + * button when the shell backend's view is active. This + * is all sorted out in shell_window_extract_actions(). + * Note, the data value just needs to be non-zero. */ + if (ii == 0) + g_object_set_data ( + G_OBJECT (action), + "primary", GINT_TO_POINTER (TRUE)); } + + e_shell_window_update_new_menu (shell_window); } /** - * e_shell_window_change_component_button_icon - * Changes icon of components button at sidebar. For more info how this behaves see - * info at @ref e_sidebar_change_button_icon. - * @param window EShellWindow instance. - * @param component_id ID of the component. - * @param icon Icon buffer. + * e_shell_window_register_new_source_actions: + * @shell_window: an #EShellWindow + * @backend_name: name of an #EShellBackend + * @entries: an array of #GtkActionEntry<!-- -->s + * @n_entries: number of elements in the array + * + * Registers a list of #GtkAction<!-- -->s to appear in + * @shell_window<!-- -->'s "New" menu and toolbar button. This + * function should be called from an #EShell<!-- -->'s + * #EShell::window-created signal handler. The #EShellBackend calling + * this function should pass its own name for the @backend_name argument + * (i.e. the <structfield>name</structfield> field from its own + * #EShellBackendInfo). + * + * The registered #GtkAction<!-- -->s should be for creating item + * containers such as an email folder or a calendar. The action labels + * should be marked for translation with the "New" context using the + * NC_() macro. **/ void -e_shell_window_change_component_button_icon (EShellWindow *window, const gchar *component_id, const gchar *icon_name) -{ - EShellWindowPrivate *priv; - GSList *p; +e_shell_window_register_new_source_actions (EShellWindow *shell_window, + const gchar *backend_name, + GtkActionEntry *entries, + guint n_entries) +{ + GtkActionGroup *action_group; + GtkAccelGroup *accel_group; + GtkUIManager *ui_manager; + guint ii; + + g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); + g_return_if_fail (backend_name != NULL); + g_return_if_fail (entries != NULL); + + action_group = ACTION_GROUP (NEW_SOURCE); + ui_manager = e_shell_window_get_ui_manager (shell_window); + accel_group = gtk_ui_manager_get_accel_group (ui_manager); + backend_name = g_intern_string (backend_name); + + /* XXX The action label translations are retrieved from the + * message context "New", but gtk_action_group_add_actions() + * does not support message contexts. So we have to fetch + * the label translations ourselves before adding them to + * the action group. + * + * gtk_action_group_set_translate_func() does not help here + * because the action tooltips do not use a message context + * (though I suppose they could). */ + for (ii = 0; ii < n_entries; ii++) + entries[ii].label = g_dpgettext2 ( + GETTEXT_PACKAGE, "New", entries[ii].label); + + gtk_action_group_add_actions ( + action_group, entries, n_entries, shell_window); - g_return_if_fail (window != NULL); - g_return_if_fail (component_id != NULL); + /* Tag each action with the name of the shell backend that + * registered it. This is used to help sort actions in the + * "New" menu. */ - priv = window->priv; + for (ii = 0; ii < n_entries; ii++) { + const gchar *action_name; + GtkAction *action; - if (priv->destroyed) - return; + action_name = entries[ii].name; - for (p = priv->component_views; p != NULL; p = p->next) { - ComponentView *this_view = p->data; + action = gtk_action_group_get_action ( + action_group, action_name); - if (strcmp (this_view->component_id, component_id) == 0 - || (this_view->component_alias != NULL - && strcmp (this_view->component_alias, component_id) == 0)) { - e_sidebar_change_button_icon (E_SIDEBAR (priv->sidebar), icon_name, this_view->button_id); - break; - } + gtk_action_set_accel_group (action, accel_group); + + g_object_set_data ( + G_OBJECT (action), + "backend-name", (gpointer) backend_name); } + + e_shell_window_update_new_menu (shell_window); } diff --git a/shell/e-shell-window.h b/shell/e-shell-window.h index 7c404fadc8..b867490afb 100644 --- a/shell/e-shell-window.h +++ b/shell/e-shell-window.h @@ -1,4 +1,5 @@ /* + * e-shell-window.h * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -14,63 +15,104 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef _E_SHELL_WINDOW_H_ -#define _E_SHELL_WINDOW_H_ - -#include <bonobo/bonobo-window.h> -#include <bonobo/bonobo-ui-component.h> -#include "e-sidebar.h" - -#define E_TYPE_SHELL_WINDOW (e_shell_window_get_type ()) -#define E_SHELL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SHELL_WINDOW, EShellWindow)) -#define E_SHELL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL_WINDOW, EShellWindowClass)) -#define E_IS_SHELL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SHELL_WINDOW)) -#define E_IS_SHELL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL_WINDOW)) - -typedef struct _EShellWindow EShellWindow; +/** + * SECTION: e-shell-window + * @short_description: the main window + * @include: shell/e-shell-window.h + **/ + +#ifndef E_SHELL_WINDOW_H +#define E_SHELL_WINDOW_H + +#include <shell/e-shell.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_WINDOW \ + (e_shell_window_get_type ()) +#define E_SHELL_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_WINDOW, EShellWindow)) +#define E_SHELL_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_WINDOW, EShellWindowClass)) +#define E_IS_SHELL_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_WINDOW)) +#define E_IS_SHELL_WINDOW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_WINDOW)) +#define E_SHELL_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_WINDOW, EShellWindowClass)) + +G_BEGIN_DECLS + +/* Avoid including <e-shell-view.h>, because it includes us! */ +struct _EShellView; + +typedef struct _EShellWindow EShellWindow; +typedef struct _EShellWindowClass EShellWindowClass; typedef struct _EShellWindowPrivate EShellWindowPrivate; -typedef struct _EShellWindowClass EShellWindowClass; +/** + * EShellWindow: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ struct _EShellWindow { - BonoboWindow parent; - + GtkWindow parent; EShellWindowPrivate *priv; }; struct _EShellWindowClass { - BonoboWindowClass parent_class; - - void (* component_changed) (EShellWindow *window); + GtkWindowClass parent_class; }; -#include "e-shell.h" - -GType e_shell_window_get_type (void); - -GtkWidget *e_shell_window_new (EShell *shell, - const gchar *component_id); - -void e_shell_window_switch_to_component (EShellWindow *shell, - const gchar *component_id); -const gchar *e_shell_window_peek_current_component_id (EShellWindow *shell); - -EShell *e_shell_window_peek_shell (EShellWindow *window); -BonoboUIComponent *e_shell_window_peek_bonobo_ui_component (EShellWindow *window); -ESidebar *e_shell_window_peek_sidebar (EShellWindow *window); -GtkWidget *e_shell_window_peek_statusbar (EShellWindow *window); - -void e_shell_window_set_title(EShellWindow *window, const gchar *component_id, const gchar *title); - -void e_shell_window_save_defaults (EShellWindow *window); -void e_shell_window_show_settings (EShellWindow *window); - -void e_shell_window_change_component_button_icon (EShellWindow *window, const gchar *component_id, const gchar *icon_name); - -#endif /* _E_SHELL_WINDOW_H_ */ +GType e_shell_window_get_type (void); +GtkWidget * e_shell_window_new (EShell *shell, + gboolean safe_mode); +EShell * e_shell_window_get_shell (EShellWindow *shell_window); +struct _EShellView * + e_shell_window_get_shell_view (EShellWindow *shell_window, + const gchar *view_name); +GtkAction * e_shell_window_get_shell_view_action + (EShellWindow *shell_window, + const gchar *view_name); +GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *shell_window); +GtkAction * e_shell_window_get_action (EShellWindow *shell_window, + const gchar *action_name); +GtkActionGroup *e_shell_window_get_action_group (EShellWindow *shell_window, + const gchar *group_name); +GtkWidget * e_shell_window_get_managed_widget + (EShellWindow *shell_window, + const gchar *widget_path); +const gchar * e_shell_window_get_active_view (EShellWindow *shell_window); +void e_shell_window_set_active_view (EShellWindow *shell_window, + const gchar *view_name); +gboolean e_shell_window_get_safe_mode (EShellWindow *shell_window); +void e_shell_window_set_safe_mode (EShellWindow *shell_window, + gboolean safe_mode); +void e_shell_window_add_action_group (EShellWindow *shell_window, + const gchar *group_name); + +/* These should be called from the shell backend's window_created() handler. */ + +void e_shell_window_register_new_item_actions + (EShellWindow *shell_window, + const gchar *backend_name, + GtkActionEntry *entries, + guint n_entries); +void e_shell_window_register_new_source_actions + (EShellWindow *shell_window, + const gchar *backend_name, + GtkActionEntry *entries, + guint n_entries); + +G_END_DECLS + +#endif /* E_SHELL_WINDOW_H */ diff --git a/shell/e-shell.c b/shell/e-shell.c index e4224f3207..4dd72e3747 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -1,4 +1,6 @@ /* + * e-shell.c + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -13,1411 +15,1533 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#include <config.h> - -#include <string.h> -#include <unistd.h> -#include <sys/types.h> - -#include <gtk/gtk.h> -#include <glib/gstdio.h> - -#ifdef GDK_WINDOWING_X11 -#include <gdk/gdkprivate.h> -#include <gdk/gdkx.h> -#include <X11/Xatom.h> -#include <X11/Xlib.h> -#elif defined (GDK_WINDOWING_WIN32) -/* gdkwin32.h includes <windows.h> which stomps over the namespace */ -#undef DATADIR -#define interface windows_interface -#include <gdk/gdkwin32.h> -#undef interface -#endif +#include "e-shell.h" #include <glib/gi18n.h> - -#include <gconf/gconf-client.h> - -#include <bonobo-activation/bonobo-activation.h> -#include <bonobo/bonobo-exception.h> -#include <bonobo/bonobo-moniker-util.h> - -#include <libedataserver/e-xml-utils.h> #include <libedataserverui/e-passwords.h> -#include "e-util/e-bconf-map.h" -#include "e-util/e-dialog-utils.h" -#include "e-util/e-error.h" -#include "e-util/e-fsutils.h" #include "e-util/e-util.h" +#include "e-util/e-module.h" +#include "smclient/eggsmclient.h" +#include "widgets/misc/e-preferences-window.h" -#include "Evolution.h" -#include "e-shell-constants.h" -#include "e-shell-settings-dialog.h" -#include "e-shell.h" -#include "e-shell-view.h" -#include "es-event.h" -#include "evolution-listener.h" -#include "evolution-shell-component-utils.h" - -static void set_line_status_complete(EvolutionListener *el, gpointer data); +#include "e-shell-backend.h" +#include "e-shell-migrate.h" +#include "e-shell-window.h" -#define PARENT_TYPE bonobo_object_get_type () -static BonoboObjectClass *parent_class = NULL; -static gboolean session_started = FALSE; +#define E_SHELL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL, EShellPrivate)) struct _EShellPrivate { - /* IID for registering the object on OAF. */ - gchar *iid; + GList *watched_windows; + EShellSettings *settings; + GConfClient *gconf_client; + GtkWidget *preferences_window; - GList *windows; + /* Shell Backends */ + GList *loaded_backends; + GHashTable *backends_by_name; + GHashTable *backends_by_scheme; - /* EUriSchemaRegistry *uri_schema_registry; FIXME */ - EComponentRegistry *component_registry; + gpointer preparing_for_line_change; /* weak pointer */ + gpointer preparing_for_quit; /* weak pointer */ - /* Names for the types of the folders that have maybe crashed. */ - /* FIXME TODO */ - GList *crash_type_names; /* gchar * */ + guint auto_reconnect : 1; + guint network_available : 1; + guint online : 1; + guint quit_cancelled : 1; + guint safe_mode : 1; +}; - /* Line status and controllers */ - EShellLineStatus line_status; - gint line_status_pending; - EShellLineStatus line_status_working; - EvolutionListener *line_status_listener; +enum { + PROP_0, + PROP_NETWORK_AVAILABLE, + PROP_ONLINE, + PROP_SHELL_SETTINGS +}; - /* Settings Dialog */ - union { - GtkWidget *widget; - gpointer pointer; - } settings_dialog; +enum { + EVENT, + HANDLE_URI, + PREPARE_FOR_OFFLINE, + PREPARE_FOR_ONLINE, + PREPARE_FOR_QUIT, + QUIT_REQUESTED, + SEND_RECEIVE, + WINDOW_CREATED, + WINDOW_DESTROYED, + LAST_SIGNAL +}; - /* If we're quitting and things are still busy, a timeout handler */ - guint quit_timeout; +enum { + DEBUG_KEY_SETTINGS = 1 << 0 +}; - /* Whether the shell is succesfully initialized. This is needed during - the start-up sequence, to avoid CORBA calls to do make wrong things - to happen while the shell is initializing. */ - guint is_initialized : 1; +static GDebugKey debug_keys[] = { + { "settings", DEBUG_KEY_SETTINGS } +}; - /* Wether the shell is working in "interactive" mode or not. - (Currently, it's interactive IIF there is at least one active - view.) */ - guint is_interactive : 1; +EShell *default_shell = NULL; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; - /* Whether quit has been requested, and the shell is now waiting for - permissions from all the components to quit. */ - guint preparing_to_quit : 1; +#if NM_SUPPORT +gboolean e_shell_dbus_initialize (EShell *shell); +#endif - /* Whether we are recovering from a crash in the previous session. */ - guint crash_recovery : 1; -}; +static void +shell_parse_debug_string (EShell *shell) +{ + guint flags; -/* Signals. */ + flags = g_parse_debug_string ( + g_getenv ("EVOLUTION_DEBUG"), + debug_keys, G_N_ELEMENTS (debug_keys)); -enum { - NO_WINDOWS_LEFT, - LINE_STATUS_CHANGED, - NEW_WINDOW_CREATED, - LAST_SIGNAL -}; + if (flags & DEBUG_KEY_SETTINGS) + e_shell_settings_enable_debug (shell->priv->settings); +} -static guint signals[LAST_SIGNAL] = { 0 }; +static void +shell_notify_online_cb (EShell *shell) +{ + gboolean online; -/* Utility functions. */ + online = e_shell_get_online (shell); + e_passwords_set_online (online); +} static gboolean -get_config_start_offline (void) +shell_window_delete_event_cb (EShell *shell, + GtkWindow *window) { - GConfClient *client; - gboolean value; + /* If other windows are open we can safely close this one. */ + if (g_list_length (shell->priv->watched_windows) > 1) + return FALSE; - client = gconf_client_get_default (); + /* Otherwise we initiate application quit. */ + e_shell_quit (shell); + + return TRUE; +} - value = gconf_client_get_bool (client, "/apps/evolution/shell/start_offline", NULL); +static gboolean +shell_window_focus_in_event_cb (EShell *shell, + GdkEventFocus *event, + GtkWindow *window) +{ + GList *list, *link; + + /* Keep the watched windows list sorted by most recently focused, + * so the first item in the list should always be the currently + * focused window. */ + + list = shell->priv->watched_windows; + link = g_list_find (list, window); + g_return_val_if_fail (link != NULL, FALSE); + + if (link != list) { + list = g_list_remove_link (list, link); + list = g_list_concat (link, list); + } - g_object_unref (client); + shell->priv->watched_windows = list; - return value; + return FALSE; } -/* Interactivity handling. */ +static void +shell_window_weak_notify_cb (EShell *shell, + GObject *where_the_object_was) +{ + GList *list; + + list = shell->priv->watched_windows; + list = g_list_remove (list, where_the_object_was); + shell->priv->watched_windows = list; + + g_signal_emit (shell, signals[WINDOW_DESTROYED], 0); +} static void -set_interactive (EShell *shell, - gboolean interactive) +shell_ready_for_offline (EShell *shell, + EActivity *activity, + gboolean is_last_ref) { - GSList *component_list; - GSList *p; - GList *first_element; - gint num_windows; - GtkWidget *view; + if (!is_last_ref) + return; - g_return_if_fail (E_IS_SHELL (shell)); + /* Increment the reference count so we can safely emit + * a signal without triggering the toggle reference. */ + g_object_ref (activity); - shell->priv->is_interactive = interactive; + e_activity_complete (activity); - num_windows = g_list_length (shell->priv->windows); + g_object_remove_toggle_ref ( + G_OBJECT (activity), (GToggleNotify) + shell_ready_for_offline, shell); - /* We want to send the "interactive" message only when the first - window is created */ - if (num_windows != 1) - return; + /* Finalize the activity. */ + g_object_unref (activity); - first_element = g_list_first (shell->priv->windows); - view = GTK_WIDGET (first_element->data); + shell->priv->online = FALSE; + g_object_notify (G_OBJECT (shell), "online"); - component_list = e_component_registry_peek_list (shell->priv->component_registry); + g_message ("Offline preparations complete."); +} - for (p = component_list; p != NULL; p = p->next) { - EComponentInfo *info = p->data; - CORBA_Environment ev; +static void +shell_prepare_for_offline (EShell *shell) +{ + /* Are preparations already in progress? */ + if (shell->priv->preparing_for_line_change != NULL) + return; - CORBA_exception_init (&ev); + g_message ("Preparing for offline mode..."); -#ifdef GDK_WINDOWING_X11 - GNOME_Evolution_Component_interactive (info->iface, interactive,GPOINTER_TO_INT (GDK_WINDOW_XWINDOW (view->window)), &ev); -#elif defined (GDK_WINDOWING_WIN32) - GNOME_Evolution_Component_interactive (info->iface, interactive,GPOINTER_TO_INT (GDK_WINDOW_HWND (view->window)), &ev); -#else -#error Port this to your windowing system -#endif + shell->priv->preparing_for_line_change = + e_activity_new (_("Preparing to go offline...")); - /* Ignore errors, the components can decide to not implement - this interface. */ + g_object_add_toggle_ref ( + G_OBJECT (shell->priv->preparing_for_line_change), + (GToggleNotify) shell_ready_for_offline, shell); - CORBA_exception_free (&ev); - } -} + g_object_add_weak_pointer ( + G_OBJECT (shell->priv->preparing_for_line_change), + &shell->priv->preparing_for_line_change); -/* CORBA interface implementation. */ + g_signal_emit ( + shell, signals[PREPARE_FOR_OFFLINE], 0, + shell->priv->preparing_for_line_change); -static gboolean -raise_exception_if_not_ready (PortableServer_Servant servant, - CORBA_Environment *ev) + g_object_unref (shell->priv->preparing_for_line_change); +} + +static void +shell_ready_for_online (EShell *shell, + EActivity *activity, + gboolean is_last_ref) { - EShell *shell; + if (!is_last_ref) + return; - shell = E_SHELL (bonobo_object_from_servant (servant)); + /* Increment the reference count so we can safely emit + * a signal without triggering the toggle reference. */ + g_object_ref (activity); - if (! shell->priv->is_initialized) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Shell_NotReady, NULL); - return TRUE; - } + e_activity_complete (activity); - return FALSE; + g_object_remove_toggle_ref ( + G_OBJECT (activity), (GToggleNotify) + shell_ready_for_online, shell); + + /* Finalize the activity. */ + g_object_unref (activity); + + shell->priv->online = TRUE; + g_object_notify (G_OBJECT (shell), "online"); + + g_message ("Online preparations complete."); } -static GNOME_Evolution_ShellView -impl_Shell_createNewWindow (PortableServer_Servant servant, - const CORBA_char *component_id, - CORBA_Environment *ev) +static void +shell_prepare_for_online (EShell *shell) { - BonoboObject *bonobo_object; - EShell *shell; - EShellWindow *shell_window; - EShellView *shell_view; + /* Are preparations already in progress? */ + if (shell->priv->preparing_for_line_change != NULL) + return; - if (raise_exception_if_not_ready (servant, ev)) - return CORBA_OBJECT_NIL; + g_message ("Preparing for online mode..."); - bonobo_object = bonobo_object_from_servant (servant); - shell = E_SHELL (bonobo_object); + shell->priv->preparing_for_line_change = + e_activity_new (_("Preparing to go online...")); - if (component_id[0] == '\0') - component_id = NULL; + g_object_add_toggle_ref ( + G_OBJECT (shell->priv->preparing_for_line_change), + (GToggleNotify) shell_ready_for_online, shell); - shell_window = e_shell_create_window (shell, component_id, NULL); - if (shell_window == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_GNOME_Evolution_Shell_ComponentNotFound, NULL); - return CORBA_OBJECT_NIL; - } + g_object_add_weak_pointer ( + G_OBJECT (shell->priv->preparing_for_line_change), + &shell->priv->preparing_for_line_change); - /* refs?? */ - shell_view = e_shell_view_new(shell_window); - - return BONOBO_OBJREF(shell_view); + g_signal_emit ( + shell, signals[PREPARE_FOR_ONLINE], 0, + shell->priv->preparing_for_line_change); + g_object_unref (shell->priv->preparing_for_line_change); } static void -impl_Shell_handleURI (PortableServer_Servant servant, - const CORBA_char *uri, - CORBA_Environment *ev) +shell_ready_for_quit (EShell *shell, + EActivity *activity, + gboolean is_last_ref) { - EShell *shell = E_SHELL (bonobo_object_from_servant (servant)); - EComponentInfo *component_info; - gchar *schema, *p; - gint show = FALSE; - - schema = g_alloca(strlen(uri)+1); - strcpy(schema, uri); - p = strchr(schema, ':'); - if (p) - *p = 0; - - component_info = e_component_registry_peek_info(shell->priv->component_registry, ECR_FIELD_SCHEMA, schema); - if (component_info == NULL) { - show = TRUE; - component_info = e_component_registry_peek_info(shell->priv->component_registry, ECR_FIELD_ALIAS, schema); - } + GList *list; - if (component_info == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Shell_UnsupportedSchema, NULL); + if (!is_last_ref) return; - } - if (show) { - GtkWidget *shell_window; + /* Increment the reference count so we can safely emit + * a signal without triggering the toggle reference. */ + g_object_ref (activity); - shell_window = (GtkWidget *)e_shell_create_window (shell, component_info->id, NULL); - if (shell_window == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Shell_ComponentNotFound, NULL); - return; - } - } + e_activity_complete (activity); + + g_object_remove_toggle_ref ( + G_OBJECT (activity), (GToggleNotify) + shell_ready_for_quit, shell); + + /* Finalize the activity. */ + g_object_ref (activity); + + g_message ("Quit preparations complete."); - GNOME_Evolution_Component_handleURI (component_info->iface, uri, ev); - /* not an error not to implement it */ - if (ev->_id != NULL && strcmp(ev->_id, ex_CORBA_NO_IMPLEMENT) == 0) - memset(ev, 0, sizeof(*ev)); + /* Destroy all watched windows. Note, we iterate over a -copy- + * of the watched windows list because the act of destroying a + * watched window will modify the watched windows list, which + * would derail the iteration. */ + list = g_list_copy (e_shell_get_watched_windows (shell)); + g_list_foreach (list, (GFunc) gtk_widget_destroy, NULL); + g_list_free (list); } static void -impl_Shell_setLineStatus (PortableServer_Servant servant, - CORBA_boolean online, - CORBA_Environment *ev) +shell_prepare_for_quit (EShell *shell) { - BonoboObject *bonobo_object; - EShell *shell; + GList *list, *iter; - if (raise_exception_if_not_ready (servant, ev)) + /* Are preparations already in progress? */ + if (shell->priv->preparing_for_quit != NULL) return; - bonobo_object = bonobo_object_from_servant (servant); - shell = E_SHELL (bonobo_object); + g_message ("Preparing to quit..."); - /* let the password manager know out online status */ - e_passwords_set_online(online); + shell->priv->preparing_for_quit = + e_activity_new (_("Preparing to quit...")); - if (online) - e_shell_set_line_status (shell, GNOME_Evolution_USER_ONLINE); - else - e_shell_set_line_status (shell, GNOME_Evolution_USER_OFFLINE); -} -/* -static GNOME_Evolution_Component -impl_Shell_findComponent(PortableServer_Servant servant, - const CORBA_char *id, - CORBA_Environment *ev) -{ - EShell *shell; - EComponentInfo *ci; - - if (raise_exception_if_not_ready (servant, ev)) - return CORBA_OBJECT_NIL; - - shell = (EShell *)bonobo_object_from_servant (servant); - ci = e_component_registry_peek_info(shell->priv->component_registry, ECR_FIELD_ALIAS, id); - if (ci == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Shell_ComponentNotFound, NULL); - return CORBA_OBJECT_NIL; - } else if (ci->iface == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Shell_NotReady, NULL); - return CORBA_OBJECT_NIL; - } else { - return ci->iface; - } -} -*/ + g_object_add_toggle_ref ( + G_OBJECT (shell->priv->preparing_for_quit), + (GToggleNotify) shell_ready_for_quit, shell); -/* EShellWindow handling and bookkeeping. */ + g_object_add_weak_pointer ( + G_OBJECT (shell->priv->preparing_for_quit), + &shell->priv->preparing_for_quit); -static gint -window_delete_event_cb (GtkWidget *widget, - GdkEventAny *ev, - gpointer data) -{ - EShell *shell; + g_signal_emit ( + shell, signals[PREPARE_FOR_QUIT], 0, + shell->priv->preparing_for_quit); - g_return_val_if_fail (E_IS_SHELL_WINDOW (widget), TRUE); - shell = E_SHELL (data); + g_object_unref (shell->priv->preparing_for_quit); - return ! e_shell_request_close_window (shell, E_SHELL_WINDOW (widget)); + /* Desensitize all watched windows to prevent user action. */ + list = e_shell_get_watched_windows (shell); + for (iter = list; iter != NULL; iter = iter->next) + gtk_widget_set_sensitive (GTK_WIDGET (iter->data), FALSE); } static gboolean -notify_no_windows_left_idle_cb (gpointer data) +shell_request_quit (EShell *shell) { - EShell *shell; - EShellPrivate *priv; + /* Are preparations already in progress? */ + if (shell->priv->preparing_for_quit != NULL) + return TRUE; + + /* Give the application a chance to cancel quit. */ + shell->priv->quit_cancelled = FALSE; + g_signal_emit (shell, signals[QUIT_REQUESTED], 0); + + return !shell->priv->quit_cancelled; +} - shell = E_SHELL (data); - priv = shell->priv; +static void +shell_load_modules (EShell *shell) +{ + GList *modules; - set_interactive (shell, FALSE); + /* Load all shared library modules. */ + modules = e_module_load_all_in_directory (EVOLUTION_MODULEDIR); - g_signal_emit (shell, signals [NO_WINDOWS_LEFT], 0); + while (modules != NULL) { + g_type_module_unuse (G_TYPE_MODULE (modules->data)); + modules = g_list_delete_link (modules, modules); + } +} - if (priv->iid != NULL) - bonobo_activation_active_server_unregister (priv->iid, - bonobo_object_corba_objref (BONOBO_OBJECT (shell))); - bonobo_object_unref (BONOBO_OBJECT (shell)); +/* Helper for shell_process_backend() */ +static void +shell_split_and_insert_items (GHashTable *hash_table, + const gchar *items, + EShellBackend *shell_backend) +{ + gpointer key; + gchar **strv; + gint ii; - return FALSE; + strv = g_strsplit_set (items, ":", -1); + + for (ii = 0; strv[ii] != NULL; ii++) { + key = (gpointer) g_intern_string (strv[ii]); + g_hash_table_insert (hash_table, key, shell_backend); + } + + g_strfreev (strv); } static void -window_weak_notify (gpointer data, - GObject *where_the_object_was) +shell_process_backend (EShell *shell, + EShellBackend *shell_backend) { - EShell *shell; - gint num_windows; + EShellBackendClass *class; + GHashTable *backends_by_name; + GHashTable *backends_by_scheme; + const gchar *string; - shell = E_SHELL (data); + shell->priv->loaded_backends = g_list_insert_sorted ( + shell->priv->loaded_backends, shell_backend, + (GCompareFunc) e_shell_backend_compare); - num_windows = g_list_length (shell->priv->windows); + /* Bookkeeping */ - /* If this is our last window, save settings now because in the callback - for no_windows_left shell->priv->windows will be NULL and settings won't - be saved because of that. */ - if (num_windows == 1) - e_shell_save_settings (shell); + class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + backends_by_name = shell->priv->backends_by_name; + backends_by_scheme = shell->priv->backends_by_scheme; - shell->priv->windows = g_list_remove (shell->priv->windows, where_the_object_was); + if ((string = class->name) != NULL) + g_hash_table_insert ( + backends_by_name, (gpointer) + g_intern_string (string), shell_backend); - if (shell->priv->windows == NULL) { - bonobo_object_ref (BONOBO_OBJECT (shell)); - g_idle_add (notify_no_windows_left_idle_cb, shell); - } -} + if ((string = class->aliases) != NULL) + shell_split_and_insert_items ( + backends_by_name, string, shell_backend); -/* GObject methods. */ + if ((string = class->schemes) != NULL) + shell_split_and_insert_items ( + backends_by_scheme, string, shell_backend); +} static void -impl_dispose (GObject *object) +shell_create_backends (EShell *shell) { - EShell *shell; - EShellPrivate *priv; - GList *p; + GType *children; + guint ii, n_children; - shell = E_SHELL (object); - priv = shell->priv; + /* Create an instance of each EShellBackend subclass. */ + children = g_type_children (E_TYPE_SHELL_BACKEND, &n_children); - priv->is_initialized = FALSE; + for (ii = 0; ii < n_children; ii++) { + EShellBackend *shell_backend; + GType type = children[ii]; -#if 0 /* FIXME */ - if (priv->uri_schema_registry != NULL) { - g_object_unref (priv->uri_schema_registry); - priv->uri_schema_registry = NULL; + shell_backend = g_object_new (type, "shell", shell, NULL); + shell_process_backend (shell, shell_backend); } -#endif - if (priv->component_registry != NULL) { - g_object_unref (priv->component_registry); - priv->component_registry = NULL; - } + g_free (children); +} - if (priv->quit_timeout) { - g_source_remove(priv->quit_timeout); - priv->quit_timeout = 0; - } +static void +shell_sm_quit_requested_cb (EShell *shell, + EggSMClient *sm_client) +{ + gboolean will_quit; - for (p = priv->windows; p != NULL; p = p->next) { - EShellWindow *window; + /* If preparations are already in progress then we have already + * committed ourselves to quitting, and can answer 'yes'. */ + if (shell->priv->preparing_for_quit == NULL) + will_quit = shell_request_quit (shell); + else + will_quit = TRUE; - window = E_SHELL_WINDOW (p->data); + egg_sm_client_will_quit (sm_client, will_quit); +} - g_signal_handlers_disconnect_by_func (window, G_CALLBACK (window_delete_event_cb), shell); - g_object_weak_unref (G_OBJECT (window), window_weak_notify, shell); +static void +shell_sm_quit_cancelled_cb (EShell *shell, + EggSMClient *sm_client) +{ + /* Nothing to do. This is just to aid debugging. */ +} - gtk_object_destroy (GTK_OBJECT (window)); +static void +shell_sm_quit_cb (EShell *shell, + EggSMClient *sm_client) +{ + shell_prepare_for_quit (shell); +} + +static void +shell_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_NETWORK_AVAILABLE: + e_shell_set_network_available ( + E_SHELL (object), + g_value_get_boolean (value)); + return; + + case PROP_ONLINE: + e_shell_set_online ( + E_SHELL (object), + g_value_get_boolean (value)); + return; } - g_list_free (priv->windows); - priv->windows = NULL; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - /* No unreffing for these as they are aggregate. */ - /* bonobo_object_unref (BONOBO_OBJECT (priv->corba_storage_registry)); */ +static void +shell_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_NETWORK_AVAILABLE: + g_value_set_boolean ( + value, e_shell_get_network_available ( + E_SHELL (object))); + return; - if (priv->settings_dialog.widget != NULL) { - gtk_widget_destroy (priv->settings_dialog.widget); - priv->settings_dialog.widget = NULL; - } + case PROP_ONLINE: + g_value_set_boolean ( + value, e_shell_get_online ( + E_SHELL (object))); + return; - if (priv->line_status_listener) { - priv->line_status_listener->complete = NULL; - bonobo_object_unref(BONOBO_OBJECT(priv->line_status_listener)); - priv->line_status_listener = NULL; + case PROP_SHELL_SETTINGS: + g_value_set_object ( + value, e_shell_get_shell_settings ( + E_SHELL (object))); + return; } - g_free (priv->iid); - (* G_OBJECT_CLASS (parent_class)->dispose) (object); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -impl_finalize (GObject *object) +shell_dispose (GObject *object) { - EShell *shell; EShellPrivate *priv; - shell = E_SHELL (object); - priv = shell->priv; + priv = E_SHELL_GET_PRIVATE (object); - g_list_foreach (priv->crash_type_names, (GFunc) g_free, NULL); - g_list_free (priv->crash_type_names); + if (priv->settings != NULL) { + g_object_unref (priv->settings); + priv->settings = NULL; + } - g_free (priv); + if (priv->gconf_client != NULL) { + g_object_unref (priv->gconf_client); + priv->gconf_client = NULL; + } - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} + if (priv->preferences_window != NULL) { + g_object_unref (priv->preferences_window); + priv->preferences_window = NULL; + } -/* Initialization. */ + g_list_foreach (priv->loaded_backends, (GFunc) g_object_unref, NULL); + g_list_free (priv->loaded_backends); + priv->loaded_backends = NULL; -static void -e_shell_class_init (EShellClass *klass) -{ - GObjectClass *object_class; - POA_GNOME_Evolution_Shell__epv *epv; - - parent_class = g_type_class_ref(PARENT_TYPE); - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; - - signals[NO_WINDOWS_LEFT] = - g_signal_new ("no_windows_left", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EShellClass, no_windows_left), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[LINE_STATUS_CHANGED] = - g_signal_new ("line_status_changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EShellClass, line_status_changed), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - signals[NEW_WINDOW_CREATED] = - g_signal_new ("new_window_created", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EShellClass, new_window_created), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - - epv = & klass->epv; - epv->createNewWindow = impl_Shell_createNewWindow; - epv->handleURI = impl_Shell_handleURI; - epv->setLineStatus = impl_Shell_setLineStatus; -/* epv->findComponent = impl_Shell_findComponent;*/ + if (priv->preparing_for_line_change != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->preparing_for_line_change), + &priv->preparing_for_line_change); + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -e_shell_init (EShell *shell) +shell_finalize (GObject *object) { EShellPrivate *priv; - priv = g_new0 (EShellPrivate, 1); - priv->line_status = E_SHELL_LINE_STATUS_OFFLINE; - priv->component_registry = e_component_registry_new (); + priv = E_SHELL_GET_PRIVATE (object); - shell->priv = priv; + g_hash_table_destroy (priv->backends_by_name); + g_hash_table_destroy (priv->backends_by_scheme); - priv->line_status_listener = evolution_listener_new(set_line_status_complete, shell); + /* Indicates a clean shut down to the next session. */ + if (!unique_app_is_running (UNIQUE_APP (object))) + e_file_lock_destroy (); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -detect_version (GConfClient *gconf, gint *major, gint *minor, gint *revision) +shell_constructed (GObject *object) { - gchar *val, *evolution_dir; - struct stat st; - - evolution_dir = g_build_filename (g_get_home_dir (), "evolution", NULL); - - val = gconf_client_get_string(gconf, "/apps/evolution/version", NULL); - if (val) { - /* Since 1.4.0 We've been keeping the version key in gconf */ - sscanf(val, "%d.%d.%d", major, minor, revision); - g_free(val); - } else if (g_lstat (evolution_dir, &st) != 0 || !S_ISDIR (st.st_mode)) { - /* If ~/evolution does not exit or is not a directory it must be a new installation */ - *major = 0; - *minor = 0; - *revision = 0; - } else { - xmlDocPtr config_doc; - xmlNodePtr source; - gchar *tmp; - - tmp = g_build_filename (evolution_dir, "config.xmldb", NULL); - config_doc = e_xml_parse_file (tmp); - g_free (tmp); - tmp = NULL; - - if (config_doc - && (source = e_bconf_get_path (config_doc, "/Shell")) - && (tmp = e_bconf_get_value (source, "upgrade_from_1_0_to_1_2_performed")) - && tmp[0] == '1' ) { - *major = 1; - *minor = 2; - *revision = 0; - } else { - *major = 1; - *minor = 0; - *revision = 0; - } - g_free (tmp); - if (config_doc) - xmlFreeDoc (config_doc); - } + /* The first EShell instance is the default. */ + if (default_shell == NULL) + default_shell = g_object_ref (object); + + /* UniqueApp will have by this point determined whether we're + * the only Evolution process running. If so, proceed normally. + * Otherwise we just issue commands to the other process. */ + if (unique_app_is_running (UNIQUE_APP (object))) + return; + + e_file_lock_create (); - g_free (evolution_dir); + shell_load_modules (E_SHELL (object)); + shell_create_backends (E_SHELL (object)); + + e_shell_migrate_attempt (E_SHELL (object)); } -/* calls components to perform upgrade */ static gboolean -attempt_upgrade (EShell *shell, gint major, gint minor, gint revision) +shell_message_handle_new (EShell *shell, + UniqueMessageData *data) { - GSList *component_infos, *p; - gboolean success; - gint res; - - success = TRUE; - - component_infos = e_component_registry_peek_list (shell->priv->component_registry); - for (p = component_infos; success && p != NULL; p = p->next) { - const EComponentInfo *info = p->data; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - GNOME_Evolution_Component_upgradeFromVersion (info->iface, major, minor, revision, &ev); - - if (BONOBO_EX (&ev)) { - gchar *exception_text; - CORBA_char *id = CORBA_exception_id(&ev); - - if (strcmp (id, ex_CORBA_NO_IMPLEMENT) == 0) { - /* Ignore components that do not implement this version, it - might just mean that they don't need an upgrade path. */ - } else if (strcmp (id, ex_GNOME_Evolution_Component_UpgradeFailed) == 0) { - GNOME_Evolution_Component_UpgradeFailed *ex = CORBA_exception_value(&ev); - - res = e_error_run(NULL, "shell:upgrade-failed", ex->what, ex->why, NULL); - if (res == GTK_RESPONSE_CANCEL) - success = FALSE; - } else if (strcmp (id, ex_GNOME_Evolution_Component_UnsupportedVersion) == 0) { - /* This is non-fatal */ - /* DO WE CARE??? */ - printf("Upgrade of component failed, unsupported prior version\n"); - } else { - exception_text = bonobo_exception_get_text (&ev); - res = e_error_run(NULL, "shell:upgrade-failed", exception_text, _("Unknown system error."), NULL); - g_free (exception_text); - if (res == GTK_RESPONSE_CANCEL) - success = FALSE; - } - } - CORBA_exception_free (&ev); - } + gchar *view_name; + + view_name = unique_message_data_get_text (data); + e_shell_create_shell_window (shell, view_name); + g_free (view_name); - return success; + return TRUE; } -/** - * e_shell_construct: - * @shell: An EShell object to construct - * @iid: OAFIID for registering the shell into the name server - * @startup_line_mode: How to set up the line mode (online or offline) initally. - * - * Construct @shell so that it uses the specified @corba_object. - * - * Return value: The result of the operation. - **/ -EShellConstructResult -e_shell_construct (EShell *shell, - const gchar *iid, - EShellStartupLineMode startup_line_mode) +static gboolean +shell_message_handle_open (EShell *shell, + UniqueMessageData *data) { - EShellPrivate *priv; - CORBA_Object corba_object; - gboolean start_online; - GSList *component; - - g_return_val_if_fail (E_IS_SHELL (shell), E_SHELL_CONSTRUCT_RESULT_INVALIDARG); - g_return_val_if_fail (startup_line_mode == E_SHELL_STARTUP_LINE_MODE_CONFIG - || startup_line_mode == E_SHELL_STARTUP_LINE_MODE_ONLINE - || startup_line_mode == E_SHELL_STARTUP_LINE_MODE_OFFLINE, - E_SHELL_CONSTRUCT_RESULT_INVALIDARG); - - priv = shell->priv; - priv->iid = g_strdup (iid); - - /* Now we can register into OAF. Notice that we shouldn't be - registering into OAF until we are sure we can complete. */ - - /* FIXME: Multi-display stuff. */ - corba_object = bonobo_object_corba_objref (BONOBO_OBJECT (shell)); - if (bonobo_activation_active_server_register (iid, corba_object) != Bonobo_ACTIVATION_REG_SUCCESS) - return E_SHELL_CONSTRUCT_RESULT_CANNOTREGISTER; - - while (gtk_events_pending ()) - gtk_main_iteration (); - - /* activate all the components (peek list does this implictly) */ - /* Do we really need to assign the result of this to the list? */ - component = e_component_registry_peek_list (shell->priv->component_registry); - - e_shell_attempt_upgrade(shell); - - priv->is_initialized = TRUE; - - switch (startup_line_mode) { - case E_SHELL_STARTUP_LINE_MODE_CONFIG: - start_online = ! get_config_start_offline (); - break; - case E_SHELL_STARTUP_LINE_MODE_ONLINE: - start_online = TRUE; - break; - case E_SHELL_STARTUP_LINE_MODE_OFFLINE: - start_online = FALSE; - break; - default: - start_online = FALSE; /* Make compiler happy. */ - g_return_val_if_reached(E_SHELL_CONSTRUCT_RESULT_OK); - } + gchar **uris; - e_passwords_set_online(start_online); + uris = unique_message_data_get_uris (data); + e_shell_handle_uris (shell, uris); + g_strfreev (uris); - if (start_online) - e_shell_set_line_status (shell, GNOME_Evolution_USER_ONLINE); - else - e_shell_set_line_status (shell, GNOME_Evolution_USER_OFFLINE); + return TRUE; +} + +static gboolean +shell_message_handle_close (EShell *shell, + UniqueMessageData *data) +{ + e_shell_quit (shell); - return E_SHELL_CONSTRUCT_RESULT_OK; + return TRUE; } -/** - * e_shell_new: - * @start_online: Whether to start in on-line mode or not. - * @construct_result_return: A pointer to an EShellConstructResult variable into - * which the result of the operation will be stored. - * - * Create a new EShell. - * - * Return value: - **/ -EShell * -e_shell_new (EShellStartupLineMode startup_line_mode, - EShellConstructResult *construct_result_return) +static UniqueResponse +shell_message_received (UniqueApp *app, + gint command, + UniqueMessageData *data, + guint time_) { - EShell *new; - EShellConstructResult construct_result; + EShell *shell = E_SHELL (app); - new = g_object_new (e_shell_get_type (), NULL); + switch (command) { + case UNIQUE_ACTIVATE: + break; /* use the default behavior */ - construct_result = e_shell_construct (new, E_SHELL_OAFIID, startup_line_mode); + case UNIQUE_NEW: + if (shell_message_handle_new (shell, data)) + return UNIQUE_RESPONSE_OK; + break; - if (construct_result != E_SHELL_CONSTRUCT_RESULT_OK) { - *construct_result_return = construct_result; - bonobo_object_unref (BONOBO_OBJECT (new)); - return NULL; - } + case UNIQUE_OPEN: + if (shell_message_handle_open (shell, data)) + return UNIQUE_RESPONSE_OK; + break; - *construct_result_return = E_SHELL_CONSTRUCT_RESULT_OK; - return new; -} + case UNIQUE_CLOSE: + if (shell_message_handle_close (shell, data)) + return UNIQUE_RESPONSE_OK; + break; -static gint -remove_dir(const gchar *root, const gchar *path) -{ - GDir *dir; - const gchar *dname; - gint res = -1; - gchar *new = NULL; - struct stat st; - - dir = g_dir_open(path, 0, NULL); - if (dir == NULL) - return -1; - - while ( (dname = g_dir_read_name(dir)) ) { - new = g_build_filename(path, dname, NULL); - if (g_stat(new, &st) == -1) - goto fail; - - /* make sure we're really removing something from evolution dir */ - g_return_val_if_fail (strlen(path) >= strlen(root) - && strncmp(root, path, strlen(root)) == 0, -1); - - if (S_ISDIR(st.st_mode)) { - if (remove_dir(root, new) == -1) - goto fail; - } else { - if (g_unlink(new) == -1) - goto fail; - } - g_free(new); - new = NULL; + default: + break; } - res = g_rmdir(path); -fail: - g_free(new); - g_dir_close(dir); - return res; + /* Chain up to parent's message_received() method. */ + return UNIQUE_APP_CLASS (parent_class)-> + message_received (app, command, data, time_); } -/** - * e_shell_attempt_upgrade: - * @shell: - * - * Upgrade config and components from the currently installed version. - * - * Return value: %TRUE If it works. If it fails the application will exit. - **/ -gboolean -e_shell_attempt_upgrade (EShell *shell) +static void +shell_class_init (EShellClass *class) { - GConfClient *gconf_client; - gint major = 0, minor = 0, revision = 0; - gint lmajor, lminor, lrevision; - gint cmajor, cminor, crevision; - gchar *version_string, *last_version = NULL; - gint done_upgrade = FALSE; - gchar *oldpath; - struct stat st; - ESEvent *ese; - - gconf_client = gconf_client_get_default(); - - oldpath = g_build_filename(g_get_home_dir(), "evolution", NULL); - - g_return_val_if_fail (sscanf(BASE_VERSION, "%u.%u", &cmajor, &cminor) == 2, TRUE); - crevision = atoi(UPGRADE_REVISION); - - detect_version (gconf_client, &major, &minor, &revision); - - if (!(cmajor > major - || (cmajor == major && cminor > minor) - || (cminor == minor && crevision > revision))) - goto check_old; - - /* if upgrading from < 1.5, we need to copy most data from ~/evolution to ~/.evolution */ - if (major == 1 && minor < 5) { - long size, space; - - size = e_fsutils_usage(oldpath); - space = e_fsutils_avail(g_get_home_dir()); - if (size != -1 && space != -1 && space < size) { - gchar *required = g_strdup_printf(_("%ld KB"), size); - gchar *have = g_strdup_printf(_("%ld KB"), space); - - e_error_run(NULL, "shell:upgrade-nospace", required, have, NULL); - g_free(required); - g_free(have); - _exit(0); - } - } + GObjectClass *object_class; + UniqueAppClass *unique_app_class; - if (!attempt_upgrade (shell, major, minor, revision)) - _exit(0); - - /* mark as upgraded */ - version_string = g_strdup_printf ("%s.%s", BASE_VERSION, UPGRADE_REVISION); - gconf_client_set_string (gconf_client, "/apps/evolution/version", version_string, NULL); - done_upgrade = TRUE; - -check_old: - /* if the last upgraded version was old, check for stuff to remove */ - if (done_upgrade - || (last_version = gconf_client_get_string (gconf_client, "/apps/evolution/last_version", NULL)) == NULL - || sscanf(last_version, "%d.%d.%d", &lmajor, &lminor, &lrevision) != 3) { - lmajor = major; - lminor = minor; - lrevision = revision; - } - g_free(last_version); - - if (lmajor == 1 && lminor < 5 - && g_stat(oldpath, &st) == 0 - && S_ISDIR(st.st_mode)) { - gint res; - - last_version = g_strdup_printf("%d.%d.%d", lmajor, lminor, lrevision); - res = e_error_run(NULL, "shell:upgrade-remove-1-4", last_version, NULL); - g_free(last_version); - - switch (res) { - case GTK_RESPONSE_OK: /* 'delete' */ - if (e_error_run(NULL, "shell:upgrade-remove-1-4-confirm", NULL) == GTK_RESPONSE_OK) - remove_dir(oldpath, oldpath); - else - break; - /* falls through */ - case GTK_RESPONSE_ACCEPT: /* 'keep' */ - lmajor = cmajor; - lminor = cminor; - lrevision = crevision; - break; - default: - /* cancel - noop */ - break; - } - } else { - /* otherwise 'last version' is now the same as current */ - lmajor = cmajor; - lminor = cminor; - lrevision = crevision; - } + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellPrivate)); - last_version = g_strdup_printf("%d.%d.%d", lmajor, lminor, lrevision); - gconf_client_set_string (gconf_client, "/apps/evolution/last_version", last_version, NULL); - g_free(last_version); + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_set_property; + object_class->get_property = shell_get_property; + object_class->dispose = shell_dispose; + object_class->finalize = shell_finalize; + object_class->constructed = shell_constructed; - g_free(oldpath); - g_object_unref (gconf_client); + unique_app_class = UNIQUE_APP_CLASS (class); + unique_app_class->message_received = shell_message_received; - /** @Event: Shell attempted upgrade - * @Id: upgrade.done - * @Target: ESMenuTargetState + /** + * EShell:network-available * - * This event is emitted whenever the shell successfully attempts an upgrade. + * Whether the network is available. + **/ + g_object_class_install_property ( + object_class, + PROP_NETWORK_AVAILABLE, + g_param_spec_boolean ( + "network-available", + _("Network Available"), + _("Whether the network is available"), + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * EShell:online * - */ - ese = es_event_peek(); - e_event_emit((EEvent *)ese, "upgrade.done", (EEventTarget *)es_event_target_new_upgrade(ese, cmajor, cminor, crevision)); - - return TRUE; + * Whether the shell is online. + **/ + g_object_class_install_property ( + object_class, + PROP_ONLINE, + g_param_spec_boolean ( + "online", + _("Online"), + _("Whether the shell is online"), + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * EShell:settings + * + * The #EShellSettings object stores application settings. + **/ + g_object_class_install_property ( + object_class, + PROP_SHELL_SETTINGS, + g_param_spec_object ( + "shell-settings", + _("Shell Settings"), + _("Application-wide settings"), + E_TYPE_SHELL_SETTINGS, + G_PARAM_READABLE)); + + /** + * EShell::event + * @shell: the #EShell which emitted the signal + * @event_data: data associated with the event + * + * This signal is used to broadcast custom events to the entire + * application. The nature of @event_data depends on the event + * being broadcast. The signal's detail denotes the event. + **/ + signals[EVENT] = g_signal_new ( + "event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + /** + * EShell::handle-uri + * @shell: the #EShell which emitted the signal + * @uri: the URI to be handled + * + * Emitted when @shell receives a URI to be handled, usually by + * way of a command-line argument. An #EShellBackend should listen + * for this signal and try to handle the URI, usually by opening an + * editor window for the identified resource. + * + * Returns: %TRUE if the URI could be handled, %FALSE otherwise + **/ + signals[HANDLE_URI] = g_signal_new ( + "handle-uri", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, g_signal_accumulator_true_handled, NULL, + e_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + /** + * EShell::prepare-for-offline + * @shell: the #EShell which emitted the signal + * @activity: the #EActivity for offline preparations + * + * Emitted when the user elects to work offline. An #EShellBackend + * should listen for this signal and make preparations for working + * in offline mode. + * + * If preparations for working offline cannot immediately be + * completed (such as when synchronizing with a remote server), + * the #EShellBackend should reference the @activity until + * preparations are complete, and then unreference the @activity. + * This will delay Evolution from actually going to offline mode + * until all backends have unreferenced @activity. + **/ + signals[PREPARE_FOR_OFFLINE] = g_signal_new ( + "prepare-for-offline", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACTIVITY); + + /** + * EShell::prepare-for-online + * @shell: the #EShell which emitted the signal + * @activity: the #EActivity for offline preparations + * + * Emitted when the user elects to work online. An #EShellBackend + * should listen for this signal and make preparations for working + * in online mode. + * + * If preparations for working online cannot immediately be + * completed (such as when re-connecting to a remote server), the + * #EShellBackend should reference the @activity until preparations + * are complete, and then unreference the @activity. This will + * delay Evolution from actually going to online mode until all + * backends have unreferenced @activity. + **/ + signals[PREPARE_FOR_ONLINE] = g_signal_new ( + "prepare-for-online", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACTIVITY); + + /** + * EShell::prepare-for-quit + * @shell: the #EShell which emitted the signal + * @activity: the #EActivity for quit preparations + * + * Emitted when the user elects to quit the application, after + * #EShell::quit-requested. An #EShellBackend should listen for + * this signal and make preparations for shutting down. + * + * If preparations for shutting down cannot immediately be completed + * (such as when there are uncompleted network operations), the + * #EShellBackend should reference the @activity until preparations + * are complete, and then unreference the @activity. This will + * delay Evolution from actually shutting down until all backends + * have unreferenced @activity. + **/ + signals[PREPARE_FOR_QUIT] = g_signal_new ( + "prepare-for-quit", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_ACTIVITY); + + /** + * EShell::quit-requested + * @shell: the #EShell which emitted the signal + * + * Emitted when the user elects to quit the application, before + * #EShell::prepare-for-quit. + * + * #EShellBackend<!-- -->s and editor windows can listen for + * this signal to prompt the user to save changes or finish + * scheduled operations immediately (such as sending mail in + * Outbox). If the user elects to cancel, the signal handler + * should call e_shell_cancel_quit() to abort the quit. + **/ + signals[QUIT_REQUESTED] = g_signal_new ( + "quit-requested", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * EShell::send-receive + * @shell: the #EShell which emitted the signal + * @parent: a parent #GtkWindow + * + * Emitted when the user chooses the "Send / Receive" action. + * The parent window can be used for showing transient windows. + **/ + signals[SEND_RECEIVE] = g_signal_new ( + "send-receive", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_WINDOW); + + /** + * EShell::window-created + * @shell: the #EShell which emitted the signal + * @window: the newly created #GtkWindow + * + * Emitted when @shell begins watching a newly created window. + **/ + signals[WINDOW_CREATED] = g_signal_new ( + "window-created", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + GTK_TYPE_WINDOW); + + /** + * EShell::window-destroyed + * @shell: the #EShell which emitted the signal + * + * Emitted when a watched is destroyed. + **/ + signals[WINDOW_DESTROYED] = g_signal_new ( + "window-destroyed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /* Install some application-wide settings. */ + + e_shell_settings_install_property ( + g_param_spec_string ( + "file-chooser-folder", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); } -/** - * e_shell_create_window: - * @shell: The shell for which to create a new window. - * @component_id: Id or alias of the component to display in the new window. - * @template_window: Window from which to copy the window settings (can be %NULL). - * - * Create a new window for @uri. - * - * Return value: The new window. - **/ -EShellWindow * -e_shell_create_window (EShell *shell, - const gchar *component_id, - EShellWindow *template_window) +static void +shell_init (EShell *shell) { - EShellWindow *window; + GHashTable *backends_by_name; + GHashTable *backends_by_scheme; + EggSMClient *sm_client; - /* FIXME need to actually copy settings from template_window. */ + shell->priv = E_SHELL_GET_PRIVATE (shell); - g_return_val_if_fail (shell != NULL, NULL); - g_return_val_if_fail (E_IS_SHELL (shell), NULL); + backends_by_name = g_hash_table_new (g_str_hash, g_str_equal); + backends_by_scheme = g_hash_table_new (g_str_hash, g_str_equal); - window = E_SHELL_WINDOW (e_shell_window_new (shell, component_id)); + shell->priv->settings = g_object_new (E_TYPE_SHELL_SETTINGS, NULL); + shell->priv->gconf_client = gconf_client_get_default (); + shell->priv->preferences_window = e_preferences_window_new (); + shell->priv->backends_by_name = backends_by_name; + shell->priv->backends_by_scheme = backends_by_scheme; + shell->priv->safe_mode = e_file_lock_exists (); - g_signal_connect (window, "delete_event", G_CALLBACK (window_delete_event_cb), shell); - g_object_weak_ref (G_OBJECT (window), window_weak_notify, shell); - shell->priv->windows = g_list_prepend (shell->priv->windows, window); + g_object_ref_sink (shell->priv->preferences_window); - g_signal_emit (shell, signals[NEW_WINDOW_CREATED], 0, window); +#if NM_SUPPORT + e_shell_dbus_initialize (shell); +#endif - gtk_widget_show (GTK_WIDGET (window)); + shell_parse_debug_string (shell); - e_error_default_parent((GtkWindow *)window); + g_signal_connect ( + shell, "notify::online", + G_CALLBACK (shell_notify_online_cb), NULL); - set_interactive (shell, TRUE); + /* XXX Do this after creating the EShellSettings instance, + * otherwise the GConf bindings will not get set up. */ - if (!session_started) { - ESEvent *ese; + e_shell_settings_install_property_for_key ( + "start-offline", + "/apps/evolution/shell/start_offline"); - session_started = TRUE; - ese = es_event_peek(); - e_event_emit((EEvent *)ese, "started.done", (EEventTarget *)es_event_target_new_shell(ese, shell)); - } - return window; -} + e_shell_settings_install_property_for_key ( + "disable-application-handlers", + "/desktop/gnome/lockdown/disable_application_handlers"); -gboolean -e_shell_request_close_window (EShell *shell, - EShellWindow *shell_window) -{ - g_return_val_if_fail (E_IS_SHELL (shell), FALSE); - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); + e_shell_settings_install_property_for_key ( + "disable-command-line", + "/desktop/gnome/lockdown/disable_command_line"); - e_shell_save_settings (shell); + e_shell_settings_install_property_for_key ( + "disable-printing", + "/desktop/gnome/lockdown/disable_printing"); - if (g_list_length (shell->priv->windows) != 1) { - /* Not the last window. */ - return TRUE; + e_shell_settings_install_property_for_key ( + "disable-print-setup", + "/desktop/gnome/lockdown/disable_print_setup"); + + e_shell_settings_install_property_for_key ( + "disable-save-to-disk", + "/desktop/gnome/lockdown/disable_save_to_disk"); + + /*** Session Management ***/ + + sm_client = egg_sm_client_get (); + + /* Not participating in session saving yet. */ + egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_NO_RESTART); + + g_signal_connect_swapped ( + sm_client, "quit-requested", + G_CALLBACK (shell_sm_quit_requested_cb), shell); + + g_signal_connect_swapped ( + sm_client, "quit-cancelled", + G_CALLBACK (shell_sm_quit_cancelled_cb), shell); + + g_signal_connect_swapped ( + sm_client, "quit", + G_CALLBACK (shell_sm_quit_cb), shell); +} + +GType +e_shell_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EShellClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShell), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + UNIQUE_TYPE_APP, "EShell", &type_info, 0); } - return e_shell_quit(shell); + return type; } -#if 0 /* FIXME */ /** - * e_shell_peek_uri_schema_registry: - * @shell: An EShell object. + * e_shell_get_default: * - * Get the schema registry associated to @shell. + * Returns the #EShell created by <function>main()</function>. * - * Return value: A pointer to the EUriSchemaRegistry associated to @shell. + * Try to obtain the #EShell from elsewhere if you can. This function + * is intended as a temporary workaround for when that proves difficult. + * + * Returns: the #EShell singleton **/ -EUriSchemaRegistry * -e_shell_peek_uri_schema_registry (EShell *shell) +EShell * +e_shell_get_default (void) { - g_return_val_if_fail (E_IS_SHELL (shell), NULL); + /* Emit a warning if we call this too early. */ + g_return_val_if_fail (default_shell != NULL, NULL); - return shell->priv->uri_schema_registry; + return default_shell; } -#endif /** - * e_shell_peek_component_registry: - * @shell: + * e_shell_get_shell_backends: + * @shell: an #EShell * - * Get the component registry associated to @shell. + * Returns a list of loaded #EShellBackend instances. The list is + * owned by @shell and should not be modified or freed. * - * Return value: + * Returns: a list of loaded #EShellBackend instances **/ -EComponentRegistry * -e_shell_peek_component_registry (EShell *shell) +GList * +e_shell_get_shell_backends (EShell *shell) { g_return_val_if_fail (E_IS_SHELL (shell), NULL); - return shell->priv->component_registry; + return shell->priv->loaded_backends; } /** - * e_shell_save_settings: - * @shell: + * e_shell_get_canonical_name: + * @shell: an #EShell + * @name: the name or alias of an #EShellBackend * - * Save the settings for this shell. + * Returns the canonical name for the #EShellBackend whose name or alias + * is @name. * - * Return value: %TRUE if it worked, %FALSE otherwise. Even if %FALSE is - * returned, it is possible that at least part of the settings for the windows - * have been saved. + * Returns: the canonical #EShellBackend name **/ -gboolean -e_shell_save_settings (EShell *shell) +const gchar * +e_shell_get_canonical_name (EShell *shell, + const gchar *name) { - GConfClient *client; - gboolean is_offline; + EShellBackend *shell_backend; - is_offline = ( e_shell_get_line_status (shell) == E_SHELL_LINE_STATUS_OFFLINE ); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - client = gconf_client_get_default (); - gconf_client_set_bool (client, "/apps/evolution/shell/start_offline", is_offline, NULL); - g_object_unref (client); + /* Handle NULL name arguments silently. */ + if (name == NULL) + return NULL; - return TRUE; + shell_backend = e_shell_get_backend_by_name (shell, name); + + if (shell_backend == NULL) + return NULL; + + return E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; } /** - * e_shell_close_all_windows: - * @shell: + * e_shell_get_backend_by_name: + * @shell: an #EShell + * @name: the name or alias of an #EShellBackend + * + * Returns the corresponding #EShellBackend for the given name or alias, + * or %NULL if @name is not recognized. * - * Destroy all the windows in @shell. + * Returns: the #EShellBackend named @name, or %NULL **/ -void -e_shell_close_all_windows (EShell *shell) +EShellBackend * +e_shell_get_backend_by_name (EShell *shell, + const gchar *name) { - EShellPrivate *priv; - GList *p, *pnext; - - g_return_if_fail (shell != NULL); - g_return_if_fail (E_IS_SHELL (shell)); + GHashTable *hash_table; - if (shell->priv->windows) - e_shell_save_settings (shell); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + g_return_val_if_fail (name != NULL, NULL); - priv = shell->priv; - for (p = priv->windows; p != NULL; p = pnext) { - pnext = p->next; + hash_table = shell->priv->backends_by_name; - /* Note that this will also remove the window from the list... Hence the - need for the pnext variable. */ - gtk_widget_destroy (GTK_WIDGET (p->data)); - } + return g_hash_table_lookup (hash_table, name); } /** - * e_shell_get_line_status: - * @shell: A pointer to an EShell object. + * e_shell_get_backend_by_scheme: + * @shell: an #EShell + * @scheme: a URI scheme * - * Get the line status for @shell. + * Returns the #EShellBackend that implements the given URI scheme, + * or %NULL if @scheme is not recognized. * - * Return value: The current line status for @shell. + * Returns: the #EShellBackend that implements @scheme, or %NULL **/ -EShellLineStatus -e_shell_get_line_status (EShell *shell) +EShellBackend * +e_shell_get_backend_by_scheme (EShell *shell, + const gchar *scheme) { - g_return_val_if_fail (shell != NULL, E_SHELL_LINE_STATUS_OFFLINE); - g_return_val_if_fail (E_IS_SHELL (shell), E_SHELL_LINE_STATUS_OFFLINE); + GHashTable *hash_table; - return shell->priv->line_status; -} + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + g_return_val_if_fail (scheme != NULL, NULL); -/* Offline/online handling. */ + hash_table = shell->priv->backends_by_scheme; -static void -set_line_status_finished(EShell *shell) + return g_hash_table_lookup (hash_table, scheme); +} +/** + * e_shell_get_shell_settings: + * @shell: an #EShell + * + * Returns the #EShellSettings instance for @shell. + * + * Returns: the #EShellSettings instance for @shell + **/ +EShellSettings * +e_shell_get_shell_settings (EShell *shell) { - EShellPrivate *priv = shell->priv; - ESEvent *ese; - - priv->line_status = priv->line_status_working; - - e_passwords_set_online (priv->line_status == E_SHELL_LINE_STATUS_ONLINE); - g_signal_emit (shell, signals[LINE_STATUS_CHANGED], 0, priv->line_status); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - /** @Event: Shell online state changed - * @Id: state.changed - * @Target: ESMenuTargetState - * - * This event is emitted whenever the shell online state changes. - * - * Only the online and offline states are emitted. - */ - ese = es_event_peek(); - e_event_emit((EEvent *)ese, "state.changed", (EEventTarget *)es_event_target_new_state(ese, priv->line_status == E_SHELL_LINE_STATUS_ONLINE)); + return shell->priv->settings; } -static void -set_line_status_complete(EvolutionListener *el, gpointer data) +/** + * e_shell_get_gconf_client: + * @shell: an #EShell + * + * Returns the default #GConfClient. This function is purely for + * convenience. The @shell owns the reference so you don't have to. + * + * Returns: the default #GConfClient + **/ +GConfClient * +e_shell_get_gconf_client (EShell *shell) { - EShell *shell = data; - EShellPrivate *priv = shell->priv; + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - if (priv->line_status_pending > 0) { - priv->line_status_pending--; - if (priv->line_status_pending == 0) - set_line_status_finished(shell); - } + return shell->priv->gconf_client; } -void -e_shell_set_line_status (EShell *shell, - GNOME_Evolution_ShellState shell_state) +/** + * e_shell_create_shell_window: + * @shell: an #EShell + * @view_name: name of the initial shell view, or %NULL + * + * Creates a new #EShellWindow and emits the #EShell::window-created + * signal. Use this function instead of e_shell_window_new() so that + * @shell can track the window. + * + * Returns: a new #EShellWindow + **/ +GtkWidget * +e_shell_create_shell_window (EShell *shell, + const gchar *view_name) { - EShellPrivate *priv; - GSList *component_infos; - GSList *p; - CORBA_Environment ev; - GConfClient *client; - gboolean is_online; - gboolean forced = FALSE; - - priv = shell->priv; - - if (shell_state == GNOME_Evolution_FORCED_OFFLINE || shell_state == GNOME_Evolution_USER_OFFLINE) { - is_online = FALSE; - if (shell_state == GNOME_Evolution_FORCED_OFFLINE) - forced = TRUE; - } else - is_online = TRUE; + GtkWidget *shell_window; + UniqueMessageData *data; + UniqueApp *app; - if ((is_online && priv->line_status == E_SHELL_LINE_STATUS_ONLINE) - || (!is_online && priv->line_status == E_SHELL_LINE_STATUS_OFFLINE && !forced)) - return; - - /* we use 'going offline' to mean 'changing status' now */ - priv->line_status = E_SHELL_LINE_STATUS_GOING_OFFLINE; - g_signal_emit (shell, signals[LINE_STATUS_CHANGED], 0, priv->line_status); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - client = gconf_client_get_default (); - if (!forced) - gconf_client_set_bool (client, "/apps/evolution/shell/start_offline", !is_online, NULL); - g_object_unref (client); + app = UNIQUE_APP (shell); - priv->line_status_working = is_online ? E_SHELL_LINE_STATUS_ONLINE: forced?E_SHELL_LINE_STATUS_FORCED_OFFLINE:E_SHELL_LINE_STATUS_OFFLINE; - /* we start at 2: setLineStatus could recursively call back, we therefore - `need to not complete till we're really complete */ - priv->line_status_pending += 2; + if (unique_app_is_running (app)) + goto unique; - component_infos = e_component_registry_peek_list (priv->component_registry); - for (p = component_infos; p != NULL; p = p->next) { - EComponentInfo *info = p->data; + view_name = e_shell_get_canonical_name (shell, view_name); - CORBA_exception_init (&ev); + /* EShellWindow initializes its active view from a GConf key, + * so set the key ahead of time to control the intial view. */ + if (view_name != NULL) { + GConfClient *client; + const gchar *key; + GError *error = NULL; - GNOME_Evolution_Component_setLineStatus(info->iface, shell_state, bonobo_object_corba_objref((BonoboObject *)priv->line_status_listener), &ev); - if (ev._major == CORBA_NO_EXCEPTION) - priv->line_status_pending++; + client = e_shell_get_gconf_client (shell); + key = "/apps/evolution/shell/view_defaults/component_id"; + gconf_client_set_string (client, key, view_name, &error); - CORBA_exception_free (&ev); + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + } } - priv->line_status_pending -= 2; - if (priv->line_status_pending == 0) - set_line_status_finished(shell); -} + shell_window = e_shell_window_new (shell, shell->priv->safe_mode); -gboolean -e_shell_get_crash_recovery (EShell *shell) -{ - g_return_val_if_fail (E_IS_SHELL (shell), FALSE); + gtk_widget_show (shell_window); - return shell->priv->crash_recovery; -} + return shell_window; -void -e_shell_set_crash_recovery (EShell *shell, - gboolean crash_recovery) -{ - g_return_if_fail (E_IS_SHELL (shell)); +unique: /* Send a message to the other Evolution process. */ + + /* XXX Do something with UniqueResponse? */ - shell->priv->crash_recovery = crash_recovery; + if (view_name != NULL) { + data = unique_message_data_new (); + unique_message_data_set_text (data, view_name, -1); + unique_app_send_message (app, UNIQUE_NEW, data); + unique_message_data_free (data); + } else + unique_app_send_message (app, UNIQUE_ACTIVATE, NULL); + + return NULL; } -void -e_shell_send_receive (EShell *shell) +/** + * e_shell_handle_uris: + * @shell: an #EShell + * @uris: %NULL-terminated list of URIs + * + * Emits the #EShell::handle-uri signal for each URI. + * + * Returns: the number of URIs successfully handled + **/ +guint +e_shell_handle_uris (EShell *shell, + gchar **uris) { - GSList *component_list; - GSList *p; + UniqueApp *app; + UniqueMessageData *data; + guint n_handled = 0; + gint ii; - g_return_if_fail (E_IS_SHELL (shell)); + g_return_val_if_fail (E_IS_SHELL (shell), FALSE); + g_return_val_if_fail (uris != NULL, FALSE); - component_list = e_component_registry_peek_list (shell->priv->component_registry); + app = UNIQUE_APP (shell); - for (p = component_list; p != NULL; p = p->next) { - EComponentInfo *info = p->data; - CORBA_Environment ev; + if (unique_app_is_running (app)) + goto unique; - CORBA_exception_init (&ev); + for (ii = 0; uris[ii] != NULL; ii++) { + gboolean handled; - GNOME_Evolution_Component_sendAndReceive (info->iface, &ev); + g_signal_emit ( + shell, signals[HANDLE_URI], + 0, uris[ii], &handled); + n_handled += handled ? 1 : 0; + } - /* Ignore errors, the components can decide to not implement - this interface. */ + return n_handled; - CORBA_exception_free (&ev); - } +unique: /* Send a message to the other Evolution process. */ + + /* XXX Do something with UniqueResponse? */ + + data = unique_message_data_new (); + unique_message_data_set_uris (data, uris); + unique_app_send_message (app, UNIQUE_OPEN, data); + unique_message_data_free (data); + + /* As far as we're concerned, all URIs have been handled. */ + + return g_strv_length (uris); } +/** + * e_shell_watch_window: + * @shell: an #EShell + * @window: a #GtkWindow + * + * Makes @shell "watch" a newly created toplevel window, and emits the + * #EShell::window-created signal. All #EShellWindow<!-- -->s should be + * watched, along with any editor or viewer windows that may be shown in + * response to e_shell_handle_uris(). When the last watched window is + * closed, Evolution terminates. + **/ void -e_shell_show_settings (EShell *shell, - const gchar *type, - EShellWindow *shell_window) +e_shell_watch_window (EShell *shell, + GtkWindow *window) { - EShellPrivate *priv; + GList *list; - g_return_if_fail (shell != NULL); g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (GTK_IS_WINDOW (window)); - priv = shell->priv; + list = shell->priv->watched_windows; - if (priv->settings_dialog.widget != NULL) { - gdk_window_show (priv->settings_dialog.widget->window); - gtk_widget_grab_focus (priv->settings_dialog.widget); + /* Ignore duplicates. */ + if (g_list_find (list, window) != NULL) return; - } - priv->settings_dialog.widget = e_shell_settings_dialog_new (); + list = g_list_prepend (list, window); + shell->priv->watched_windows = list; - if (type != NULL) - e_shell_settings_dialog_show_type (E_SHELL_SETTINGS_DIALOG (priv->settings_dialog.widget), type); + unique_app_watch_window (UNIQUE_APP (shell), window); - g_object_add_weak_pointer (G_OBJECT (priv->settings_dialog.widget), &priv->settings_dialog.pointer); + g_signal_connect_swapped ( + window, "delete-event", + G_CALLBACK (shell_window_delete_event_cb), shell); - gtk_window_set_transient_for (GTK_WINDOW (priv->settings_dialog.widget), GTK_WINDOW (shell_window)); - gtk_widget_show (priv->settings_dialog.widget); -} + g_signal_connect_swapped ( + window, "focus-in-event", + G_CALLBACK (shell_window_focus_in_event_cb), shell); -const gchar * -e_shell_construct_result_to_string (EShellConstructResult result) -{ - switch (result) { - case E_SHELL_CONSTRUCT_RESULT_OK: - return _("OK"); - case E_SHELL_CONSTRUCT_RESULT_INVALIDARG: - return _("Invalid arguments"); - case E_SHELL_CONSTRUCT_RESULT_CANNOTREGISTER: - return _("Cannot register on OAF"); - case E_SHELL_CONSTRUCT_RESULT_NOCONFIGDB: - return _("Configuration Database not found"); - case E_SHELL_CONSTRUCT_RESULT_GENERICERROR: - return _("Generic error"); - default: - return _("Unknown error"); - } + g_object_weak_ref ( + G_OBJECT (window), (GWeakNotify) + shell_window_weak_notify_cb, shell); + + g_signal_emit (shell, signals[WINDOW_CREATED], 0, window); } -/* timeout handler, so returns TRUE if we can't quit yet */ -static gboolean -es_run_quit(EShell *shell) +/** + * e_shell_get_watched_windows: + * @shell: an #EShell + * + * Returns a list of windows being watched by @shell. The list is sorted + * by the most recently focused window, such that the first instance is the + * currently focused window. (Useful for choosing a parent for a transient + * window.) The list is owned by @shell and should not be modified or freed. + * + * Returns: a list of watched windows + **/ +GList * +e_shell_get_watched_windows (EShell *shell) { - EShellPrivate *priv; - GSList *component_infos; - GSList *sp; - CORBA_boolean done_quit; - - g_return_val_if_fail (E_IS_SHELL (shell), FALSE); - - priv = shell->priv; - priv->preparing_to_quit = TRUE; - - component_infos = e_component_registry_peek_list (priv->component_registry); - done_quit = TRUE; - for (sp = component_infos; sp != NULL; sp = sp->next) { - EComponentInfo *info = sp->data; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - done_quit = GNOME_Evolution_Component_quit(info->iface, &ev); - if (BONOBO_EX (&ev)) { - /* The component might not implement the interface, in which case we assume we can quit. */ - done_quit = TRUE; - } - - CORBA_exception_free (&ev); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - if (!done_quit) - break; - } + return shell->priv->watched_windows; +} - if (done_quit) { - if (priv->quit_timeout) { - g_source_remove(priv->quit_timeout); - priv->quit_timeout = 0; - } - e_shell_close_all_windows(shell); - } else if (priv->quit_timeout == 0) { - priv->quit_timeout = g_timeout_add(500, (GSourceFunc)es_run_quit, shell); - } +/** + * e_shell_send_receive: + * @shell: an #EShell + * @parent: the parent #GtkWindow + * + * Emits the #EShell::send-receive signal. + **/ +void +e_shell_send_receive (EShell *shell, + GtkWindow *parent) +{ + g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (GTK_IS_WINDOW (parent)); - return !done_quit; + g_signal_emit (shell, signals[SEND_RECEIVE], 0, parent); } +/** + * e_shell_get_network_available: + * @shell: an #EShell + * + * Returns %TRUE if a network is available. + * + * Returns: %TRUE if a network is available + **/ gboolean -e_shell_can_quit (EShell *shell) +e_shell_get_network_available (EShell *shell) { - EShellPrivate *priv; - GSList *component_infos; - GSList *sp; - CORBA_boolean can_quit; - g_return_val_if_fail (E_IS_SHELL (shell), FALSE); - priv = shell->priv; - - if (priv->preparing_to_quit) - return FALSE; - - component_infos = e_component_registry_peek_list (priv->component_registry); - can_quit = TRUE; - for (sp = component_infos; sp != NULL; sp = sp->next) { - EComponentInfo *info = sp->data; - CORBA_Environment ev; - - CORBA_exception_init (&ev); + return shell->priv->network_available; +} - can_quit = GNOME_Evolution_Component_requestQuit (info->iface, &ev); - if (BONOBO_EX (&ev)) { - /* The component might not implement the interface, in which case we assume we can quit. */ - can_quit = TRUE; - } +/** + * e_shell_set_network_available: + * @shell: an #EShell + * @network_available: whether a network is available + * + * Sets whether a network is available. This is usually called in + * response to a status change signal from NetworkManager. If the + * network becomes unavailable while #EShell:online is %TRUE, the + * @shell will force #EShell:online to %FALSE until the network + * becomes available again. + **/ +void +e_shell_set_network_available (EShell *shell, + gboolean network_available) +{ + g_return_if_fail (E_IS_SHELL (shell)); - CORBA_exception_free (&ev); + if (network_available == shell->priv->network_available) + return; - if (! can_quit) - break; + shell->priv->network_available = network_available; + g_object_notify (G_OBJECT (shell), "network-available"); + + /* If we're being forced offline, perhaps due to a network outage, + * reconnect automatically when the network becomes available. */ + if (!network_available && shell->priv->online) { + g_message ("Network disconnected. Forced offline."); + e_shell_set_online (shell, FALSE); + shell->priv->auto_reconnect = TRUE; + } else if (network_available && shell->priv->auto_reconnect) { + g_message ("Connection established. Going online."); + e_shell_set_online (shell, TRUE); + shell->priv->auto_reconnect = FALSE; } - - return can_quit; } +/** + * e_shell_get_online: + * @shell: an #EShell + * + * Returns %TRUE if Evolution is online, %FALSE if Evolution is offline. + * Evolution may be offline because the user elected to work offline, or + * because the network has become unavailable. + * + * Returns: %TRUE if Evolution is online + **/ gboolean -e_shell_do_quit (EShell *shell) +e_shell_get_online (EShell *shell) { - EShellPrivate *priv; - GList *p; - gboolean can_quit; - g_return_val_if_fail (E_IS_SHELL (shell), FALSE); - priv = shell->priv; - - if (priv->preparing_to_quit) - return FALSE; - - for (p = shell->priv->windows; p != NULL; p = p->next) { - gtk_widget_set_sensitive (GTK_WIDGET (p->data), FALSE); - - if (p == shell->priv->windows) - e_shell_window_save_defaults (p->data); - } + return shell->priv->online; +} - can_quit = !es_run_quit (shell); +/** + * e_shell_set_online: + * @shell: an #EShell + * @online: %TRUE to go online, %FALSE to go offline + * + * Asynchronously places Evolution in online or offline mode. + **/ +void +e_shell_set_online (EShell *shell, + gboolean online) +{ + g_return_if_fail (E_IS_SHELL (shell)); - /* Mark a safe quit by destroying the lock. */ - e_file_lock_destroy (); + if (online == shell->priv->online) + return; - return can_quit; + if (online) + shell_prepare_for_online (shell); + else + shell_prepare_for_offline (shell); } -gboolean -e_shell_quit (EShell *shell) +/** + * e_shell_get_preferences_window: + * @shell: an #EShell + * + * Returns the Evolution Preferences window. + * + * Returns: the preferences window + **/ +GtkWidget * +e_shell_get_preferences_window (EShell *shell) { - return e_shell_can_quit (shell) && e_shell_do_quit (shell); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + + return shell->priv->preferences_window; } /** - * gboolean (*EMainShellFunc) (EShell *shell, EShellWindow *window, gpointer user_data); - * Function used in @ref e_shell_foreach_shell_window. - * @param shell Pointer to EShell. - * @param window Pointer to EShellWindow. - * @param user_data User's data passed to @ref main_shell_foreach_shell_window. - * @return TRUE if need to go to next window, FALSE when stop looking for next window. + * e_shell_event: + * @shell: an #EShell + * @event_name: the name of the event + * @event_data: data associated with the event + * + * The #EShell::event signal acts as a cheap mechanism for broadcasting + * events to the rest of the application, such as new mail arriving. The + * @event_name is used as the signal detail, and @event_data may point to + * an object or data structure associated with the event. **/ +void +e_shell_event (EShell *shell, + const gchar *event_name, + gpointer event_data) +{ + GQuark detail; + + g_return_if_fail (E_IS_SHELL (shell)); + g_return_if_fail (event_name != NULL); + + detail = g_quark_from_string (event_name); + g_signal_emit (shell, signals[EVENT], detail, event_data); +} -/** - * e_shell_foreach_shell_window - * This will call function callback for all known EShellWindow of main shell. - * When there is no shell active, then this will do nothing. - * @param shell EShell instance. - * @param func Function to be called. - * @param user_data User data to pass to func. - **/ void -e_shell_foreach_shell_window (EShell *shell, EMainShellFunc func, gpointer user_data) +e_shell_quit (EShell *shell) { - EShellPrivate *priv; - GList *p; + g_return_if_fail (E_IS_SHELL (shell)); - if (!shell) + if (!shell_request_quit (shell)) return; - priv = shell->priv; + shell_prepare_for_quit (shell); +} - for (p = priv->windows; p != NULL; p = p->next) { - EShellWindow *window; +/** + * e_shell_cancel_quit: + * @shell: an #EShell + * + * This function may only be called from #EShell::quit-requested signal + * handlers to prevent Evolution from quitting. Calling this will stop + * further emission of the #EShell::quit-requested signal. + * + * Note: This function has no effect during a #EShell::prepare-for-quit + * signal emission. + **/ +void +e_shell_cancel_quit (EShell *shell) +{ + g_return_if_fail (E_IS_SHELL (shell)); - window = E_SHELL_WINDOW (p->data); + shell->priv->quit_cancelled = TRUE; - if (window && !func (shell, window, user_data)) - break; - } + g_signal_stop_emission (shell, signals[QUIT_REQUESTED], 0); } - -BONOBO_TYPE_FUNC_FULL (EShell, GNOME_Evolution_Shell, PARENT_TYPE, e_shell) diff --git a/shell/e-shell.h b/shell/e-shell.h index 00f4266562..818607e1fb 100644 --- a/shell/e-shell.h +++ b/shell/e-shell.h @@ -1,4 +1,6 @@ /* + * e-shell.h + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -13,126 +15,98 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef _E_SHELL_H_ -#define _E_SHELL_H_ - -#include <bonobo-activation/bonobo-activation.h> -#include <bonobo/bonobo-object.h> +/** + * SECTION: e-shell + * @short_description: the backbone of Evolution + * @include: shell/e-shell.h + **/ + +#ifndef E_SHELL_H +#define E_SHELL_H + +#include <unique/unique.h> +#include <gconf/gconf-client.h> +#include <shell/e-shell-common.h> +#include <shell/e-shell-backend.h> +#include <shell/e-shell-settings.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL \ + (e_shell_get_type ()) +#define E_SHELL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL, EShell)) +#define E_SHELL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL, EShellClass)) +#define E_IS_SHELL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL)) +#define E_IS_SHELL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SHELL)) +#define E_SHELL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL, EShellClass)) G_BEGIN_DECLS -typedef struct _EShell EShell; +typedef struct _EShell EShell; +typedef struct _EShellClass EShellClass; typedef struct _EShellPrivate EShellPrivate; -typedef struct _EShellClass EShellClass; - -#include "Evolution.h" - -#include "e-component-registry.h" -#include "e-shell-window.h" - -#define E_TYPE_SHELL (e_shell_get_type ()) -#define E_SHELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SHELL, EShell)) -#define E_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SHELL, EShellClass)) -#define E_IS_SHELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SHELL)) -#define E_IS_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SHELL)) - -enum _EShellLineStatus { - E_SHELL_LINE_STATUS_ONLINE, - E_SHELL_LINE_STATUS_GOING_OFFLINE, /* NB: really means changing state in either direction */ - E_SHELL_LINE_STATUS_OFFLINE, - E_SHELL_LINE_STATUS_FORCED_OFFLINE -}; -typedef enum _EShellLineStatus EShellLineStatus; - -enum _EShellStartupLineMode { - E_SHELL_STARTUP_LINE_MODE_CONFIG, - E_SHELL_STARTUP_LINE_MODE_ONLINE, - E_SHELL_STARTUP_LINE_MODE_OFFLINE -}; -typedef enum _EShellStartupLineMode EShellStartupLineMode; +/** + * EShell: + * + * Contains only private data that should be read and manipulated using the + * functions below. + **/ struct _EShell { - BonoboObject parent; - + UniqueApp parent; EShellPrivate *priv; }; struct _EShellClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_Shell__epv epv; - - void (* no_windows_left) (EShell *shell); - void (* line_status_changed) (EShell *shell, EShellLineStatus status); - void (* new_window_created) (EShell *shell, EShellWindow *window); + UniqueAppClass parent_class; }; -/* ID for registering the shell in the OAF name service. */ -#define E_SHELL_OAFIID "OAFIID:GNOME_Evolution_Shell:" BASE_VERSION - -enum _EShellConstructResult { - E_SHELL_CONSTRUCT_RESULT_OK, - E_SHELL_CONSTRUCT_RESULT_INVALIDARG, - E_SHELL_CONSTRUCT_RESULT_CANNOTREGISTER, - E_SHELL_CONSTRUCT_RESULT_NOCONFIGDB, - E_SHELL_CONSTRUCT_RESULT_GENERICERROR -}; -typedef enum _EShellConstructResult EShellConstructResult; - -GType e_shell_get_type (void); -EShellConstructResult e_shell_construct (EShell *shell, - const gchar *iid, - EShellStartupLineMode startup_line_mode); -EShell *e_shell_new (EShellStartupLineMode startup_line_mode, - EShellConstructResult *construct_result_return); - -gboolean e_shell_attempt_upgrade (EShell *shell); - -EShellWindow *e_shell_create_window (EShell *shell, - const gchar *component_id, - EShellWindow *template_window); -gboolean e_shell_request_close_window (EShell *shell, - EShellWindow *window); - -#if 0 -EUriSchemaRegistry *e_shell_peek_uri_schema_registry (EShell *shell); -#endif - -EComponentRegistry *e_shell_peek_component_registry (EShell *shell); - -gboolean e_shell_save_settings (EShell *shell); -void e_shell_close_all_windows (EShell *shell); - -EShellLineStatus e_shell_get_line_status (EShell *shell); -void e_shell_set_line_status (EShell *shell, - GNOME_Evolution_ShellState shell_state); - -gboolean e_shell_get_crash_recovery (EShell *shell); -void e_shell_set_crash_recovery (EShell *shell, - gboolean crash_recovery); - -void e_shell_send_receive (EShell *shell); - -void e_shell_show_settings (EShell *shell, - const gchar *type, - EShellWindow *shell_window); - -gboolean e_shell_can_quit (EShell *shell); -gboolean e_shell_do_quit (EShell *shell); -gboolean e_shell_quit (EShell *shell); - -const gchar *e_shell_construct_result_to_string (EShellConstructResult result); - -typedef gboolean (*EMainShellFunc) (EShell *shell, EShellWindow *window, gpointer user_data); -void e_shell_foreach_shell_window (EShell *shell, EMainShellFunc func, gpointer user_data); +GType e_shell_get_type (void); +EShell * e_shell_get_default (void); +GList * e_shell_get_shell_backends (EShell *shell); +const gchar * e_shell_get_canonical_name (EShell *shell, + const gchar *name); +EShellBackend * e_shell_get_backend_by_name (EShell *shell, + const gchar *name); +EShellBackend * e_shell_get_backend_by_scheme (EShell *shell, + const gchar *scheme); +EShellSettings *e_shell_get_shell_settings (EShell *shell); +GConfClient * e_shell_get_gconf_client (EShell *shell); +GtkWidget * e_shell_create_shell_window (EShell *shell, + const gchar *view_name); +guint e_shell_handle_uris (EShell *shell, + gchar **uris); +void e_shell_watch_window (EShell *shell, + GtkWindow *window); +GList * e_shell_get_watched_windows (EShell *shell); +void e_shell_send_receive (EShell *shell, + GtkWindow *parent); +gboolean e_shell_get_network_available (EShell *shell); +void e_shell_set_network_available (EShell *shell, + gboolean network_available); +gboolean e_shell_get_online (EShell *shell); +void e_shell_set_online (EShell *shell, + gboolean online); +GtkWidget * e_shell_get_preferences_window (EShell *shell); +void e_shell_event (EShell *shell, + const gchar *event_name, + gpointer event_data); +void e_shell_quit (EShell *shell); +void e_shell_cancel_quit (EShell *shell); G_END_DECLS -#endif /* _E_SHELL_H_ */ +#endif /* E_SHELL_H */ diff --git a/shell/e-sidebar.c b/shell/e-sidebar.c deleted file mode 100644 index 3942de727b..0000000000 --- a/shell/e-sidebar.c +++ /dev/null @@ -1,785 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-sidebar.h" - -#include "e-util/e-util.h" - -#include <gconf/gconf-client.h> - -typedef struct { - GtkWidget *button_widget; - GtkWidget *label; - GtkWidget *icon; - GtkWidget *hbox; - gchar *default_icon_name; - gint id; -} Button; - -struct _ESidebarPrivate { - ESidebarMode mode; - ESidebarMode toolbar_mode; - - gboolean show; - - GtkWidget *selection_widget; - GSList *buttons; - - guint style_changed_id; - - gboolean in_toggle; -}; - -enum { - BUTTON_SELECTED, - BUTTON_PRESSED, - NUM_SIGNALS -}; - -static guint signals[NUM_SIGNALS] = { 0 }; - -G_DEFINE_TYPE (ESidebar, e_sidebar, GTK_TYPE_CONTAINER) - -#define INTERNAL_MODE(sidebar) (sidebar->priv->mode == E_SIDEBAR_MODE_TOOLBAR ? sidebar->priv->toolbar_mode : sidebar->priv->mode) -#define H_PADDING 6 -#define V_PADDING 6 - -/* Utility functions. */ - -static Button * -button_new (GtkWidget *button_widget, - GtkWidget *label, - GtkWidget *icon, - GtkWidget *hbox, - gint id) -{ - Button *button = g_new (Button, 1); - const gchar *icon_name; - - button->button_widget = button_widget; - button->label = label; - button->icon = icon; - button->hbox = hbox; - button->id = id; - - gtk_image_get_icon_name (GTK_IMAGE (icon), &icon_name, NULL); - button->default_icon_name = g_strdup (icon_name); - - g_object_ref (button_widget); - g_object_ref (label); - g_object_ref (icon); - g_object_ref (hbox); - - return button; -} - -static void -button_free (Button *button) -{ - g_object_unref (button->button_widget); - g_object_unref (button->label); - g_object_unref (button->icon); - g_object_unref (button->hbox); - g_free (button->default_icon_name); - g_free (button); -} - -static void -update_buttons (ESidebar *sidebar, gint new_selected_id) -{ - GSList *p; - - sidebar->priv->in_toggle = TRUE; - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - - if (button->id == new_selected_id) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->button_widget), TRUE); - else - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->button_widget), FALSE); - } - - sidebar->priv->in_toggle = FALSE; -} - -/* Callbacks. */ - -static void -button_toggled_callback (GtkToggleButton *toggle_button, - ESidebar *sidebar) -{ - gint id = 0; - gboolean is_active = FALSE; - GSList *p; - - if (sidebar->priv->in_toggle) - return; - - sidebar->priv->in_toggle = TRUE; - - if (gtk_toggle_button_get_active (toggle_button)) - is_active = TRUE; - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - - if (button->button_widget != GTK_WIDGET (toggle_button)) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->button_widget), FALSE); - } else { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button->button_widget), TRUE); - id = button->id; - } - } - - sidebar->priv->in_toggle = FALSE; - - if (is_active) - g_signal_emit (sidebar, signals[BUTTON_SELECTED], 0, id); -} - -static gboolean -button_pressed_callback (GtkToggleButton *toggle_button, - GdkEventButton *event, - ESidebar *sidebar) -{ - gboolean return_val = FALSE; - GSList *p; - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - - if (button->button_widget == GTK_WIDGET (toggle_button)) - g_signal_emit (sidebar, signals [BUTTON_PRESSED], - 0, event, button->id, &return_val); - } - - return return_val; -} - -static gboolean -button_query_tooltip (GtkWidget *widget, - gint x, - gint y, - gboolean keyboard_mode, - GtkTooltip *tooltip, - ESidebar *sidebar) -{ - /* Show the tooltip only if the label is hidden */ - if (INTERNAL_MODE (sidebar) == E_SIDEBAR_MODE_ICON) { - gchar *tip; - - tip = g_object_get_data (G_OBJECT (widget), - "ESidebar:button-tooltip"); - if (tip) { - gtk_tooltip_set_text (tooltip, tip); - - return TRUE; - } - } - - return FALSE; -} - -/* Layout. */ - -static gint -layout_buttons (ESidebar *sidebar) -{ - GtkAllocation *allocation = & GTK_WIDGET (sidebar)->allocation; - ESidebarMode mode; - gboolean icons_only; - gint num_btns = g_slist_length (sidebar->priv->buttons), btns_per_row; - GSList **rows, *p; - Button *button; - gint row_number; - gint max_btn_width = 0, max_btn_height = 0; - gint row_last; - gint x, y; - gint i; - - y = allocation->y + allocation->height - V_PADDING - 1; - - if (num_btns == 0) - return y; - - mode = INTERNAL_MODE (sidebar); - icons_only = (mode == E_SIDEBAR_MODE_ICON); - - /* Figure out the max width and height */ - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - GtkRequisition requisition; - - button = p->data; - gtk_widget_size_request (GTK_WIDGET (button->button_widget), &requisition); - - max_btn_height = MAX (max_btn_height, requisition.height); - max_btn_width = MAX (max_btn_width, requisition.width); - } - - /* Figure out how many rows and columns we'll use. */ - btns_per_row = allocation->width / (max_btn_width + H_PADDING); - if (!icons_only) { - /* If using text buttons, we want to try to have a - * completely filled-in grid, but if we can't, we want - * the odd row to have just a single button. - */ - while (num_btns % btns_per_row > 1) - btns_per_row--; - } - - /* Assign buttons to rows */ - rows = g_new0 (GSList *, num_btns / btns_per_row + 1); - - if (!icons_only && num_btns % btns_per_row != 0) { - button = sidebar->priv->buttons->data; - rows [0] = g_slist_append (rows [0], button->button_widget); - - p = sidebar->priv->buttons->next; - row_number = p ? 1 : 0; - } else { - p = sidebar->priv->buttons; - row_number = 0; - } - - for (; p != NULL; p = p->next) { - button = p->data; - - if (g_slist_length (rows [row_number]) == btns_per_row) - row_number ++; - - rows [row_number] = g_slist_append (rows [row_number], button->button_widget); - } - - row_last = row_number; - - /* Layout the buttons. */ - for (i = row_last; i >= 0; i --) { - gint len, extra_width; - - y -= max_btn_height; - x = H_PADDING + allocation->x; - len = g_slist_length (rows[i]); - if (mode == E_SIDEBAR_MODE_TEXT || mode == E_SIDEBAR_MODE_BOTH) - extra_width = (allocation->width - (len * max_btn_width ) - (len * H_PADDING)) / len; - else - extra_width = 0; - for (p = rows [i]; p != NULL; p = p->next) { - GtkAllocation child_allocation; - - child_allocation.x = x; - child_allocation.y = y; - child_allocation.width = max_btn_width + extra_width; - child_allocation.height = max_btn_height; - - gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation); - - x += child_allocation.width + H_PADDING; - } - - y -= V_PADDING; - } - - for (i = 0; i <= row_last; i ++) - g_slist_free (rows [i]); - g_free (rows); - - return y; -} - -static void -do_layout (ESidebar *sidebar) -{ - GtkAllocation *allocation = & GTK_WIDGET (sidebar)->allocation; - GtkAllocation child_allocation; - gint y; - - if (sidebar->priv->show) - y = layout_buttons (sidebar); - else - y = allocation->y + allocation->height; - - /* Place the selection widget. */ - child_allocation.x = allocation->x; - child_allocation.y = allocation->y; - child_allocation.width = allocation->width; - child_allocation.height = y - allocation->y; - - gtk_widget_size_allocate (sidebar->priv->selection_widget, & child_allocation); -} - -/* GtkContainer methods. */ - -static void -impl_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - ESidebar *sidebar = E_SIDEBAR (container); - GSList *p; - - if (sidebar->priv->selection_widget != NULL) - (* callback) (sidebar->priv->selection_widget, callback_data); - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - GtkWidget *widget = ((Button *) p->data)->button_widget; - (* callback) (widget, callback_data); - } -} - -static void -impl_remove (GtkContainer *container, - GtkWidget *widget) -{ - ESidebar *sidebar = E_SIDEBAR (container); - GSList *p; - - if (widget == sidebar->priv->selection_widget) { - e_sidebar_set_selection_widget (sidebar, NULL); - return; - } - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - GtkWidget *button_widget = ((Button *) p->data)->button_widget; - - if (button_widget == widget) { - gtk_widget_unparent (button_widget); - sidebar->priv->buttons = g_slist_remove_link (sidebar->priv->buttons, p); - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - break; - } - } -} - -/* GtkWidget methods. */ - -static void -impl_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - ESidebar *sidebar = E_SIDEBAR (widget); - GSList *p; - - if (sidebar->priv->selection_widget == NULL) { - requisition->width = 2 * H_PADDING; - requisition->height = 2 * V_PADDING; - } else { - gtk_widget_size_request (sidebar->priv->selection_widget, requisition); - } - - if (!sidebar->priv->show) - return; - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - GtkRequisition button_requisition; - - gtk_widget_size_request (button->button_widget, &button_requisition); - - requisition->width = MAX (requisition->width, button_requisition.width + 2 * H_PADDING); - requisition->height += button_requisition.height + V_PADDING; - } -} - -static void -impl_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - widget->allocation = *allocation; - - do_layout (E_SIDEBAR (widget)); -} - -/* GObject methods. */ - -static void -impl_dispose (GObject *object) -{ - ESidebarPrivate *priv = E_SIDEBAR (object)->priv; - GConfClient *gconf_client = gconf_client_get_default (); - - g_slist_foreach (priv->buttons, (GFunc) button_free, NULL); - g_slist_free (priv->buttons); - priv->buttons = NULL; - - if (priv->style_changed_id) { - gconf_client_notify_remove (gconf_client, priv->style_changed_id); - priv->style_changed_id = 0; - } - - g_object_unref (gconf_client); - - (* G_OBJECT_CLASS (e_sidebar_parent_class)->dispose) (object); -} - -static gboolean -boolean_handled_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer dummy) -{ - gboolean handled; - - handled = g_value_get_boolean (handler_return); - g_value_set_boolean (return_accu, handled); - - return !handled; -} - -static void -impl_finalize (GObject *object) -{ - ESidebarPrivate *priv = E_SIDEBAR (object)->priv; - - g_free (priv); - - (* G_OBJECT_CLASS (e_sidebar_parent_class)->finalize) (object); -} - -/* Initialization. */ - -static void -e_sidebar_class_init (ESidebarClass *klass) -{ - GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - container_class->forall = impl_forall; - container_class->remove = impl_remove; - - widget_class->size_request = impl_size_request; - widget_class->size_allocate = impl_size_allocate; - - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; - - signals[BUTTON_SELECTED] - = g_signal_new ("button_selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (ESidebarClass, button_selected), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - signals[BUTTON_PRESSED] - = g_signal_new ("button_pressed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESidebarClass, button_pressed), - boolean_handled_accumulator, NULL, - e_marshal_NONE__POINTER_INT, - G_TYPE_BOOLEAN, 2, - G_TYPE_POINTER, G_TYPE_INT); -} - -static void -e_sidebar_init (ESidebar *sidebar) -{ - ESidebarPrivate *priv; - - GTK_WIDGET_SET_FLAGS (sidebar, GTK_NO_WINDOW); - - priv = g_new0 (ESidebarPrivate, 1); - sidebar->priv = priv; - - priv->mode = E_SIDEBAR_MODE_TEXT; -} - -GtkWidget * -e_sidebar_new (void) -{ - ESidebar *sidebar = g_object_new (e_sidebar_get_type (), NULL); - - return GTK_WIDGET (sidebar); -} - -void -e_sidebar_set_selection_widget (ESidebar *sidebar, GtkWidget *widget) -{ - if (sidebar->priv->selection_widget != NULL) - gtk_widget_unparent (sidebar->priv->selection_widget); - - sidebar->priv->selection_widget = widget; - - if (widget != NULL) - gtk_widget_set_parent (widget, GTK_WIDGET (sidebar)); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); -} - -void -e_sidebar_add_button (ESidebar *sidebar, - const gchar *label, - const gchar *tooltips, - const gchar *icon_name, - gint id) -{ - GtkWidget *button_widget; - GtkWidget *hbox; - GtkWidget *icon_widget; - GtkWidget *label_widget; - - button_widget = gtk_toggle_button_new (); - if (sidebar->priv->show) - gtk_widget_show (button_widget); - g_signal_connect (button_widget, "toggled", G_CALLBACK (button_toggled_callback), sidebar); - g_signal_connect (button_widget, "button_press_event", - G_CALLBACK (button_pressed_callback), sidebar); - - hbox = gtk_hbox_new (FALSE, 3); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 2); - gtk_widget_show (hbox); - - icon_widget = gtk_image_new_from_icon_name ( - icon_name, GTK_ICON_SIZE_BUTTON); - gtk_widget_show (icon_widget); - - label_widget = gtk_label_new (label); - gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5); - gtk_widget_show (label_widget); - - g_object_set_data_full (G_OBJECT (button_widget), - "ESidebar:button-tooltip", - g_strdup (tooltips), - g_free); - gtk_widget_set_has_tooltip (button_widget, TRUE); - g_signal_connect (button_widget, "query-tooltip", - G_CALLBACK (button_query_tooltip), sidebar); - - switch (INTERNAL_MODE (sidebar)) { - case E_SIDEBAR_MODE_TEXT: - gtk_box_pack_start (GTK_BOX (hbox), label_widget, TRUE, TRUE, 0); - break; - case E_SIDEBAR_MODE_ICON: - gtk_box_pack_start (GTK_BOX (hbox), icon_widget, TRUE, TRUE, 0); - break; - case E_SIDEBAR_MODE_BOTH: - default: - gtk_box_pack_start (GTK_BOX (hbox), icon_widget, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), label_widget, TRUE, TRUE, 0); - break; - } - - gtk_container_add (GTK_CONTAINER (button_widget), hbox); - - sidebar->priv->buttons = g_slist_append (sidebar->priv->buttons, button_new (button_widget, label_widget, icon_widget, hbox, id)); - gtk_widget_set_parent (button_widget, GTK_WIDGET (sidebar)); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); -} - -/** - * e_sidebar_change_button_icon - * @sidebar: an #ESidebar - * @icon_name: button icon name, or %NULL - * @button_id: component's button ID, for which change the icon. - * - * This will change icon in icon_widget of the button of known component. - * You cannot change icon as in a stack, only one default icon will be stored. - **/ -void -e_sidebar_change_button_icon (ESidebar *sidebar, const gchar *icon_name, gint button_id) -{ - GSList *p; - - g_return_if_fail (sidebar != NULL); - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - - if (button->id == button_id) { - if (!button->icon) - break; - - if (icon_name == NULL) - icon_name = button->default_icon_name; - - gtk_image_set_from_icon_name ( - GTK_IMAGE (button->icon), - icon_name, GTK_ICON_SIZE_BUTTON); - - break; - } - } -} - -void -e_sidebar_select_button (ESidebar *sidebar, gint id) -{ - update_buttons (sidebar, id); - - g_signal_emit (sidebar, signals[BUTTON_SELECTED], 0, id); -} - -ESidebarMode -e_sidebar_get_mode (ESidebar *sidebar) -{ - return sidebar->priv->mode; -} - -static GConfEnumStringPair toolbar_styles[] = { - { E_SIDEBAR_MODE_TEXT, "text" }, - { E_SIDEBAR_MODE_ICON, "icons" }, - { E_SIDEBAR_MODE_BOTH, "both" }, - { E_SIDEBAR_MODE_BOTH, "both-horiz" }, - { E_SIDEBAR_MODE_BOTH, "both_horiz" }, - { -1, NULL } -}; - -static void -set_mode_internal (ESidebar *sidebar, ESidebarMode mode ) -{ - GSList *p; - - if (mode == INTERNAL_MODE (sidebar)) - return; - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - - switch (mode) { - case E_SIDEBAR_MODE_TEXT: - gtk_container_remove (GTK_CONTAINER (button->hbox), button->icon); - if (INTERNAL_MODE (sidebar) == E_SIDEBAR_MODE_ICON) { - gtk_box_pack_start (GTK_BOX (button->hbox), button->label, TRUE, TRUE, 0); - gtk_widget_show (button->label); - } - break; - case E_SIDEBAR_MODE_ICON: - gtk_container_remove(GTK_CONTAINER (button->hbox), button->label); - if (INTERNAL_MODE (sidebar) == E_SIDEBAR_MODE_TEXT) { - gtk_box_pack_start (GTK_BOX (button->hbox), button->icon, TRUE, TRUE, 0); - gtk_widget_show (button->icon); - } else - gtk_container_child_set (GTK_CONTAINER (button->hbox), button->icon, - "expand", TRUE, - NULL); - break; - case E_SIDEBAR_MODE_BOTH: - if (INTERNAL_MODE (sidebar) == E_SIDEBAR_MODE_TEXT) { - gtk_container_remove (GTK_CONTAINER (button->hbox), button->label); - gtk_box_pack_start (GTK_BOX (button->hbox), button->icon, FALSE, TRUE, 0); - gtk_widget_show (button->icon); - } else { - gtk_container_child_set (GTK_CONTAINER (button->hbox), button->icon, - "expand", FALSE, - NULL); - } - - gtk_box_pack_start (GTK_BOX (button->hbox), button->label, TRUE, TRUE, 0); - gtk_widget_show (button->label); - break; - default: - break; - } - } -} - -static void -style_changed_notify (GConfClient *gconf, guint id, GConfEntry *entry, gpointer data) -{ - ESidebar *sidebar = data; - gchar *val; - gint mode; - - val = gconf_client_get_string (gconf, "/desktop/gnome/interface/toolbar_style", NULL); - if (val == NULL || !gconf_string_to_enum (toolbar_styles, val, &mode)) - mode = E_SIDEBAR_MODE_BOTH; - g_free(val); - - set_mode_internal (E_SIDEBAR (sidebar), mode); - sidebar->priv->toolbar_mode = mode; - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); -} - -void -e_sidebar_set_mode (ESidebar *sidebar, ESidebarMode mode) -{ - GConfClient *gconf_client = gconf_client_get_default (); - - if (sidebar->priv->mode == mode) - return; - - if (sidebar->priv->mode == E_SIDEBAR_MODE_TOOLBAR) { - if (sidebar->priv->style_changed_id) { - gconf_client_notify_remove (gconf_client, sidebar->priv->style_changed_id); - sidebar->priv->style_changed_id = 0; - } - } - - if (mode != E_SIDEBAR_MODE_TOOLBAR) { - set_mode_internal (sidebar, mode); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - } else { - /* This is a little bit tricky, toolbar mode is more - * of a meta-mode where the actual mode is dictated by - * the gnome toolbar setting, so that is why we have - * the is_toolbar_mode bool - it tracks the toolbar - * mode while the mode member is the actual look and - * feel */ - sidebar->priv->style_changed_id = gconf_client_notify_add (gconf_client, - "/desktop/gnome/interface/toolbar_style", - style_changed_notify, sidebar, NULL, NULL); - style_changed_notify (gconf_client, 0, NULL, sidebar); - } - - g_object_unref (gconf_client); - - sidebar->priv->mode = mode; -} - -void -e_sidebar_set_show_buttons (ESidebar *sidebar, gboolean show) -{ - GSList *p; - - if (sidebar->priv->show == show) - return; - - for (p = sidebar->priv->buttons; p != NULL; p = p->next) { - Button *button = p->data; - - if (show) - gtk_widget_show (button->button_widget); - else - gtk_widget_hide (button->button_widget); - } - - sidebar->priv->show = show; - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); -} - -gboolean -e_sidebar_get_show_buttons (ESidebar *sidebar) -{ - return sidebar->priv->show; -} diff --git a/shell/e-sidebar.h b/shell/e-sidebar.h deleted file mode 100644 index 9e450f8e7b..0000000000 --- a/shell/e-sidebar.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_SIDEBAR_H_ -#define _E_SIDEBAR_H_ - -#include <gtk/gtk.h> - -#define E_TYPE_SIDEBAR (e_sidebar_get_type ()) -#define E_SIDEBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SIDEBAR, ESidebar)) -#define E_SIDEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SIDEBAR, ESidebarClass)) -#define E_IS_SIDEBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SIDEBAR)) -#define E_IS_SIDEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SIDEBAR)) - -typedef struct _ESidebar ESidebar; -typedef struct _ESidebarPrivate ESidebarPrivate; -typedef struct _ESidebarClass ESidebarClass; - -typedef enum { - E_SIDEBAR_MODE_TEXT, - E_SIDEBAR_MODE_ICON, - E_SIDEBAR_MODE_BOTH, - E_SIDEBAR_MODE_TOOLBAR -} ESidebarMode; - -struct _ESidebar { - GtkContainer parent; - - ESidebarPrivate *priv; -}; - -struct _ESidebarClass { - GtkContainerClass parent_class; - - /* signals */ - void (* button_selected) (ESidebar *sidebar, gint id); - void (* button_pressed) (ESidebar *sidebar, GdkEventButton *event, gint id); -}; - -GType e_sidebar_get_type (void); -GtkWidget *e_sidebar_new (void); - -void e_sidebar_set_selection_widget (ESidebar *sidebar, - GtkWidget *widget); - -void e_sidebar_add_button (ESidebar *sidebar, - const gchar *label, - const gchar *tooltips, - const gchar *icon_name, - gint id); - -void e_sidebar_select_button (ESidebar *sidebar, - gint id); - -void e_sidebar_change_button_icon (ESidebar *sidebar, - const gchar *icon_name, - gint button_id); - -ESidebarMode e_sidebar_get_mode (ESidebar *sidebar); -void e_sidebar_set_mode (ESidebar *sidebar, ESidebarMode mode); - -void e_sidebar_set_show_buttons (ESidebar *sidebar, gboolean show); -gboolean e_sidebar_get_show_buttons (ESidebar *sidebar); - -#endif /* _E_SIDEBAR_H_ */ diff --git a/shell/e-user-creatable-items-handler.c b/shell/e-user-creatable-items-handler.c deleted file mode 100644 index 6fef2b7309..0000000000 --- a/shell/e-user-creatable-items-handler.c +++ /dev/null @@ -1,907 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-user-creatable-items-handler.h" -#include <e-util/e-icon-factory.h> -#include "Evolution.h" - -#include "e-util/e-corba-utils.h" -#include "misc/e-combo-button.h" - -#include <bonobo/bonobo-ui-util.h> -#include <bonobo/bonobo-exception.h> -#include <bonobo/bonobo-control.h> - -#include <gtk/gtk.h> -#include <glib/gi18n-lib.h> - -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -#include <gconf/gconf-client.h> - -struct _Component { - gchar *id, *alias; - GNOME_Evolution_Component component; - GNOME_Evolution_CreatableItemTypeList *type_list; -}; -typedef struct _Component Component; - -/* Representation of a single menu item. */ -struct _MenuItem { - const gchar *label; - gchar shortcut; - gchar *verb; - gchar *tooltip; - gchar *component; - GdkPixbuf *icon; - GdkPixbuf *icon_toolbar; -}; -typedef struct _MenuItem MenuItem; - -struct _EUserCreatableItemsHandlerPrivate { - /* This component's alias */ - gchar *this_component; - - /* For creating items on the view */ - EUserCreatableItemsHandlerCreate create_local; - gpointer create_data; - - /* The components that register user creatable items. */ - GSList *components; /* Component */ - - /* The "New ..." menu items. */ - GSList *objects; /* MenuItem */ - GSList *folders; /* MenuItem */ - - /* The default item (the mailer's "message" item). To be used when the - component in the view we are in doesn't provide a default user - creatable type. This pointer always points to one of the menu items - in ->objects. */ - const MenuItem *fallback_menu_item; - const MenuItem *default_menu_item; - - gchar *menu_xml; - GtkWidget *new_button, *new_menu; - BonoboControl *new_control; - GtkAccelGroup *accel_group; -}; - -enum { - PROP_THIS_COMPONENT = 1, - LAST_PROP -}; - -G_DEFINE_TYPE (EUserCreatableItemsHandler, e_user_creatable_items_handler, G_TYPE_OBJECT) - -/* Component struct handling. */ - -static Component * -component_new (const gchar *id, - const gchar *component_alias, - GNOME_Evolution_Component component) -{ - CORBA_Environment ev; - Component *new; - - CORBA_exception_init (&ev); - - new = g_new (Component, 1); - new->id = g_strdup (id); - new->alias = g_strdup (component_alias); - - new->type_list = GNOME_Evolution_Component__get_userCreatableItems (component, &ev); - if (BONOBO_EX (&ev)) - new->type_list = NULL; - - new->component = component; - Bonobo_Unknown_ref (new->component, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - new->type_list = NULL; - - CORBA_exception_free (&ev); - - return new; -} - -static void -component_free (Component *component) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - Bonobo_Unknown_unref (component->component, &ev); - - g_free (component->id); - g_free (component->alias); - - if (component->type_list != NULL) - CORBA_free (component->type_list); - - CORBA_exception_free (&ev); - - g_free (component); -} - -static const gchar *component_query = - "repo_ids.has ('IDL:GNOME/Evolution/Component:" BASE_VERSION "')"; - -static void -get_components_from_bonobo (EUserCreatableItemsHandler *handler) -{ - Bonobo_ServerInfoList *info_list; - Bonobo_ActivationProperty *property; - CORBA_Environment ev; - const gchar *alias; - gchar *iid; - GNOME_Evolution_Component corba_component; - Component *component; - gint i; - - CORBA_exception_init (&ev); - info_list = bonobo_activation_query (component_query, NULL, &ev); - if (BONOBO_EX (&ev)) { - gchar *ex_text = bonobo_exception_get_text (&ev); - g_warning ("Cannot query for components: %s\n", ex_text); - g_free (ex_text); - CORBA_exception_free (&ev); - return; - } - - for (i = 0; i < info_list->_length; i++) { - iid = info_list->_buffer[i].iid; - corba_component = bonobo_activation_activate_from_id (iid, Bonobo_ACTIVATION_FLAG_EXISTING_ONLY, NULL, &ev); - if (BONOBO_EX (&ev)) { - CORBA_exception_free (&ev); - continue; - } - - property = bonobo_server_info_prop_find (&info_list->_buffer[i], - "evolution:component_alias"); - alias = property ? property->v._u.value_string : "unknown"; - - component = component_new (iid, alias, corba_component); - handler->priv->components = g_slist_prepend (handler->priv->components, component); - } - - CORBA_free (info_list); -} - -/* Helper functions. */ - -static gboolean -item_is_default (const MenuItem *item, - const gchar *component) -{ - if (component == NULL) - return FALSE; - - if (strcmp (item->component, component) == 0) - return TRUE; - else - return FALSE; -} - -static gchar * -create_verb (EUserCreatableItemsHandler *handler, gint component_num, const gchar *comp, const gchar *type_id) -{ - return g_strdup_printf ("EUserCreatableItemsHandler-%s:%d:%s", comp, component_num, type_id); -} - -/* Setting up menu items for the "File -> New" submenu and the "New" toolbar - button. */ - -static void -ensure_menu_items (EUserCreatableItemsHandler *handler) -{ - EUserCreatableItemsHandlerPrivate *priv; - GSList *objects, *folders; - GSList *p; - gint component_num; - const gchar *default_verb; - - priv = handler->priv; - if (priv->objects != NULL) - return; - - objects = folders = NULL; - component_num = 0; - default_verb = NULL; - for (p = priv->components; p != NULL; p = p->next) { - const Component *component; - gint i; - - component = (const Component *) p->data; - if (component->type_list != NULL) { - for (i = 0; i < component->type_list->_length; i ++) { - const GNOME_Evolution_CreatableItemType *corba_item; - MenuItem *item; - - corba_item = (const GNOME_Evolution_CreatableItemType *) component->type_list->_buffer + i; - - item = g_new (MenuItem, 1); - item->label = corba_item->menuDescription; - item->shortcut = corba_item->menuShortcut; - item->verb = create_verb (handler, component_num, component->alias, corba_item->id); - item->tooltip = corba_item->tooltip; - item->component = g_strdup (component->alias); - - if (strcmp (item->component, "mail") == 0 - && strcmp (corba_item->id, "message") == 0) - default_verb = item->verb; - - if (corba_item->iconName == NULL || *corba_item->iconName == '\0') { - item->icon = NULL; - item->icon_toolbar = NULL; - } else { - item->icon = e_icon_factory_get_icon (corba_item->iconName, GTK_ICON_SIZE_MENU); - if (item_is_default (item, component->alias)) - item->icon_toolbar = e_icon_factory_get_icon (corba_item->iconName, GTK_ICON_SIZE_LARGE_TOOLBAR); - else - item->icon_toolbar = NULL; - } - - if (corba_item->type == GNOME_Evolution_CREATABLE_OBJECT) - objects = g_slist_prepend (objects, item); - else - folders = g_slist_prepend (folders, item); - } - } - - component_num ++; - } - - priv->objects = g_slist_reverse (objects); - priv->folders = g_slist_reverse (folders); - - priv->fallback_menu_item = NULL; - if (default_verb != NULL) { - for (p = priv->objects; p != NULL; p = p->next) { - const MenuItem *item; - - item = (const MenuItem *) p->data; - if (strcmp (item->verb, default_verb) == 0) - priv->fallback_menu_item = item; - } - } -} - -static void -free_menu_items (GSList *menu_items) -{ - GSList *p; - - if (menu_items == NULL) - return; - - for (p = menu_items; p != NULL; p = p->next) { - MenuItem *item; - - item = (MenuItem *) p->data; - g_free (item->verb); - - if (item->icon != NULL) - g_object_unref (item->icon); - - if (item->icon_toolbar != NULL) - g_object_unref (item->icon_toolbar); - - g_free (item->component); - g_free (item); - } - - g_slist_free (menu_items); -} - -static const MenuItem * -get_default_action_for_view (EUserCreatableItemsHandler *handler) -{ - EUserCreatableItemsHandlerPrivate *priv; - const GSList *p; - - priv = handler->priv; - - for (p = priv->objects; p != NULL; p = p->next) { - const MenuItem *item; - - item = (const MenuItem *) p->data; - if (item_is_default (item, priv->this_component)) - return item; - } - - return priv->fallback_menu_item; -} - -/* Verb handling. */ - -static void -execute_verb (EUserCreatableItemsHandler *handler, - const gchar *verb_name) -{ - EUserCreatableItemsHandlerPrivate *priv; - const Component *component; - gint component_number; - const gchar *p; - const gchar *id; - GSList *component_list_item; - gint i; - - priv = handler->priv; - - p = strchr (verb_name, ':'); - g_return_if_fail (p != NULL); - component_number = atoi (p + 1); - - p = strchr (p + 1, ':'); - g_return_if_fail (p != NULL); - id = p + 1; - - component_list_item = g_slist_nth (priv->components, component_number); - g_return_if_fail (component_list_item != NULL); - - component = (const Component *) component_list_item->data; - - if (component->type_list == NULL) - return; - - /* TODO: why do we actually iterate this? Is it just to check we have it in the menu? The - search isn't used otherwise */ - for (i = 0; i < component->type_list->_length; i ++) { - if (strcmp (component->type_list->_buffer[i].id, id) == 0) { - if (priv->create_local && priv->this_component && strcmp(priv->this_component, component->alias) == 0) { - priv->create_local(handler, id, priv->create_data); - } else { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - GNOME_Evolution_Component_requestCreateItem (component->component, id, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - g_warning ("Error in requestCreateItem -- %s", BONOBO_EX_REPOID (&ev)); - - CORBA_exception_free (&ev); - } - return; - } - } -} - -static void -verb_fn (BonoboUIComponent *ui_component, - gpointer data, - const gchar *verb_name) -{ - EUserCreatableItemsHandler *handler= - E_USER_CREATABLE_ITEMS_HANDLER (data); - - execute_verb (handler, verb_name); -} - -static void -add_verbs (EUserCreatableItemsHandler *handler, - BonoboUIComponent *ui_component) -{ - EUserCreatableItemsHandlerPrivate *priv; - gint component_num; - GSList *p; - - priv = handler->priv; - - component_num = 0; - for (p = priv->components; p != NULL; p = p->next) { - const Component *component; - gint i; - - component = (const Component *) p->data; - - if (component->type_list != NULL) { - for (i = 0; i < component->type_list->_length; i ++) { - gchar *verb_name; - - verb_name = create_verb (handler, - component_num, - component->alias, - component->type_list->_buffer[i].id); - - bonobo_ui_component_add_verb (ui_component, verb_name, verb_fn, handler); - - g_free (verb_name); - } - } - - component_num ++; - } -} - -/* Generic menu construction code */ - -static gint -item_types_sort_func (gconstpointer a, - gconstpointer b) -{ - const MenuItem *item_a; - const MenuItem *item_b; - const gchar *p1, *p2; - - item_a = (const MenuItem *) a; - item_b = (const MenuItem *) b; - - p1 = item_a->label; - p2 = item_b->label; - - while (*p1 != '\0' && *p2 != '\0') { - if (*p1 == '_') { - p1 ++; - continue; - } - - if (*p2 == '_') { - p2 ++; - continue; - } - - if (toupper ((gint) *p1) < toupper ((gint) *p2)) - return -1; - else if (toupper ((gint) *p1) > toupper ((gint) *p2)) - return +1; - - p1 ++, p2 ++; - } - - if (*p1 == '\0') { - if (*p2 == '\0') - return 0; - else - return -1; - } else { - return +1; - } -} - -typedef void (*EUserCreatableItemsHandlerMenuItemFunc) (EUserCreatableItemsHandler *, gpointer, MenuItem *, gboolean); -typedef void (*EUserCreatableItemsHandlerSeparatorFunc) (EUserCreatableItemsHandler *, gpointer, gint); - -static void -construct_menu (EUserCreatableItemsHandler *handler, gpointer menu, - EUserCreatableItemsHandlerMenuItemFunc menu_item_func, - EUserCreatableItemsHandlerSeparatorFunc separator_func) -{ - EUserCreatableItemsHandlerPrivate *priv; - MenuItem *item; - GSList *p, *items; - gboolean first = TRUE; - - priv = handler->priv; - - /* First add the current component's creatable objects */ - for (p = priv->objects; p != NULL; p = p->next) { - item = p->data; - if (item_is_default (item, priv->this_component)) { - menu_item_func (handler, menu, item, first); - first = FALSE; - } - } - - /* Then its creatable folders */ - for (p = priv->folders; p != NULL; p = p->next) { - item = p->data; - if (item_is_default (item, priv->this_component)) - menu_item_func (handler, menu, item, FALSE); - } - - /* Then a separator */ - separator_func (handler, menu, 1); - - /* Then the objects from other components. */ - items = NULL; - for (p = priv->objects; p != NULL; p = p->next) { - item = p->data; - if (! item_is_default (item, priv->this_component)) - items = g_slist_prepend (items, item); - } - - items = g_slist_sort (items, item_types_sort_func); - for (p = items; p != NULL; p = p->next) - menu_item_func (handler, menu, p->data, FALSE); - g_slist_free (items); - - /* Another separator */ - separator_func (handler, menu, 2); - - /* And finally the folders from other components */ - items = NULL; - for (p = priv->folders; p != NULL; p = p->next) { - item = p->data; - if (! item_is_default (item, priv->this_component)) - items = g_slist_prepend (items, item); - } - - items = g_slist_sort (items, item_types_sort_func); - for (p = items; p != NULL; p = p->next) - menu_item_func (handler, menu, p->data, FALSE); - g_slist_free (items); -} - -/* The XML description for "File -> New". */ - -static void -xml_menu_item_func (EUserCreatableItemsHandler *handler, gpointer menu, - MenuItem *item, gboolean first) -{ - GString *xml = menu; - gchar *encoded_label; - gchar *encoded_tooltip; - - encoded_label = bonobo_ui_util_encode_str (item->label); - g_string_append_printf (xml, "<menuitem name=\"New:%s\" verb=\"%s\" label=\"%s\"", - item->verb, item->verb, encoded_label); - - if (first) - g_string_append_printf (xml, " accel=\"*Control*N\""); - else if (item->shortcut != '\0') - g_string_append_printf (xml, " accel=\"*Control**Shift*%c\"", item->shortcut); - - if (item->icon != NULL) { - gchar *icon_xml; - - icon_xml = bonobo_ui_util_pixbuf_to_xml (item->icon); - g_string_append_printf (xml, " pixtype=\"pixbuf\" pixname=\"%s\"", icon_xml); - g_free (icon_xml); - } - - encoded_tooltip = bonobo_ui_util_encode_str (item->tooltip); - g_string_append_printf (xml, " tip=\"%s\"", encoded_tooltip); - - g_string_append (xml, "/> "); - - g_free (encoded_label); - g_free (encoded_tooltip); -} - -static void -xml_separator_func (EUserCreatableItemsHandler *handler, gpointer menu, gint nth) -{ - GString *xml = menu; - - g_string_append_printf (xml, "<separator f=\"\" name=\"EUserCreatableItemsHandlerSeparator%d\"/>", nth); -} - -static void -create_menu_xml (EUserCreatableItemsHandler *handler) -{ - GString *xml; - - xml = g_string_new ("<placeholder name=\"NewMenu\">"); - construct_menu (handler, xml, xml_menu_item_func, xml_separator_func); - g_string_append (xml, "</placeholder>"); - - handler->priv->menu_xml = xml->str; - g_string_free (xml, FALSE); -} - -/* The GtkMenu for the toolbar button. */ - -static void -menuitem_activate (GtkMenuItem *item, gpointer data) -{ - EUserCreatableItemsHandler *handler = data; - const gchar *verb; - - verb = g_object_get_data (G_OBJECT (item), "EUserCreatableItemsHandler:verb"); - execute_verb (handler, verb); -} - -static void -default_activate (EComboButton *combo_button, gpointer data) -{ - EUserCreatableItemsHandler *handler = data; - - execute_verb (handler, handler->priv->default_menu_item->verb); -} - -static void -gtk_menu_item_func (EUserCreatableItemsHandler *handler, gpointer menu, - MenuItem *item, gboolean first) -{ - GtkWidget *menuitem, *icon; - - menuitem = gtk_image_menu_item_new_with_mnemonic (item->label); - - if (item->icon) { - icon = gtk_image_new_from_pixbuf (item->icon); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), - icon); - } - - if (first) { - gtk_widget_add_accelerator (menuitem, "activate", - handler->priv->accel_group, - 'n', GDK_CONTROL_MASK, - GTK_ACCEL_VISIBLE); - } else if (item->shortcut != '\0') { - gtk_widget_add_accelerator (menuitem, "activate", - handler->priv->accel_group, - item->shortcut, - GDK_CONTROL_MASK | GDK_SHIFT_MASK, - GTK_ACCEL_VISIBLE); - } - - g_object_set_data (G_OBJECT (menuitem), "EUserCreatableItemsHandler:verb", item->verb); - g_signal_connect (menuitem, "activate", - G_CALLBACK (menuitem_activate), handler); - - gtk_menu_shell_append (menu, menuitem); -} - -static void -gtk_separator_func (EUserCreatableItemsHandler *handler, gpointer menu, gint nth) -{ - gtk_menu_shell_append (menu, gtk_separator_menu_item_new ()); -} - -static void -set_combo_button_style (EComboButton *button, const gchar *style, GdkPixbuf *icon) -{ - if (!g_ascii_strcasecmp (style,"both-horiz")) { - e_combo_button_pack_hbox (button); - e_combo_button_set_label (button, _("New")); - e_combo_button_set_icon (button, icon); - } - else if (!g_ascii_strcasecmp (style,"icons")) { - e_combo_button_pack_hbox (button); - e_combo_button_set_icon (button, icon); - e_combo_button_set_label (button, ""); - } - else if (!g_ascii_strcasecmp(style,"text")) { - e_combo_button_pack_hbox (button); - e_combo_button_set_label (button, _("New")); - e_combo_button_set_icon (button, NULL); - } else { /* Default to both */ - e_combo_button_pack_vbox (button); - e_combo_button_set_icon (button, icon); - e_combo_button_set_label (button, _("New")); - } -} - -static void -new_button_change (GConfClient *gconf, - guint connection_id, - GConfEntry *entry, - EUserCreatableItemsHandler *handler) -{ - EUserCreatableItemsHandlerPrivate *priv; - gchar *val; - - priv = handler->priv; - val = gconf_client_get_string (gconf, "/desktop/gnome/interface/toolbar_style", NULL); - - set_combo_button_style (E_COMBO_BUTTON (priv->new_button), - val, priv->default_menu_item->icon_toolbar ? priv->default_menu_item->icon_toolbar : priv->default_menu_item->icon); - - g_free (val); - gtk_widget_show (priv->new_button); -} - -static void -setup_toolbar_button (EUserCreatableItemsHandler *handler) -{ - EUserCreatableItemsHandlerPrivate *priv; - GConfClient *gconf = gconf_client_get_default (); - gchar *val; - - priv = handler->priv; - val = gconf_client_get_string (gconf, "/desktop/gnome/interface/toolbar_style", NULL); - - priv->new_button = e_combo_button_new (); - priv->new_menu = gtk_menu_new (); - priv->accel_group = gtk_accel_group_new (); - construct_menu (handler, priv->new_menu, - gtk_menu_item_func, gtk_separator_func); - gtk_widget_show_all (priv->new_menu); - e_combo_button_set_menu (E_COMBO_BUTTON (priv->new_button), - GTK_MENU (priv->new_menu)); - - g_signal_connect (priv->new_button, "activate_default", - G_CALLBACK (default_activate), handler); - - priv->new_control = bonobo_control_new (priv->new_button); - - priv->default_menu_item = get_default_action_for_view (handler); - if (!priv->default_menu_item) { - gtk_widget_set_sensitive (priv->new_button, FALSE); - g_object_unref (gconf); - return; - } - - gtk_widget_set_sensitive (priv->new_button, TRUE); - - set_combo_button_style (E_COMBO_BUTTON (priv->new_button), - val, priv->default_menu_item->icon_toolbar ? priv->default_menu_item->icon_toolbar : priv->default_menu_item->icon); - - gconf_client_notify_add(gconf,"/desktop/gnome/interface/toolbar_style", - (GConfClientNotifyFunc)new_button_change, handler, NULL, NULL); - - gtk_widget_set_tooltip_text (priv->new_button, - priv->default_menu_item->tooltip); - gtk_widget_show (priv->new_button); - - g_free (val); - g_object_unref (gconf); -} - -/* GObject methods. */ - -static void -impl_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - EUserCreatableItemsHandler *handler = - E_USER_CREATABLE_ITEMS_HANDLER (object); - - switch (prop_id) { - case PROP_THIS_COMPONENT: - handler->priv->this_component = g_value_dup_string (value); - - get_components_from_bonobo (handler); - ensure_menu_items (handler); - break; - default: - break; - } -} - -static void -impl_dispose (GObject *object) -{ - EUserCreatableItemsHandler *handler; - EUserCreatableItemsHandlerPrivate *priv; - GSList *p; - - handler = E_USER_CREATABLE_ITEMS_HANDLER (object); - priv = handler->priv; - - for (p = priv->components; p != NULL; p = p->next) - component_free ((Component *) p->data); - - g_slist_free (priv->components); - priv->components = NULL; - - if (priv->new_control) { - bonobo_object_unref (priv->new_control); - priv->new_control = NULL; - } - - if (priv->accel_group) { - g_object_unref (priv->accel_group); - priv->accel_group = NULL; - } - - (* G_OBJECT_CLASS (e_user_creatable_items_handler_parent_class)->dispose) (object); -} - -static void -impl_finalize (GObject *object) -{ - EUserCreatableItemsHandler *handler; - EUserCreatableItemsHandlerPrivate *priv; - - handler = E_USER_CREATABLE_ITEMS_HANDLER (object); - priv = handler->priv; - - g_free (priv->this_component); - - free_menu_items (priv->objects); - free_menu_items (priv->folders); - - g_free (priv->menu_xml); - - g_free (priv); - - (* G_OBJECT_CLASS (e_user_creatable_items_handler_parent_class)->finalize) (object); -} - -static void -e_user_creatable_items_handler_class_init (EUserCreatableItemsHandlerClass *klass) -{ - GObjectClass *object_class; - - bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; - object_class->set_property = impl_set_property; - - g_object_class_install_property ( - object_class, PROP_THIS_COMPONENT, - g_param_spec_string ("this_component", "Component alias", - "The component_alias of this component", - NULL, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -e_user_creatable_items_handler_init (EUserCreatableItemsHandler *handler) -{ - EUserCreatableItemsHandlerPrivate *priv; - - priv = g_new0 (EUserCreatableItemsHandlerPrivate, 1); - - handler->priv = priv; -} - -EUserCreatableItemsHandler * -e_user_creatable_items_handler_new (const gchar *component_alias, - EUserCreatableItemsHandlerCreate create_local, gpointer data) -{ - EUserCreatableItemsHandler *handler; - - handler = g_object_new (e_user_creatable_items_handler_get_type (), - "this_component", component_alias, - NULL); - handler->priv->create_local = create_local; - handler->priv->create_data = data; - - return handler; -} - -/** - * e_user_creatable_items_handler_activate: - * @handler: the #EUserCreatableItemsHandler - * @ui_component: the #BonoboUIComponent to attach to - * - * Set up the menus and toolbar items for @ui_component. - **/ -void -e_user_creatable_items_handler_activate (EUserCreatableItemsHandler *handler, - BonoboUIComponent *ui_component) -{ - EUserCreatableItemsHandlerPrivate *priv; - - g_return_if_fail (E_IS_USER_CREATABLE_ITEMS_HANDLER (handler)); - g_return_if_fail (BONOBO_IS_UI_COMPONENT (ui_component)); - - priv = handler->priv; - - if (!priv->menu_xml) { - create_menu_xml (handler); - setup_toolbar_button (handler); - add_verbs (handler, ui_component); - } - - bonobo_ui_component_set (ui_component, "/menu/File/New", - priv->menu_xml, NULL); - - bonobo_ui_component_object_set (ui_component, - "/Toolbar/NewComboButton", - BONOBO_OBJREF (priv->new_control), - NULL); -} diff --git a/shell/e-user-creatable-items-handler.h b/shell/e-user-creatable-items-handler.h deleted file mode 100644 index cb978bdb37..0000000000 --- a/shell/e-user-creatable-items-handler.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_USER_CREATABLE_ITEMS_HANDLER_H_ -#define _E_USER_CREATABLE_ITEMS_HANDLER_H_ - -#include <glib-object.h> -#include <bonobo/bonobo-ui-component.h> -#include <bonobo/bonobo-window.h> - -G_BEGIN_DECLS - -#define E_TYPE_USER_CREATABLE_ITEMS_HANDLER (e_user_creatable_items_handler_get_type ()) -#define E_USER_CREATABLE_ITEMS_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_USER_CREATABLE_ITEMS_HANDLER, EUserCreatableItemsHandler)) -#define E_USER_CREATABLE_ITEMS_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_USER_CREATABLE_ITEMS_HANDLER, EUserCreatableItemsHandlerClass)) -#define E_IS_USER_CREATABLE_ITEMS_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_USER_CREATABLE_ITEMS_HANDLER)) -#define E_IS_USER_CREATABLE_ITEMS_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_USER_CREATABLE_ITEMS_HANDLER)) - -typedef struct _EUserCreatableItemsHandler EUserCreatableItemsHandler; -typedef struct _EUserCreatableItemsHandlerPrivate EUserCreatableItemsHandlerPrivate; -typedef struct _EUserCreatableItemsHandlerClass EUserCreatableItemsHandlerClass; - -typedef void (*EUserCreatableItemsHandlerCreate)(EUserCreatableItemsHandler *handler, const gchar *item_type_name, gpointer data); - -struct _EUserCreatableItemsHandler { - GObject parent; - - EUserCreatableItemsHandlerPrivate *priv; -}; - -struct _EUserCreatableItemsHandlerClass { - GObjectClass parent_class; -}; - -GType e_user_creatable_items_handler_get_type (void); -EUserCreatableItemsHandler *e_user_creatable_items_handler_new (const gchar *component_alias, - EUserCreatableItemsHandlerCreate create_local, gpointer data); - -void e_user_creatable_items_handler_activate (EUserCreatableItemsHandler *handler, - BonoboUIComponent *ui_component); - -G_END_DECLS - -#endif /* _E_USER_CREATABLE_ITEMS_HANDLER_H_ */ diff --git a/shell/es-event.c b/shell/es-event.c index 5740d585c7..c647827586 100644 --- a/shell/es-event.c +++ b/shell/es-event.c @@ -91,11 +91,10 @@ es_event_get_type(void) /** * es_event_peek: - * @void: * * Get the singular instance of the shell event handler. * - * Return value: + * Return: the shell event handler **/ ESEvent *es_event_peek(void) { @@ -112,6 +111,14 @@ ESEvent *es_event_peek(void) return es_event; } +ESEventTargetShell * +es_event_target_new (ESEvent *eme) +{ + return e_event_target_new ( + &eme->event, ES_EVENT_TARGET_SHELL, + sizeof (ESEventTargetShell)); +} + ESEventTargetState * es_event_target_new_state(ESEvent *eme, gint state) { @@ -130,16 +137,6 @@ es_event_target_new_state(ESEvent *eme, gint state) return t; } -ESEventTargetShell * -es_event_target_new_shell(ESEvent *eme, EShell *shell) -{ - ESEventTargetShell *t = e_event_target_new(&eme->event, ES_EVENT_TARGET_SHELL, sizeof(*t)); - - t->shell = shell; - - return t; -} - ESEventTargetUpgrade * es_event_target_new_upgrade(ESEvent *eme, gint major, gint minor, gint revision) { diff --git a/shell/es-event.h b/shell/es-event.h index b422151a56..7bb9fcd781 100644 --- a/shell/es-event.h +++ b/shell/es-event.h @@ -30,8 +30,6 @@ G_BEGIN_DECLS -struct _EShell; /* Avoid including "e-shell.h" */ - typedef struct _ESEvent ESEvent; typedef struct _ESEventClass ESEventClass; @@ -56,8 +54,6 @@ typedef struct _ESEventTargetComponent ESEventTargetComponent; struct _ESEventTargetShell { EEventTarget target; - - struct _EShell *shell; }; struct _ESEventTargetState { @@ -97,8 +93,8 @@ GType es_event_get_type(void); ESEvent *es_event_peek(void); +ESEventTargetShell *es_event_target_new(ESEvent *eme); ESEventTargetState *es_event_target_new_state(ESEvent *emp, gint state); -ESEventTargetShell *es_event_target_new_shell(ESEvent *eme, struct _EShell *shell); ESEventTargetUpgrade *es_event_target_new_upgrade(ESEvent *emp, gint major, gint minor, gint revision); ESEventTargetComponent *es_event_target_new_component(ESEvent *eme, const gchar *id); diff --git a/shell/es-menu.c b/shell/es-menu.c deleted file mode 100644 index d272d613be..0000000000 --- a/shell/es-menu.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdlib.h> - -#include <glib.h> - -#include "es-menu.h" - -static GObjectClass *esm_parent; - -static void -esm_init(GObject *o) -{ - /*ESMenu *esm = (ESMenu *)o; */ -} - -static void -esm_finalise(GObject *o) -{ - ((GObjectClass *)esm_parent)->finalize(o); -} - -static void -esm_target_free(EMenu *ep, EMenuTarget *t) -{ - switch (t->type) { - case ES_MENU_TARGET_SHELL: { - ESMenuTargetShell *s = (ESMenuTargetShell *)t; - - s = s; - break; } - } - - ((EMenuClass *)esm_parent)->target_free(ep, t); -} - -static void -esm_class_init(GObjectClass *klass) -{ - klass->finalize = esm_finalise; - ((EMenuClass *)klass)->target_free = esm_target_free; -} - -GType -es_menu_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(ESMenuClass), - NULL, NULL, - (GClassInitFunc)esm_class_init, - NULL, NULL, - sizeof(ESMenu), 0, - (GInstanceInitFunc)esm_init - }; - esm_parent = g_type_class_ref(e_menu_get_type()); - type = g_type_register_static(e_menu_get_type(), "ESMenu", &info, 0); - } - - return type; -} - -ESMenu *es_menu_new(const gchar *menuid) -{ - ESMenu *esm = g_object_new(es_menu_get_type(), NULL); - - e_menu_construct(&esm->menu, menuid); - - return esm; -} - -/** - * es_menu_target_new_shell: - * @esm: - * @flags: - * - * Create a new menu target for the shell. - * - * Return value: - **/ -ESMenuTargetShell * -es_menu_target_new_shell(ESMenu *esm, guint32 flags) -{ - ESMenuTargetShell *t = e_menu_target_new(&esm->menu, ES_MENU_TARGET_SHELL, sizeof(*t)); - guint32 mask = ~0; - - mask &= ~ flags; - t->target.mask = mask; - - return t; -} - -/* ********************************************************************** */ - -static gpointer esph_parent_class; -#define esph ((ESMenuHook *)eph) - -static const EMenuHookTargetMask esph_shell_masks[] = { - { "online", ES_MENU_SHELL_ONLINE }, - { "offline", ES_MENU_SHELL_OFFLINE }, - { NULL } -}; - -static const EMenuHookTargetMap esph_targets[] = { - { "shell", ES_MENU_TARGET_SHELL, esph_shell_masks }, - { NULL } -}; - -static void -esph_finalise(GObject *o) -{ - /*EPluginHook *eph = (EPluginHook *)o;*/ - - ((GObjectClass *)esph_parent_class)->finalize(o); -} - -static void -esph_class_init(EPluginHookClass *klass) -{ - gint i; - - /** @HookClass: Shell Main Menu - * @Id: org.gnome.evolution.shell.bonobomenu:1.0 - * @Target: ESMenuTargetShell - * - * A hook for the main menus from the shell component. - * - * These menu's will be available from all components, but - * will have no context for the current component. - **/ - - ((GObjectClass *)klass)->finalize = esph_finalise; - ((EPluginHookClass *)klass)->id = "org.gnome.evolution.shell.bonobomenu:1.0"; - - for (i=0;esph_targets[i].type;i++) - e_menu_hook_class_add_target_map((EMenuHookClass *)klass, &esph_targets[i]); - - /* FIXME: leaks parent set class? */ - ((EMenuHookClass *)klass)->menu_class = g_type_class_ref(es_menu_get_type()); -} - -GType -es_menu_hook_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(ESMenuHookClass), NULL, NULL, (GClassInitFunc) esph_class_init, NULL, NULL, - sizeof(ESMenuHook), 0, (GInstanceInitFunc) NULL, - }; - - esph_parent_class = g_type_class_ref(e_menu_hook_get_type()); - type = g_type_register_static(e_menu_hook_get_type(), "ESMenuHook", &info, 0); - } - - return type; -} diff --git a/shell/es-menu.h b/shell/es-menu.h deleted file mode 100644 index d8ac21a567..0000000000 --- a/shell/es-menu.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michel Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __ES_MENU_H__ -#define __ES_MENU_H__ - -#include <glib-object.h> - -#include "e-util/e-menu.h" - -G_BEGIN_DECLS - -typedef struct _ESMenu ESMenu; -typedef struct _ESMenuClass ESMenuClass; - -/* Current target description */ -/* Types of popup tagets */ -enum _es_menu_target_t { - ES_MENU_TARGET_SHELL -}; - -/* Flags that describe a TARGET_SHELL */ -enum { - ES_MENU_SHELL_ONLINE = 1<<0, - ES_MENU_SHELL_OFFLINE = 1<<1 -}; - -typedef struct _ESMenuTargetShell ESMenuTargetShell; - -struct _ESMenuTargetShell { - EMenuTarget target; - - /* current component?? */ -}; - -typedef struct _EMenuItem ESMenuItem; - -/* The object */ -struct _ESMenu { - EMenu menu; - - struct _ESMenuPrivate *priv; -}; - -struct _ESMenuClass { - EMenuClass menu_class; -}; - -GType es_menu_get_type(void); - -ESMenu *es_menu_new(const gchar *menuid); - -ESMenuTargetShell *es_menu_target_new_shell(ESMenu *emp, guint32 flags); - -/* ********************************************************************** */ - -typedef struct _ESMenuHook ESMenuHook; -typedef struct _ESMenuHookClass ESMenuHookClass; - -struct _ESMenuHook { - EMenuHook hook; -}; - -struct _ESMenuHookClass { - EMenuHookClass hook_class; -}; - -GType es_menu_hook_get_type(void); - -G_END_DECLS - -#endif /* __ES_MENU_H__ */ diff --git a/shell/evolution-component.c b/shell/evolution-component.c deleted file mode 100644 index 49824c9545..0000000000 --- a/shell/evolution-component.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@novell.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-component.h" - -#define PARENT_TYPE bonobo_object_get_type () - -static BonoboObjectClass *parent_class = NULL; - -/* Evolution.Component */ - -/* Initialization */ - -static void -evolution_component_class_init (EvolutionComponentClass *klass) -{ - parent_class = g_type_class_peek_parent (klass); -} - -static void -evolution_component_init(EvolutionComponent *emf, EvolutionComponentClass *klass) -{ -} - -BONOBO_TYPE_FUNC_FULL (EvolutionComponent, GNOME_Evolution_Component, PARENT_TYPE, evolution_component) diff --git a/shell/evolution-component.h b/shell/evolution-component.h deleted file mode 100644 index 302263a657..0000000000 --- a/shell/evolution-component.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Abstract class wrapper for EvolutionComponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@novell.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _EVOLUTION_COMPONENT_H_ -#define _EVOLUTION_COMPONENT_H_ - -#include <bonobo/bonobo-object.h> -#include "shell/Evolution.h" - -typedef struct _EvolutionComponent EvolutionComponent; -typedef struct _EvolutionComponentClass EvolutionComponentClass; - -struct _EvolutionComponent { - BonoboObject parent; -}; - -struct _EvolutionComponentClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_Component__epv epv; -}; - -GType evolution_component_get_type(void); - -#endif /* _EVOLUTION_COMPONENT_H_ */ diff --git a/shell/evolution-config-control.c b/shell/evolution-config-control.c deleted file mode 100644 index a0d3f473a2..0000000000 --- a/shell/evolution-config-control.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-config-control.h" - -#include <e-util/e-util.h> - -#include <bonobo/bonobo-control.h> -#include <bonobo/bonobo-event-source.h> - - -#define PARENT_TYPE BONOBO_OBJECT_TYPE -static BonoboObjectClass *parent_class = NULL; - -struct _EvolutionConfigControlPrivate { - BonoboControl *control; - BonoboEventSource *event_source; -}; - -/* GObject methods. */ - -static void -impl_dispose (GObject *object) -{ - EvolutionConfigControl *config_control; - EvolutionConfigControlPrivate *priv; - - config_control = EVOLUTION_CONFIG_CONTROL (object); - priv = config_control->priv; - - if (priv->control != NULL) { - bonobo_object_unref (BONOBO_OBJECT (priv->control)); - priv->control = NULL; - } - - if (priv->event_source != NULL) { - bonobo_object_unref (BONOBO_OBJECT (priv->event_source)); - priv->event_source = NULL; - } - - (* G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -static void -impl_finalize (GObject *object) -{ - EvolutionConfigControl *config_control; - EvolutionConfigControlPrivate *priv; - - config_control = EVOLUTION_CONFIG_CONTROL (object); - priv = config_control->priv; - - g_free (priv); - - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} - - -/* Evolution::ConfigControl CORBA methods. */ - -static Bonobo_Control -impl__get_control (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionConfigControl *config_control; - EvolutionConfigControlPrivate *priv; - - config_control = EVOLUTION_CONFIG_CONTROL (bonobo_object_from_servant (servant)); - priv = config_control->priv; - - bonobo_object_ref (BONOBO_OBJECT (priv->control)); - - return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (priv->control)), ev); -} - -static Bonobo_EventSource -impl__get_eventSource (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionConfigControl *config_control; - EvolutionConfigControlPrivate *priv; - - config_control = EVOLUTION_CONFIG_CONTROL (bonobo_object_from_servant (servant)); - priv = config_control->priv; - - bonobo_object_ref (BONOBO_OBJECT (priv->event_source)); - - return CORBA_Object_duplicate (bonobo_object_corba_objref (BONOBO_OBJECT (priv->event_source)), ev); -} - - -static void -evolution_config_control_class_init (EvolutionConfigControlClass *class) -{ - POA_GNOME_Evolution_ConfigControl__epv *epv; - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; - - epv = &class->epv; - epv->_get_control = impl__get_control; - epv->_get_eventSource = impl__get_eventSource; - - parent_class = g_type_class_ref (PARENT_TYPE); -} - -static void -evolution_config_control_init (EvolutionConfigControl *config_control) -{ - EvolutionConfigControlPrivate *priv; - - priv = g_new (EvolutionConfigControlPrivate, 1); - priv->control = NULL; - priv->event_source = bonobo_event_source_new (); - - config_control->priv = priv; -} - - -void -evolution_config_control_construct (EvolutionConfigControl *control, - GtkWidget *widget) -{ - EvolutionConfigControlPrivate *priv; - - g_return_if_fail (EVOLUTION_IS_CONFIG_CONTROL (control)); - g_return_if_fail (GTK_IS_WIDGET (widget)); - - priv = control->priv; - - priv->control = bonobo_control_new (widget); -} - -EvolutionConfigControl * -evolution_config_control_new (GtkWidget *widget) -{ - EvolutionConfigControl *new; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - - new = g_object_new (evolution_config_control_get_type (), NULL); - evolution_config_control_construct (new, widget); - - return new; -} - -BONOBO_TYPE_FUNC_FULL (EvolutionConfigControl, - GNOME_Evolution_ConfigControl, - PARENT_TYPE, - evolution_config_control) diff --git a/shell/evolution-config-control.h b/shell/evolution-config-control.h deleted file mode 100644 index 59d7aba210..0000000000 --- a/shell/evolution-config-control.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EVOLUTION_CONFIG_CONTROL_H -#define EVOLUTION_CONFIG_CONTROL_H - -#include "Evolution.h" - -#include <bonobo/bonobo-object.h> -#include <gtk/gtk.h> - -#ifdef cplusplus -extern "C" { -#pragma } -#endif /* cplusplus */ - -#define EVOLUTION_TYPE_CONFIG_CONTROL (evolution_config_control_get_type ()) -#define EVOLUTION_CONFIG_CONTROL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_TYPE_CONFIG_CONTROL, EvolutionConfigControl)) -#define EVOLUTION_CONFIG_CONTROL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_CONFIG_CONTROL, EvolutionConfigControlClass)) -#define EVOLUTION_IS_CONFIG_CONTROL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_TYPE_CONFIG_CONTROL)) -#define EVOLUTION_IS_CONFIG_CONTROL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_CONFIG_CONTROL)) - -typedef struct _EvolutionConfigControl EvolutionConfigControl; -typedef struct _EvolutionConfigControlPrivate EvolutionConfigControlPrivate; -typedef struct _EvolutionConfigControlClass EvolutionConfigControlClass; - -struct _EvolutionConfigControl { - BonoboObject parent; - - EvolutionConfigControlPrivate *priv; -}; - -struct _EvolutionConfigControlClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_ConfigControl__epv epv; -}; - - -GType evolution_config_control_get_type (void); -EvolutionConfigControl *evolution_config_control_new (GtkWidget *widget); -void evolution_config_control_construct (EvolutionConfigControl *control, - GtkWidget *widget); - -#endif /* EVOLUTION_CONFIG_CONTROL_H */ diff --git a/shell/evolution-listener.c b/shell/evolution-listener.c deleted file mode 100644 index 3209450134..0000000000 --- a/shell/evolution-listener.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@novell.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-listener.h" - -#define PARENT_TYPE bonobo_object_get_type () - -static BonoboObjectClass *parent_class = NULL; - -/* Evolution.Listener */ -static void -impl_complete(PortableServer_Servant _servant, CORBA_Environment * ev) -{ - EvolutionListener *el = (EvolutionListener *)bonobo_object_from_servant(_servant); - - if (el->complete) - el->complete(el, el->data); -} - -static void -evolution_listener_class_init (EvolutionListenerClass *klass) -{ - POA_GNOME_Evolution_Listener__epv *epv = &klass->epv; - - parent_class = g_type_class_peek_parent (klass); - - epv->complete = impl_complete; -} - -static void -evolution_listener_init(EvolutionListener *emf, EvolutionListenerClass *klass) -{ -} - -BONOBO_TYPE_FUNC_FULL (EvolutionListener, GNOME_Evolution_Listener, PARENT_TYPE, evolution_listener) - -EvolutionListener * -evolution_listener_new(EvolutionListenerFunc complete, gpointer data) -{ - EvolutionListener *el; - - el = g_object_new(evolution_listener_get_type(), NULL); - el->complete = complete; - el->data = data; - - return el; -} diff --git a/shell/evolution-listener.h b/shell/evolution-listener.h deleted file mode 100644 index 9637342099..0000000000 --- a/shell/evolution-listener.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Abstract class wrapper for EvolutionListener - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Michael Zucchi <notzed@novell.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _EVOLUTION_LISTENER_H_ -#define _EVOLUTION_LISTENER_H_ - -#include <bonobo/bonobo-object.h> -#include "shell/Evolution.h" - -typedef struct _EvolutionListener EvolutionListener; -typedef struct _EvolutionListenerClass EvolutionListenerClass; - -typedef void (*EvolutionListenerFunc)(EvolutionListener *, gpointer ); - -struct _EvolutionListener { - BonoboObject parent; - - /* we dont need signals, so why bother wasting resources on it */ - EvolutionListenerFunc complete; - gpointer data; -}; - -struct _EvolutionListenerClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_Listener__epv epv; -}; - -GType evolution_listener_get_type(void); -EvolutionListener *evolution_listener_new(EvolutionListenerFunc complete, gpointer data); - -#endif /* _EVOLUTION_LISTENER_H_ */ diff --git a/shell/evolution-shell-component-utils.c b/shell/evolution-shell-component-utils.c deleted file mode 100644 index 7301a3741b..0000000000 --- a/shell/evolution-shell-component-utils.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-shell-component-utils.h" -#include <e-util/e-icon-factory.h> -#include "e-util/e-dialog-utils.h" - -#include <string.h> -#include <glib/gi18n.h> -#include <bonobo/bonobo-ui-util.h> -#include <bonobo/bonobo-moniker-util.h> -#include <bonobo/bonobo-exception.h> -#include <bonobo-activation/bonobo-activation.h> - -static void free_pixmaps (void); -static GSList *inited_arrays = NULL; - -void e_pixmaps_update (BonoboUIComponent *uic, EPixmap *pixcache) -{ - static gint done_init = 0; - gint i; - - if (!done_init) { - g_atexit (free_pixmaps); - done_init = 1; - } - - if (g_slist_find (inited_arrays, pixcache) == NULL) - inited_arrays = g_slist_prepend (inited_arrays, pixcache); - - for (i = 0; pixcache [i].path; i++) { - if (!pixcache [i].pixbuf) { - GdkPixbuf *pixbuf; - - pixbuf = e_icon_factory_get_icon (pixcache [i].name, pixcache [i].size); - pixcache [i].pixbuf = bonobo_ui_util_pixbuf_to_xml (pixbuf); - g_object_unref (pixbuf); - bonobo_ui_component_set_prop (uic, - pixcache [i].path, "pixname", - pixcache [i].pixbuf, NULL); - } else { - bonobo_ui_component_set_prop (uic, pixcache [i].path, - "pixname", - pixcache [i].pixbuf, - NULL); - } - } -} - -static void -free_pixmaps (void) -{ - gint i; - GSList *li; - - for (li = inited_arrays; li != NULL; li = li->next) { - EPixmap *pixcache = li->data; - for (i = 0; pixcache [i].path; i++) - g_free (pixcache [i].pixbuf); - } - - g_slist_free (inited_arrays); -} - -/** - * e_get_activation_failure_msg: - * @ev: An exception returned by an oaf_activate call. - * - * Get a descriptive error message from @ev. - * - * Return value: A newly allocated string with the printable error message. - **/ -gchar * -e_get_activation_failure_msg (CORBA_Environment *ev) -{ - g_return_val_if_fail (ev != NULL, NULL); - - if (CORBA_exception_id (ev) == NULL) - return NULL; - - if (strcmp (CORBA_exception_id (ev), ex_Bonobo_GeneralError) != 0) { - return bonobo_exception_get_text (ev); - } else { - const Bonobo_GeneralError *oaf_general_error; - - oaf_general_error = CORBA_exception_value (ev); - return g_strdup (oaf_general_error->description); - } -} diff --git a/shell/import.glade b/shell/import.glade deleted file mode 100644 index 389d2feee3..0000000000 --- a/shell/import.glade +++ /dev/null @@ -1,124 +0,0 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> -<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> - -<glade-interface> -<requires lib="gnome"/> - -<widget class="GtkWindow" id="importwizard"> - <property name="title" translatable="yes">Evolution Import Assistant</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - - <child> - <widget class="GnomeDruid" id="druid1"> - <property name="border_width">4</property> - <property name="visible">True</property> - <property name="show_help">False</property> - - <child> - <widget class="GnomeDruidPageEdge" id="page0"> - <property name="visible">True</property> - <property name="position">GNOME_EDGE_START</property> - <property name="title" translatable="yes">Evolution Import Assistant</property> - <property name="text" translatable="yes">Welcome to the Evolution Import Assistant. -With this assistant you will be guided through the process of -importing external files into Evolution.</property> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page1"> - <property name="visible">True</property> - <property name="title" translatable="yes">Importer Type</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox2"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page2-file"> - <property name="visible">True</property> - <property name="title" translatable="yes">Select a File</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox1"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page3-file"> - <property name="visible">True</property> - <property name="title" translatable="yes">Import Location</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox3"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page2-intelligent"> - <property name="visible">True</property> - <property name="title" translatable="yes">Select Information to Import</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox3"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageEdge" id="page4"> - <property name="visible">True</property> - <property name="position">GNOME_EDGE_FINISH</property> - <property name="title" translatable="yes">Import File</property> - <property name="text" translatable="yes">Click "Import" to begin importing the file into Evolution. </property> - </widget> - </child> - </widget> - </child> -</widget> - -</glade-interface> diff --git a/shell/importer/GNOME_Evolution_Importer.idl b/shell/importer/GNOME_Evolution_Importer.idl deleted file mode 100644 index e33ca150ae..0000000000 --- a/shell/importer/GNOME_Evolution_Importer.idl +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Interfaces for the importer framework. - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - */ - -#include <Bonobo.idl> - -module GNOME { -module Evolution { - interface ImporterListener : Bonobo::Unknown { - enum ImporterResult { - OK, - UNSUPPORTED_OPERATION, - NOT_READY, - BUSY, - UNKNOWN_DATA, - BAD_DATA, - BAD_FILE - }; - - /** - * notifyResult: - * @result: The result of the import. - * @more_items: Are there any more items to be processed? - * - * Notifies the listener of the result and whether there are - * any more items to be imported. - */ - oneway void notifyResult (in ImporterResult result, - in boolean more_items); - }; - - interface Importer : Bonobo::Unknown { - - /** - * processItem: - * @listener: The ImporterListener that will be notified of the - * progress. - * - * Processes the next item. - * - */ - oneway void processItem (in ImporterListener listener); - - /** - * getError: - * - * Retrieve a detailed explaination of the error. - * - * Returns: A string. - */ - string getError (); - - void createControl (out Bonobo::Control control); - - /** - * supportFormat: - * @filename: The filename of the file. - * - * Checks if the importer created by this factory can - * import the file specified. - * - * Returns: A boolean, TRUE if it can import the file, - * FALSE otherwise. - */ - boolean supportFormat (in string filename); - - /** - * loadFile: - * @filename: The filename of the file. - * @folderpath: The full pathname to the folder. - * @foldertpe: The type of the folder to import to. - * - * Loads the file and prepares an Importer object that can - * process files of this type. - * - * Returns: An Importer object. - */ - boolean loadFile (in string filename); - }; - - interface IntelligentImporter : Bonobo::Unknown { - - readonly attribute string importername; - readonly attribute string message; - - boolean canImport (); - - void importData (); - }; -}; -}; diff --git a/shell/importer/Makefile.am b/shell/importer/Makefile.am deleted file mode 100644 index 06735179af..0000000000 --- a/shell/importer/Makefile.am +++ /dev/null @@ -1,68 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/shell \ - -I$(top_builddir)/shell \ - -DG_LOG_DOMAIN=\"Evolution-Importer\" \ - -DEVOLUTION_GLADEDIR="\"$(gladedir)\"" \ - $(SHELL_CFLAGS) - -privlib_LTLIBRARIES = libevolution-importer.la - - -# IDL stuff - -IDLS = GNOME_Evolution_Importer.idl - -IDL_GENERATED_H = \ - GNOME_Evolution_Importer.h - -IDL_GENERATED_C = \ - GNOME_Evolution_Importer-common.c \ - GNOME_Evolution_Importer-skels.c \ - GNOME_Evolution_Importer-stubs.c - -IDL_GENERATED = $(IDL_GENERATED_H) $(IDL_GENERATED_C) - -$(IDL_GENERATED_H): $(IDLS) - $(ORBIT_IDL) -I $(srcdir) $(IDL_INCLUDES) $(srcdir)/GNOME_Evolution_Importer.idl - -$(IDL_GENERATED_C): $(IDL_GENERATED_H) - -idl_DATA = $(IDLS) - - -# Component - -libevolution_importerincludedir = $(privincludedir)/importer -libevolution_importer_la_SOURCES = \ - $(IDL_GENERATED) \ - evolution-intelligent-importer.c \ - evolution-importer-client.c \ - evolution-importer-listener.c \ - evolution-importer.c \ - intelligent.c \ - intelligent.h - -libevolution_importerinclude_HEADERS = \ - GNOME_Evolution_Importer.h \ - evolution-intelligent-importer.h \ - evolution-importer-client.h \ - evolution-importer-listener.h \ - evolution-importer.h - -libevolution_importer_la_LIBADD = \ - $(top_builddir)/e-util/libeutil.la \ - $(SHELL_LIBS) - -glade_DATA = import.glade - -EXTRA_DIST = $(glade_DATA) $(IDLS) - -BUILT_SOURCES= $(IDL_GENERATED) -CLEANFILES = $(BUILT_SOURCES) - -dist-hook: - cd $(distdir); rm -f $(BUILT_SOURCES) - - --include $(top_srcdir)/git.mk diff --git a/shell/importer/evolution-importer-client.c b/shell/importer/evolution-importer-client.c deleted file mode 100644 index 66a82836e3..0000000000 --- a/shell/importer/evolution-importer-client.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Based on evolution-shell-component-client.c by Ettore Perazzoli - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-importer-client.h" - -#include <glib.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-main.h> -#include <bonobo/bonobo-widget.h> -#include <bonobo/bonobo-exception.h> - -#include "GNOME_Evolution_Importer.h" - -G_DEFINE_TYPE (EvolutionImporterClient, evolution_importer_client, G_TYPE_OBJECT) - - -static void -finalise (GObject *object) -{ - /* FIXME: should this unref the client->objref?? */ - - (* G_OBJECT_CLASS (evolution_importer_client_parent_class)->finalize) (object); -} - -static void -evolution_importer_client_class_init (EvolutionImporterClientClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = finalise; -} - -static void -evolution_importer_client_init (EvolutionImporterClient *client) -{ -} - -/** - * evolution_importer_client_new: - * @objref: The CORBA_Object to make a client for. - * - * Makes a client for @objref. @objref should be an Evolution_Importer. - * - * Returns: A newly created EvolutionImporterClient. - */ -EvolutionImporterClient * -evolution_importer_client_new (const CORBA_Object objref) -{ - EvolutionImporterClient *client; - - g_return_val_if_fail (objref != CORBA_OBJECT_NIL, NULL); - - client = g_object_new (evolution_importer_client_get_type (), NULL); - client->objref = objref; - - return client; -} - -/** - * evolution_importer_client_new_from_id: - * @id: The oafiid of the component to make a client for. - * - * Makes a client for the object returned by activating @id. - * - * Returns: A newly created EvolutionImporterClient. - */ -EvolutionImporterClient * -evolution_importer_client_new_from_id (const gchar *id) -{ - CORBA_Environment ev; - CORBA_Object objref; - - g_return_val_if_fail (id != NULL, NULL); - - CORBA_exception_init (&ev); - objref = bonobo_activation_activate_from_id ((gchar *) id, 0, NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - CORBA_exception_free (&ev); - g_warning ("Could not start %s.", id); - return NULL; - } - - CORBA_exception_free (&ev); - if (objref == CORBA_OBJECT_NIL) { - g_warning ("Could not activate component %s", id); - return NULL; - } - - return evolution_importer_client_new (objref); -} - -/* API */ -GtkWidget * -evolution_importer_client_create_control (EvolutionImporterClient *client) -{ - GNOME_Evolution_Importer corba_importer; - GtkWidget *widget = NULL; - Bonobo_Control control; - CORBA_Environment ev; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (EVOLUTION_IS_IMPORTER_CLIENT (client), NULL); - - CORBA_exception_init (&ev); - corba_importer = client->objref; - GNOME_Evolution_Importer_createControl (corba_importer, &control, &ev); - - if (!BONOBO_EX (&ev)) { - /* FIXME Pass in container? */ - widget = bonobo_widget_new_control_from_objref (control, NULL); - gtk_widget_show (widget); - } - - CORBA_exception_free (&ev); - - return widget; -} - -/** - * evolution_importer_client_support_format: - * @client: The EvolutionImporterClient. - * @filename: Name of the file to check. - * - * Checks whether @client is able to import @filename. - * - * Returns: TRUE if @client can import @filename, FALSE otherwise. - */ -gboolean -evolution_importer_client_support_format (EvolutionImporterClient *client, - const gchar *filename) -{ - GNOME_Evolution_Importer corba_importer; - gboolean result; - CORBA_Environment ev; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (EVOLUTION_IS_IMPORTER_CLIENT (client), FALSE); - g_return_val_if_fail (filename != NULL, FALSE); - - CORBA_exception_init (&ev); - corba_importer = client->objref; - result = GNOME_Evolution_Importer_supportFormat (corba_importer, - filename, &ev); - CORBA_exception_free (&ev); - - return result; -} - -/** - * evolution_importer_client_load_file: - * @client: The EvolutionImporterClient. - * @filename: The file to load. - * @physical_uri: The physical URI of the folder to import data into. - * @folder_type: The type of the folder represented by @physical_uri. - * - * Loads and initialises the importer. - * - * Returns: TRUE on sucess, FALSE on failure. - */ -gboolean -evolution_importer_client_load_file (EvolutionImporterClient *client, const gchar *filename) -{ - GNOME_Evolution_Importer corba_importer; - gboolean result; - CORBA_Environment ev; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (EVOLUTION_IS_IMPORTER_CLIENT (client), FALSE); - g_return_val_if_fail (filename != NULL, FALSE); - - CORBA_exception_init (&ev); - corba_importer = client->objref; - result = GNOME_Evolution_Importer_loadFile (corba_importer, filename, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Oh there *WAS* an exception.\nIt was %s", - CORBA_exception_id (&ev)); - CORBA_exception_free (&ev); - return FALSE; - } - CORBA_exception_free (&ev); - - return result; -} - -/** - * evolution_importer_client_process_item: - * @client: The EvolutionImporterClient. - * @listener: The EvolutionImporterListener. - * - * Starts importing the next item in the file. @listener will be notified - * when the item has finished. - */ -void -evolution_importer_client_process_item (EvolutionImporterClient *client, - EvolutionImporterListener *listener) -{ - GNOME_Evolution_Importer corba_importer; - GNOME_Evolution_ImporterListener corba_listener; - CORBA_Environment ev; - - g_return_if_fail (client != NULL); - g_return_if_fail (EVOLUTION_IS_IMPORTER_CLIENT (client)); - g_return_if_fail (listener != NULL); - g_return_if_fail (EVOLUTION_IS_IMPORTER_LISTENER (listener)); - - CORBA_exception_init (&ev); - - corba_importer = client->objref; - corba_listener = bonobo_object_corba_objref (BONOBO_OBJECT (listener)); - GNOME_Evolution_Importer_processItem (corba_importer, - corba_listener, &ev); - CORBA_exception_free (&ev); -} - -/** - * evolution_importer_client_get_error: - * @client: The EvolutionImporterClient. - * - * Gets the error as a string. - * - * Returns: The error as a string. If there is no error NULL is returned. - * Importers need not support this method and if so, NULL is also returned. - */ -const gchar * -evolution_importer_client_get_error (EvolutionImporterClient *client) -{ - GNOME_Evolution_Importer corba_importer; - CORBA_char *str; - CORBA_Environment ev; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (EVOLUTION_IS_IMPORTER_CLIENT (client), NULL); - - corba_importer = client->objref; - - CORBA_exception_init (&ev); - str = GNOME_Evolution_Importer_getError (corba_importer, &ev); - - return str; -} diff --git a/shell/importer/evolution-importer-client.h b/shell/importer/evolution-importer-client.h deleted file mode 100644 index e94584216d..0000000000 --- a/shell/importer/evolution-importer-client.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EVOLUTION_IMPORTER_CLIENT_H -#define EVOLUTION_IMPORTER_CLIENT_H - -#include <glib.h> -#include <gtk/gtk.h> -#include <importer/evolution-importer.h> -#include <importer/evolution-importer-listener.h> - -G_BEGIN_DECLS - -#define EVOLUTION_TYPE_IMPORTER_CLIENT (evolution_importer_client_get_type ()) -#define EVOLUTION_IMPORTER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_TYPE_IMPORTER_CLIENT, EvolutionImporterClient)) -#define EVOLUTION_IMPORTER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_IMPORTER_CLIENT, EvolutionImporterClientClass)) -#define EVOLUTION_IS_IMPORTER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_TYPE_IMPORTER_CLIENT)) -#define EVOLUTION_IS_IMPORTER_CLIENT_CLASS(klass) (G_TYPE_CHECK_INSTANCE_TYPE ((klass), EVOLUTION_TYPE_IMPORTER_CLIENT)) - - -typedef struct _EvolutionImporterClient EvolutionImporterClient; -typedef struct _EvolutionImporterClientClass EvolutionImporterClientClass; - -struct _EvolutionImporterClient { - GObject parent_type; - - GNOME_Evolution_Importer objref; -}; - -struct _EvolutionImporterClientClass { - GObjectClass parent_class; -}; - -GType evolution_importer_client_get_type (void); - -EvolutionImporterClient *evolution_importer_client_new (const CORBA_Object objref); -EvolutionImporterClient *evolution_importer_client_new_from_id (const gchar *id); - -GtkWidget *evolution_importer_client_create_control (EvolutionImporterClient *client); -gboolean evolution_importer_client_support_format (EvolutionImporterClient *client, - const gchar *filename); -gboolean evolution_importer_client_load_file (EvolutionImporterClient *client, - const gchar *filename); -void evolution_importer_client_process_item (EvolutionImporterClient *client, - EvolutionImporterListener *listener); -const gchar *evolution_importer_client_get_error (EvolutionImporterClient *client); - -G_END_DECLS - -#endif diff --git a/shell/importer/evolution-importer-listener.c b/shell/importer/evolution-importer-listener.c deleted file mode 100644 index ffac2d3ab4..0000000000 --- a/shell/importer/evolution-importer-listener.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-importer-listener.h" - -#include <bonobo/bonobo-object.h> -#include <e-util/e-util.h> - -#include "GNOME_Evolution_Importer.h" -#define PARENT_TYPE BONOBO_OBJECT_TYPE - -static BonoboObjectClass *parent_class = NULL; - -struct _EvolutionImporterListenerPrivate { - EvolutionImporterListenerCallback callback; - - gpointer closure; -}; - -#if 0 -static POA_GNOME_Evolution_ImporterListener__vepv Listener_vepv; - -static POA_GNOME_Evolution_ImporterListener * -create_servant (void) -{ - POA_GNOME_Evolution_ImporterListener *servant; - CORBA_Environment ev; - - servant = (POA_GNOME_Evolution_ImporterListener *) g_new0 (BonoboObjectServant, 1); - servant->vepv = &Listener_vepv; - - CORBA_exception_init (&ev); - POA_GNOME_Evolution_ImporterListener__init ((PortableServer_Servant) servant, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_free (servant); - CORBA_exception_free (&ev); - return NULL; - } - - CORBA_exception_free (&ev); - - return servant; -} -#endif - -static EvolutionImporterResult -corba_result_to_evolution (GNOME_Evolution_ImporterListener_ImporterResult corba_result) -{ - switch (corba_result) { - case GNOME_Evolution_ImporterListener_OK: - return EVOLUTION_IMPORTER_OK; - case GNOME_Evolution_ImporterListener_UNSUPPORTED_OPERATION: - return EVOLUTION_IMPORTER_UNSUPPORTED_OPERATION; - case GNOME_Evolution_ImporterListener_UNKNOWN_DATA: - return EVOLUTION_IMPORTER_UNKNOWN_DATA; - case GNOME_Evolution_ImporterListener_BAD_DATA: - return EVOLUTION_IMPORTER_BAD_DATA; - case GNOME_Evolution_ImporterListener_BAD_FILE: - return EVOLUTION_IMPORTER_BAD_FILE; - case GNOME_Evolution_ImporterListener_NOT_READY: - return EVOLUTION_IMPORTER_NOT_READY; - case GNOME_Evolution_ImporterListener_BUSY: - return EVOLUTION_IMPORTER_BUSY; - default: - return EVOLUTION_IMPORTER_UNKNOWN_ERROR; - } -} - -static inline EvolutionImporterListener * -evolution_importer_listener_from_servant (PortableServer_Servant servant) -{ - return EVOLUTION_IMPORTER_LISTENER (bonobo_object_from_servant (servant)); -} - -static void -impl_GNOME_Evolution_ImporterListener_notifyResult (PortableServer_Servant servant, - GNOME_Evolution_ImporterListener_ImporterResult result, - CORBA_boolean more_items, - CORBA_Environment *ev) -{ - EvolutionImporterListener *listener; - EvolutionImporterListenerPrivate *priv; - EvolutionImporterResult out_result; - - listener = evolution_importer_listener_from_servant (servant); - priv = listener->priv; - - out_result = corba_result_to_evolution (result); - if (priv->callback) { - (priv->callback) (listener, out_result, more_items, - priv->closure); - } - - return; -} - - -/* GObject methods */ -static void -finalise (GObject *object) -{ - EvolutionImporterListener *listener; - EvolutionImporterListenerPrivate *priv; - - listener = EVOLUTION_IMPORTER_LISTENER (object); - priv = listener->priv; - - if (priv == NULL) - return; - - g_free (priv); - listener->priv = NULL; - - G_OBJECT_CLASS (parent_class)->finalize(object); -} - -#if 0 -static void -corba_class_init (void) -{ - POA_GNOME_Evolution_ImporterListener__vepv *vepv; - POA_GNOME_Evolution_ImporterListener__epv *epv; - PortableServer_ServantBase__epv *base_epv; - - base_epv = g_new0 (PortableServer_ServantBase__epv, 1); - base_epv->_private = NULL; - base_epv->finalize = NULL; - base_epv->default_POA = NULL; - - epv = g_new0 (POA_GNOME_Evolution_ImporterListener__epv, 1); - epv->notifyResult = impl_GNOME_Evolution_ImporterListener_notifyResult; - - vepv = &Listener_vepv; - vepv->_base_epv = base_epv; - vepv->Bonobo_Unknown_epv = bonobo_object_get_epv (); - vepv->GNOME_Evolution_ImporterListener_epv = epv; -} -#endif - -static void -evolution_importer_listener_class_init (EvolutionImporterListenerClass *klass) -{ - GObjectClass *object_class; - POA_GNOME_Evolution_ImporterListener__epv *epv = &klass->epv; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = finalise; - - parent_class = g_type_class_ref(PARENT_TYPE); - epv->notifyResult = impl_GNOME_Evolution_ImporterListener_notifyResult; -} - -static void -evolution_importer_listener_init (EvolutionImporterListener *listener) -{ - EvolutionImporterListenerPrivate *priv; - - priv = g_new0 (EvolutionImporterListenerPrivate, 1); - listener->priv = priv; -} - -static void -evolution_importer_listener_construct (EvolutionImporterListener *listener, - EvolutionImporterListenerCallback callback, - gpointer closure) -{ - EvolutionImporterListenerPrivate *priv; - - g_return_if_fail (listener != NULL); - g_return_if_fail (EVOLUTION_IS_IMPORTER_LISTENER (listener)); - g_return_if_fail (callback != NULL); - - priv = listener->priv; - priv->callback = callback; - priv->closure = closure; -} - -/** - * evolution_importer_listener_new - * @callback: The #EvolutionImporterListenerCallback callback. - * @closure: The data that will be passed to that callback. - * - * Creates a new #EvolutionImporterListener object which calls @callback when - * something happens. - * Returns: A newly allocated #EvolutionImporterListener. - */ -EvolutionImporterListener * -evolution_importer_listener_new (EvolutionImporterListenerCallback callback, - gpointer closure) -{ - EvolutionImporterListener *listener; - - listener = g_object_new (evolution_importer_listener_get_type (), NULL); - - evolution_importer_listener_construct (listener, callback, closure); - return listener; -} - -BONOBO_TYPE_FUNC_FULL (EvolutionImporterListener, - GNOME_Evolution_ImporterListener, - PARENT_TYPE, evolution_importer_listener); diff --git a/shell/importer/evolution-importer-listener.h b/shell/importer/evolution-importer-listener.h deleted file mode 100644 index 39bf2a0493..0000000000 --- a/shell/importer/evolution-importer-listener.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EVOLUTION_IMPORTER_LISTENER_H -#define EVOLUTION_IMPORTER_LISTENER_H - -#include <glib.h> -#include <bonobo/bonobo-object.h> -#include <importer/GNOME_Evolution_Importer.h> -#include "evolution-importer.h" - -G_BEGIN_DECLS - -#define EVOLUTION_TYPE_IMPORTER_LISTENER (evolution_importer_listener_get_type ()) -#define EVOLUTION_IMPORTER_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_TYPE_IMPORTER_LISTENER, EvolutionImporterListener)) -#define EVOLUTION_IMPORTER_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_IMPORTER_LISTENER, EvolutionImporterListenerClass)) -#define EVOLUTION_IS_IMPORTER_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_TYPE_IMPORTER_LISTENER)) -#define EVOLUTION_IS_IMPORTER_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_IMPORTER_LISTENER)) - -typedef struct _EvolutionImporterListener EvolutionImporterListener; -typedef struct _EvolutionImporterListenerPrivate EvolutionImporterListenerPrivate; -typedef struct _EvolutionImporterListenerClass EvolutionImporterListenerClass; - -typedef void (* EvolutionImporterListenerCallback) (EvolutionImporterListener *listener, - EvolutionImporterResult result, - gboolean more_items, - gpointer closure); -struct _EvolutionImporterListener { - BonoboObject parent; - - EvolutionImporterListenerPrivate *priv; -}; - -struct _EvolutionImporterListenerClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_ImporterListener__epv epv; -}; - -GType evolution_importer_listener_get_type (void); - -EvolutionImporterListener *evolution_importer_listener_new (EvolutionImporterListenerCallback callback, - gpointer closure); - -G_END_DECLS - -#endif diff --git a/shell/importer/evolution-importer.c b/shell/importer/evolution-importer.c deleted file mode 100644 index 17e118094b..0000000000 --- a/shell/importer/evolution-importer.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-importer.h" - -#include <bonobo/bonobo-object.h> -#include <e-util/e-util.h> - -#include "GNOME_Evolution_Importer.h" - -#define PARENT_TYPE BONOBO_OBJECT_TYPE -static BonoboObjectClass *parent_class = NULL; - -struct _EvolutionImporterPrivate { - EvolutionImporterCreateControlFn create_control_fn; - EvolutionImporterLoadFileFn load_file_fn; - EvolutionImporterSupportFormatFn support_format_fn; - EvolutionImporterProcessItemFn process_item_fn; - EvolutionImporterGetErrorFn get_error_fn; - - gpointer closure; -}; - - -static inline EvolutionImporter * -evolution_importer_from_servant (PortableServer_Servant servant) -{ - return EVOLUTION_IMPORTER (bonobo_object_from_servant (servant)); -} - -static void -impl_GNOME_Evolution_Importer_createControl (PortableServer_Servant servant, - Bonobo_Control *control, - CORBA_Environment *ev) -{ - EvolutionImporter *importer; - EvolutionImporterPrivate *priv; - - importer = evolution_importer_from_servant (servant); - priv = importer->priv; - - if (priv->create_control_fn != NULL) - (priv->create_control_fn) (importer, control, priv->closure); - else - CORBA_exception_set_system (ev, ex_CORBA_NO_IMPLEMENT, CORBA_COMPLETED_NO); -} - -static CORBA_boolean -impl_GNOME_Evolution_Importer_supportFormat (PortableServer_Servant servant, - const CORBA_char *filename, - CORBA_Environment *ev) -{ - EvolutionImporter *importer; - EvolutionImporterPrivate *priv; - - importer = evolution_importer_from_servant (servant); - priv = importer->priv; - - if (priv->support_format_fn != NULL) - return (priv->support_format_fn) (importer, filename, - priv->closure); - else - return FALSE; -} - -static CORBA_boolean -impl_GNOME_Evolution_Importer_loadFile (PortableServer_Servant servant, - const CORBA_char *filename, - CORBA_Environment *ev) -{ - EvolutionImporter *importer; - EvolutionImporterPrivate *priv; - - importer = evolution_importer_from_servant (servant); - priv = importer->priv; - - if (priv->load_file_fn != NULL) - return (priv->load_file_fn) (importer, filename, priv->closure); - else - return FALSE; -} - -static void -impl_GNOME_Evolution_Importer_processItem (PortableServer_Servant servant, - GNOME_Evolution_ImporterListener listener, - CORBA_Environment *ev) -{ - EvolutionImporter *importer; - EvolutionImporterPrivate *priv; - - importer = evolution_importer_from_servant (servant); - priv = importer->priv; - - if (priv->process_item_fn != NULL) - (priv->process_item_fn) (importer, listener, priv->closure, ev); - else - GNOME_Evolution_ImporterListener_notifyResult (listener, - GNOME_Evolution_ImporterListener_UNSUPPORTED_OPERATION, FALSE, ev); -} - -static CORBA_char * -impl_GNOME_Evolution_Importer_getError (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionImporter *importer; - EvolutionImporterPrivate *priv; - CORBA_char *out_str; - - importer = evolution_importer_from_servant (servant); - priv = importer->priv; - - if (priv->get_error_fn != NULL) { - out_str = (priv->get_error_fn) (importer, priv->closure); - return CORBA_string_dup (out_str ? out_str : ""); - } else - return CORBA_string_dup (""); -} - - -static void -finalise (GObject *object) -{ - EvolutionImporter *importer; - EvolutionImporterPrivate *priv; - - importer = EVOLUTION_IMPORTER (object); - priv = importer->priv; - - if (priv == NULL) - return; - - g_free (priv); - importer->priv = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -evolution_importer_class_init (EvolutionImporterClass *klass) -{ - GObjectClass *object_class; - POA_GNOME_Evolution_Importer__epv *epv = &klass->epv; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = finalise; - - parent_class = g_type_class_ref(PARENT_TYPE); - epv->createControl = impl_GNOME_Evolution_Importer_createControl; - epv->supportFormat = impl_GNOME_Evolution_Importer_supportFormat; - epv->loadFile = impl_GNOME_Evolution_Importer_loadFile; - epv->processItem = impl_GNOME_Evolution_Importer_processItem; - epv->getError = impl_GNOME_Evolution_Importer_getError; -} - -static void -evolution_importer_init (EvolutionImporter *importer) -{ - EvolutionImporterPrivate *priv; - - priv = g_new0 (EvolutionImporterPrivate, 1); - - importer->priv = priv; -} - - - -static void -evolution_importer_construct (EvolutionImporter *importer, - EvolutionImporterCreateControlFn create_control_fn, - EvolutionImporterSupportFormatFn support_format_fn, - EvolutionImporterLoadFileFn load_file_fn, - EvolutionImporterProcessItemFn process_item_fn, - EvolutionImporterGetErrorFn get_error_fn, - gpointer closure) -{ - EvolutionImporterPrivate *priv; - - g_return_if_fail (importer != NULL); - g_return_if_fail (EVOLUTION_IS_IMPORTER (importer)); - g_return_if_fail (support_format_fn != NULL); - g_return_if_fail (load_file_fn != NULL); - g_return_if_fail (process_item_fn != NULL); - - priv = importer->priv; - priv->create_control_fn = create_control_fn; - priv->support_format_fn = support_format_fn; - priv->load_file_fn = load_file_fn; - priv->process_item_fn = process_item_fn; - priv->get_error_fn = get_error_fn; - - priv->closure = closure; -} - -/** - * evolution_importer_new: - * @support_format_fn: The function to be called by the supportFormat method. - * @load_file_fn: The function to be called by the loadFile method. - * @process_item_fn: The function to be called by the processItem method. - * @get_error_fn: The function to be called by the getError method. - * @closure: The data to be passed to all of the above functions. - * - * Creates a new EvolutionImporter object. Of the parameters only - * @get_error_function and @closure may be #NULL. - * - * Returns: A newly created EvolutionImporter object. - */ -EvolutionImporter * -evolution_importer_new (EvolutionImporterCreateControlFn create_control_fn, - EvolutionImporterSupportFormatFn support_format_fn, - EvolutionImporterLoadFileFn load_file_fn, - EvolutionImporterProcessItemFn process_item_fn, - EvolutionImporterGetErrorFn get_error_fn, - gpointer closure) -{ - EvolutionImporter *importer; - - importer = g_object_new(evolution_importer_get_type (), NULL); - evolution_importer_construct (importer, create_control_fn, support_format_fn, load_file_fn, - process_item_fn, get_error_fn, closure); - return importer; -} - -BONOBO_TYPE_FUNC_FULL (EvolutionImporter, - GNOME_Evolution_Importer, - PARENT_TYPE, - evolution_importer); diff --git a/shell/importer/evolution-importer.h b/shell/importer/evolution-importer.h deleted file mode 100644 index 05eae39b43..0000000000 --- a/shell/importer/evolution-importer.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EVOLUTION_IMPORTER_H -#define EVOLUTION_IMPORTER_H - -#include <glib.h> -#include <bonobo/bonobo-object.h> -#include <importer/GNOME_Evolution_Importer.h> - -G_BEGIN_DECLS - -#define EVOLUTION_TYPE_IMPORTER (evolution_importer_get_type ()) -#define EVOLUTION_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_TYPE_IMPORTER, EvolutionImporter)) -#define EVOLUTION_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_IMPORTER, EvolutionImporterClass)) -#define EVOLUTION_IS_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_TYPE_IMPORTER)) -#define EVOLUTION_IS_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_IMPORTER)) - -typedef struct _EvolutionImporter EvolutionImporter; -typedef struct _EvolutionImporterPrivate EvolutionImporterPrivate; -typedef struct _EvolutionImporterClass EvolutionImporterClass; - -typedef void (* EvolutionImporterCreateControlFn) (EvolutionImporter *importer, - Bonobo_Control *control, - gpointer closure); - -typedef gboolean (* EvolutionImporterSupportFormatFn) (EvolutionImporter *importer, - const gchar *filename, - gpointer closure); -typedef gboolean (* EvolutionImporterLoadFileFn) (EvolutionImporter *importer, - const gchar *filename, - gpointer closure); -typedef void (* EvolutionImporterProcessItemFn) (EvolutionImporter *importer, - CORBA_Object listener, - gpointer closure, - CORBA_Environment *ev); -typedef gchar *(* EvolutionImporterGetErrorFn) (EvolutionImporter *importer, - gpointer closure); - -typedef enum { - EVOLUTION_IMPORTER_OK, - EVOLUTION_IMPORTER_UNSUPPORTED_OPERATION, - EVOLUTION_IMPORTER_INTERRUPTED, - EVOLUTION_IMPORTER_BUSY, - EVOLUTION_IMPORTER_NOT_READY, - EVOLUTION_IMPORTER_UNKNOWN_DATA, - EVOLUTION_IMPORTER_BAD_DATA, - EVOLUTION_IMPORTER_BAD_FILE, - EVOLUTION_IMPORTER_UNKNOWN_ERROR -} EvolutionImporterResult; - -struct _EvolutionImporter { - BonoboObject parent; - - EvolutionImporterPrivate *priv; -}; - -struct _EvolutionImporterClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_Importer__epv epv; -}; - -GType evolution_importer_get_type (void); - -EvolutionImporter *evolution_importer_new (EvolutionImporterCreateControlFn create_control_fn, - EvolutionImporterSupportFormatFn support_format_fn, - EvolutionImporterLoadFileFn load_file_fn, - EvolutionImporterProcessItemFn process_item_fn, - EvolutionImporterGetErrorFn get_error_fn, - void *closure); - -G_END_DECLS - -#endif diff --git a/shell/importer/evolution-intelligent-importer.c b/shell/importer/evolution-intelligent-importer.c deleted file mode 100644 index 48c767cfde..0000000000 --- a/shell/importer/evolution-intelligent-importer.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "evolution-intelligent-importer.h" - -#include <bonobo/bonobo-object.h> - -#include "GNOME_Evolution_Importer.h" - -#define PARENT_TYPE BONOBO_OBJECT_TYPE -static BonoboObjectClass *parent_class = NULL; - -struct _EvolutionIntelligentImporterPrivate { - EvolutionIntelligentImporterCanImportFn can_import_fn; - EvolutionIntelligentImporterImportDataFn import_data_fn; - - gchar *importername; - gchar *message; - gpointer closure; -}; - - -static inline EvolutionIntelligentImporter * -evolution_intelligent_importer_from_servant (PortableServer_Servant servant) -{ - return EVOLUTION_INTELLIGENT_IMPORTER (bonobo_object_from_servant (servant)); -} - -static CORBA_char * -impl_GNOME_Evolution_IntelligentImporter__get_importername (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionIntelligentImporter *ii; - - ii = evolution_intelligent_importer_from_servant (servant); - - return CORBA_string_dup (ii->priv->importername ? - ii->priv->importername : ""); -} - -static CORBA_char * -impl_GNOME_Evolution_IntelligentImporter__get_message (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionIntelligentImporter *ii; - - ii = evolution_intelligent_importer_from_servant (servant); - - return CORBA_string_dup (ii->priv->message ? - ii->priv->message : ""); -} - -static CORBA_boolean -impl_GNOME_Evolution_IntelligentImporter_canImport (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionIntelligentImporter *ii; - EvolutionIntelligentImporterPrivate *priv; - - ii = evolution_intelligent_importer_from_servant (servant); - priv = ii->priv; - - if (priv->can_import_fn != NULL) - return (priv->can_import_fn) (ii, priv->closure); - else - return FALSE; -} - -static void -impl_GNOME_Evolution_IntelligentImporter_importData (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - EvolutionIntelligentImporter *ii; - EvolutionIntelligentImporterPrivate *priv; - - ii = evolution_intelligent_importer_from_servant (servant); - priv = ii->priv; - - if (priv->import_data_fn) - (priv->import_data_fn) (ii, priv->closure); -} - - -static void -finalise (GObject *object) -{ - EvolutionIntelligentImporter *ii; - - ii = EVOLUTION_INTELLIGENT_IMPORTER (object); - - if (ii->priv == NULL) - return; - - g_free (ii->priv->importername); - g_free (ii->priv); - ii->priv = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -evolution_intelligent_importer_class_init (EvolutionIntelligentImporterClass *klass) -{ - GObjectClass *object_class; - POA_GNOME_Evolution_IntelligentImporter__epv *epv = &klass->epv; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = finalise; - - parent_class = g_type_class_ref(PARENT_TYPE); - epv->_get_importername = impl_GNOME_Evolution_IntelligentImporter__get_importername; - epv->_get_message = impl_GNOME_Evolution_IntelligentImporter__get_message; - epv->canImport = impl_GNOME_Evolution_IntelligentImporter_canImport; - epv->importData = impl_GNOME_Evolution_IntelligentImporter_importData; -} - -static void -evolution_intelligent_importer_init (EvolutionIntelligentImporter *ii) -{ - ii->priv = g_new0 (EvolutionIntelligentImporterPrivate, 1); -} - - -static void -evolution_intelligent_importer_construct (EvolutionIntelligentImporter *ii, - EvolutionIntelligentImporterCanImportFn can_import_fn, - EvolutionIntelligentImporterImportDataFn import_data_fn, - const gchar *importername, - const gchar *message, - gpointer closure) -{ - g_return_if_fail (ii != NULL); - ii->priv->importername = g_strdup (importername); - ii->priv->message = g_strdup (message); - - ii->priv->can_import_fn = can_import_fn; - ii->priv->import_data_fn = import_data_fn; - ii->priv->closure = closure; -} - -/** - * evolution_intelligent_importer_new: - * can_import_fn: The function that will be called to see if this importer can do - * anything. - * import_data_fn: The function that will be called when the importer should - * import the data. - * importername: The name of this importer. - * message: The message that will be displayed when the importer can import. - * closure: The data to be passed to @can_import_fn and @import_data_fn. - * - * Creates a new IntelligentImporter. - * - * Returns: A newly allocated EvolutionIntelligentImporter. - */ -EvolutionIntelligentImporter * -evolution_intelligent_importer_new (EvolutionIntelligentImporterCanImportFn can_import_fn, - EvolutionIntelligentImporterImportDataFn import_data_fn, - const gchar *importername, - const gchar *message, - gpointer closure) -{ - EvolutionIntelligentImporter *ii; - - ii = g_object_new (evolution_intelligent_importer_get_type (), NULL); - evolution_intelligent_importer_construct (ii, can_import_fn, - import_data_fn, importername, - message, closure); - return ii; -} - -BONOBO_TYPE_FUNC_FULL (EvolutionIntelligentImporter, - GNOME_Evolution_IntelligentImporter, - PARENT_TYPE, - evolution_intelligent_importer); diff --git a/shell/importer/evolution-intelligent-importer.h b/shell/importer/evolution-intelligent-importer.h deleted file mode 100644 index d9613d3f66..0000000000 --- a/shell/importer/evolution-intelligent-importer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef EVOLUTION_INTELLIGENT_IMPORTER_H -#define EVOLUTION_INTELLIGENT_IMPORTER_H - -#include <glib.h> -#include <bonobo/bonobo-object.h> -#include <importer/GNOME_Evolution_Importer.h> - -G_BEGIN_DECLS - -#define EVOLUTION_TYPE_INTELLIGENT_IMPORTER (evolution_intelligent_importer_get_type ()) -#define EVOLUTION_INTELLIGENT_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_TYPE_INTELLIGENT_IMPORTER, EvolutionIntelligentImporter)) -#define EVOLUTION_INTELLIGENT_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_TYPE_INTELLIGENT_IMPORTER, EvolutionIntelligentImporterClass)) -#define EVOLUTION_IS_INTELLIGENT_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_TYPE_INTELLIGENT_IMPORTER)) -#define EVOLUTION_IS_INTELLIGENT_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EVOLUTION_TYPE_INTELLIGENT_IMPORTER)) - -typedef struct _EvolutionIntelligentImporter EvolutionIntelligentImporter; -typedef struct _EvolutionIntelligentImporterPrivate EvolutionIntelligentImporterPrivate; -typedef struct _EvolutionIntelligentImporterClass EvolutionIntelligentImporterClass; - -typedef gboolean (* EvolutionIntelligentImporterCanImportFn) (EvolutionIntelligentImporter *ii, - gpointer closure); -typedef void (* EvolutionIntelligentImporterImportDataFn) (EvolutionIntelligentImporter *ii, - gpointer closure); - -struct _EvolutionIntelligentImporter { - BonoboObject parent; - - EvolutionIntelligentImporterPrivate *priv; -}; - -struct _EvolutionIntelligentImporterClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_IntelligentImporter__epv epv; -}; - -GType evolution_intelligent_importer_get_type (void); - -EvolutionIntelligentImporter *evolution_intelligent_importer_new (EvolutionIntelligentImporterCanImportFn can_import_fn, - EvolutionIntelligentImporterImportDataFn import_data_fn, - const gchar *importername, - const gchar *message, - gpointer closure); - -G_END_DECLS - -#endif diff --git a/shell/importer/import.glade b/shell/importer/import.glade deleted file mode 100644 index 389d2feee3..0000000000 --- a/shell/importer/import.glade +++ /dev/null @@ -1,124 +0,0 @@ -<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> -<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> - -<glade-interface> -<requires lib="gnome"/> - -<widget class="GtkWindow" id="importwizard"> - <property name="title" translatable="yes">Evolution Import Assistant</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - - <child> - <widget class="GnomeDruid" id="druid1"> - <property name="border_width">4</property> - <property name="visible">True</property> - <property name="show_help">False</property> - - <child> - <widget class="GnomeDruidPageEdge" id="page0"> - <property name="visible">True</property> - <property name="position">GNOME_EDGE_START</property> - <property name="title" translatable="yes">Evolution Import Assistant</property> - <property name="text" translatable="yes">Welcome to the Evolution Import Assistant. -With this assistant you will be guided through the process of -importing external files into Evolution.</property> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page1"> - <property name="visible">True</property> - <property name="title" translatable="yes">Importer Type</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox2"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page2-file"> - <property name="visible">True</property> - <property name="title" translatable="yes">Select a File</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox1"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page3-file"> - <property name="visible">True</property> - <property name="title" translatable="yes">Import Location</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox3"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageStandard" id="page2-intelligent"> - <property name="visible">True</property> - <property name="title" translatable="yes">Select Information to Import</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="druid-vbox3"> - <property name="border_width">16</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <placeholder/> - </child> - </widget> - </child> - </widget> - </child> - - <child> - <widget class="GnomeDruidPageEdge" id="page4"> - <property name="visible">True</property> - <property name="position">GNOME_EDGE_FINISH</property> - <property name="title" translatable="yes">Import File</property> - <property name="text" translatable="yes">Click "Import" to begin importing the file into Evolution. </property> - </widget> - </child> - </widget> - </child> -</widget> - -</glade-interface> diff --git a/shell/importer/intelligent.c b/shell/importer/intelligent.c deleted file mode 100644 index 8b7ebaa743..0000000000 --- a/shell/importer/intelligent.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Iain Holmes <iain@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "intelligent.h" - -#include <gtk/gtk.h> - -#include <libgnome/gnome-config.h> -#include <glib/gi18n.h> - -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-widget.h> - -#include "intelligent.h" -#include "GNOME_Evolution_Importer.h" - -/* Prototypes */ - -void intelligent_importer_init (void); - -/* End prototypes */ - -typedef struct { - CORBA_Object object; - Bonobo_Control control; - GtkWidget *widget; - - gchar *name; - gchar *blurb; - gchar *iid; -} IntelligentImporterData; - -typedef struct { - GtkWidget *dialog; - GtkWidget *placeholder; - GtkWidget *clist; - BonoboWidget *current; - - GList *importers; - - gint running; -} IntelligentImporterDialog; - -typedef struct { - CORBA_Object importer; - gchar *iid; -} SelectedImporterData; - -static void -free_importer_dialog (IntelligentImporterDialog *d) -{ - GList *l; - - for (l = d->importers; l; l = l->next) { - CORBA_Environment ev; - IntelligentImporterData *data; - - data = l->data; - - CORBA_exception_init (&ev); - if (data->object != CORBA_OBJECT_NIL) - bonobo_object_release_unref (data->object, &ev); - - g_free (data->iid); - g_free (data->name); - g_free (data->blurb); - g_free (data); - } - - g_list_free (d->importers); - gtk_widget_destroy (d->dialog); - g_free (d); -} - -static void -start_importers (GList *selected) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - for (; selected; selected = selected->next) { - SelectedImporterData *selection = selected->data; - - GNOME_Evolution_IntelligentImporter_importData (selection->importer, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Error importing %s\n%s", selection->iid, - CORBA_exception_id (&ev)); - } - } - CORBA_exception_free (&ev); -} - -static GList * -get_intelligent_importers (void) -{ - Bonobo_ServerInfoList *info_list; - GList *iids_ret = NULL; - CORBA_Environment ev; - gint i; - - CORBA_exception_init (&ev); - info_list = bonobo_activation_query ("repo_ids.has ('IDL:GNOME/Evolution/IntelligentImporter:" BASE_VERSION "')", NULL, &ev); - CORBA_exception_free (&ev); - - for (i = 0; i < info_list->_length; i++) { - const Bonobo_ServerInfo *info; - - info = info_list->_buffer + i; - iids_ret = g_list_prepend (iids_ret, g_strdup (info->iid)); - } - - return iids_ret; -} - -static void -select_row_cb (GtkCList *clist, - gint row, - gint column, - GdkEvent *ev, - IntelligentImporterDialog *d) -{ - gtk_notebook_set_current_page (GTK_NOTEBOOK (d->placeholder), row); -} - -static void -unselect_row_cb (GtkCList *clist, - gint row, - gint column, - GdkEvent *ev, - IntelligentImporterDialog *d) -{ - gtk_notebook_set_current_page (GTK_NOTEBOOK (d->placeholder), d->running); -} - -static IntelligentImporterDialog * -create_gui (GList *importers) -{ - GtkWidget *dialog, *clist, *sw, *label; - GtkWidget *hbox, *vbox, *dummy; - IntelligentImporterDialog *d; - GList *l; - gint running = 0; - - d = g_new (IntelligentImporterDialog, 1); - d->dialog = dialog = gtk_dialog_new(); - gtk_dialog_set_has_separator ((GtkDialog *) dialog, FALSE); - gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *)dialog)->vbox, 0); - gtk_container_set_border_width ((GtkContainer *) ((GtkDialog *)dialog)->action_area, 12); - - gtk_window_set_title((GtkWindow *)dialog, _("Importers")); - dummy = gtk_button_new_from_stock(GTK_STOCK_CONVERT); - gtk_button_set_label((GtkButton *)dummy, _("Import")); - gtk_dialog_add_action_widget((GtkDialog *)dialog, dummy, GTK_RESPONSE_ACCEPT); - - dummy = gtk_button_new_from_stock(GTK_STOCK_NO); - gtk_button_set_label((GtkButton *)dummy, _("Do not import")); - gtk_dialog_add_action_widget((GtkDialog *)dialog, dummy, GTK_RESPONSE_REJECT); - - dummy = gtk_button_new_from_stock(GTK_STOCK_CANCEL); - gtk_button_set_label((GtkButton *)dummy, _("Do not ask me again")); - gtk_dialog_add_action_widget((GtkDialog *)dialog, dummy, GTK_RESPONSE_CANCEL); - d->importers = NULL; - d->current = NULL; - - d->clist = clist = gtk_clist_new (1); - gtk_clist_set_selection_mode (GTK_CLIST (d->clist), GTK_SELECTION_MULTIPLE); - - label = gtk_label_new (_("Evolution can import data from the following files:")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label, - TRUE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 2); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 2); - - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, - TRUE, TRUE, 0); - - sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); - gtk_widget_set_size_request (sw, 300, 150); - gtk_container_add (GTK_CONTAINER (sw), clist); - gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 2); - gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); - - d->placeholder = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (d->placeholder), FALSE); - gtk_box_pack_start (GTK_BOX (vbox), d->placeholder, TRUE, TRUE, 0); - - for (l = importers; l; l = l->next) { - IntelligentImporterData *data; - CORBA_Environment ev; - gboolean dontaskagain, can_run; - gchar *text[1], *prefix; - - /* Check if we want to show this one again */ - prefix = g_strdup_printf ("=%s/evolution/config/Shell=/intelligent-importers/", g_get_home_dir ()); - gnome_config_push_prefix (prefix); - g_free (prefix); - - dontaskagain = gnome_config_get_bool (l->data); - gnome_config_pop_prefix (); - - if (dontaskagain) - continue; - - data = g_new0 (IntelligentImporterData, 1); - data->iid = g_strdup (l->data); - - CORBA_exception_init (&ev); - data->object = bonobo_activation_activate_from_id ((gchar *) data->iid, 0, - NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Could not start %s: %s", data->iid, - CORBA_exception_id (&ev)); - CORBA_exception_free (&ev); - - /* Clean up the IntelligentImporterData */ - g_free (data->iid); - g_free (data); - continue; - } - - CORBA_exception_free (&ev); - if (data->object == CORBA_OBJECT_NIL) { - g_warning ("Could not activate_component %s", data->iid); - g_free (data->iid); - g_free (data); - continue; - } - - CORBA_exception_init (&ev); - can_run = GNOME_Evolution_IntelligentImporter_canImport (data->object, - &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Could not get canImport(%s): %s", - data->iid, CORBA_exception_id (&ev)); - bonobo_object_release_unref (data->object, &ev); - CORBA_exception_free (&ev); - g_free (data->iid); - g_free (data); - continue; - } - CORBA_exception_free (&ev); - - if (can_run == FALSE) { - CORBA_exception_init (&ev); - bonobo_object_release_unref (data->object, &ev); - CORBA_exception_free (&ev); - g_free (data->iid); - g_free (data); - continue; - } - - running++; - - data->name = g_strdup (GNOME_Evolution_IntelligentImporter__get_importername (data->object, &ev)); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Could not get name(%s): %s", - data->iid, CORBA_exception_id (&ev)); - bonobo_object_release_unref (data->object, &ev); - CORBA_exception_free (&ev); - g_free (data->iid); - g_free (data); - continue; - } - - data->blurb = g_strdup (GNOME_Evolution_IntelligentImporter__get_message (data->object, &ev)); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Could not get message(%s): %s", - data->iid, CORBA_exception_id (&ev)); - bonobo_object_release_unref (data->object, &ev); - CORBA_exception_free (&ev); - g_free (data->iid); - g_free (data->name); - g_free (data); - continue; - } - - data->control = Bonobo_Unknown_queryInterface (data->object, - "IDL:Bonobo/Control:1.0", &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Could not QI for Bonobo/Control:1.0 %s:%s", - data->iid, CORBA_exception_id (&ev)); - bonobo_object_release_unref (data->object, &ev); - CORBA_exception_free (&ev); - g_free (data->iid); - g_free (data->name); - g_free (data->blurb); - continue; - } - if (data->control != CORBA_OBJECT_NIL) { - data->widget = bonobo_widget_new_control_from_objref (data->control, CORBA_OBJECT_NIL); - /* Ref this widget so even if we remove it from the - containers it will always have an extra ref. */ - gtk_widget_show (data->widget); - g_object_ref (data->widget); - } else { - data->widget = gtk_label_new (""); - } - - CORBA_exception_free (&ev); - - d->importers = g_list_prepend (d->importers, data); - gtk_notebook_prepend_page (GTK_NOTEBOOK (d->placeholder), - data->widget, NULL); - text[0] = data->name; - gtk_clist_prepend (GTK_CLIST (clist), text); - } - - d->running = running; - dummy = gtk_drawing_area_new (); - gtk_widget_show (dummy); - gtk_notebook_append_page (GTK_NOTEBOOK (d->placeholder), - dummy, NULL); - /* Set the start to the blank page */ - gtk_notebook_set_current_page (GTK_NOTEBOOK (d->placeholder), running); - - g_signal_connect((clist), "select-row", - G_CALLBACK (select_row_cb), d); - g_signal_connect((clist), "unselect-row", - G_CALLBACK (unselect_row_cb), d); - - gtk_widget_show_all (GTK_DIALOG (dialog)->vbox); - return d; -} - -void -intelligent_importer_init (void) -{ - GList *importers, *l, *selected = NULL; - IntelligentImporterDialog *d; - gchar *prefix; - gboolean dontaskagain; - gint resp; - - prefix = g_strdup_printf ("=%s/evolution/config/Shell=/intelligent-importers/", g_get_home_dir()); - gnome_config_push_prefix (prefix); - g_free (prefix); - - dontaskagain = gnome_config_get_bool ("Dontaskagain=False"); - gnome_config_pop_prefix (); - - if (dontaskagain) { - return; - } - - importers = get_intelligent_importers (); - if (importers == NULL) - return; /* No intelligent importers. Easy :) */ - - d = create_gui (importers); - if (d->running == 0) { - free_importer_dialog (d); - return; /* No runnable intelligent importers. */ - } - - resp = gtk_dialog_run((GtkDialog *)d->dialog); - gtk_widget_destroy(d->dialog); - switch (resp) { - case GTK_RESPONSE_ACCEPT: - /* Make a list of the importers */ - - /* FIXME: Sort this list and don't do it a slow way */ - for (l = GTK_CLIST (d->clist)->selection; l; l = l->next) { - IntelligentImporterData *data; - SelectedImporterData *new_data; - CORBA_Environment ev; - gchar *iid; - - data = g_list_nth_data (d->importers, GPOINTER_TO_INT (l->data)); - iid = g_strdup (data->iid); - - new_data = g_new (SelectedImporterData, 1); - new_data->iid = iid; - - /* Reference the remote object, and duplicate the - local one. */ - CORBA_exception_init (&ev); - new_data->importer = bonobo_object_dup_ref (data->object, &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Error duplicating %s\n%s", iid, - CORBA_exception_id (&ev)); - g_free (iid); - CORBA_exception_free (&ev); - g_free (new_data); - continue; - } - CORBA_exception_free (&ev); - - selected = g_list_prepend (selected, new_data); - } - - /* Now destroy all the importers, as we've kept references to - the ones we need */ - free_importer_dialog (d); - - if (selected != NULL) { - /* Restart the selected ones */ - start_importers (selected); - - /* Free the selected list */ - for (l = selected; l; l = l->next) { - CORBA_Environment ev; - SelectedImporterData *selection = l->data; - - CORBA_exception_init (&ev); - bonobo_object_release_unref (selection->importer, &ev); - CORBA_exception_free (&ev); - - g_free (selection->iid); - g_free (selection); - } - g_list_free (selected); - } - - break; - - case GTK_RESPONSE_CANCEL: /* Dont ask again */ - prefix = g_strdup_printf ("=%s/evolution/config/Shell=/intelligent-importers/", g_get_home_dir()); - gnome_config_push_prefix (prefix); - g_free (prefix); - - gnome_config_set_bool ("Dontaskagain", TRUE); - gnome_config_pop_prefix (); - - gnome_config_sync (); - gnome_config_drop_all (); - g_print ("Not asking again"); - free_importer_dialog (d); - break; - - default: - case GTK_RESPONSE_REJECT: /* No button */ - free_importer_dialog (d); - break; - } - - g_list_free (importers); -} diff --git a/shell/main.c b/shell/main.c index 21cc278c7f..72333c17f7 100644 --- a/shell/main.c +++ b/shell/main.c @@ -23,6 +23,7 @@ #include <config.h> #include <gtk/gtk.h> +#include <gdk/gdkx.h> /* for copied UniqueApp code */ #include <glib/gstdio.h> #ifdef G_OS_WIN32 @@ -40,12 +41,10 @@ #include "e-util/e-bconf-map.h" #include <e-util/e-icon-factory.h> -#include "e-shell-constants.h" #include "e-util/e-profile-event.h" #include "e-util/e-util.h" #include "e-shell.h" -#include "es-menu.h" #include "es-event.h" #include "e-util/e-util-private.h" @@ -57,22 +56,13 @@ #include <gconf/gconf-client.h> #include <glib/gi18n.h> -#include <libgnome/gnome-sound.h> -#include <libgnomeui/gnome-ui-init.h> -#include <libgnomeui/gnome-client.h> - -#include <bonobo/bonobo-main.h> -#include <bonobo/bonobo-moniker-util.h> -#include <bonobo/bonobo-exception.h> - -#include <bonobo-activation/bonobo-activation.h> +#include <libedataserver/e-categories.h> #include <libedataserverui/e-passwords.h> #include <glade/glade.h> #include "e-config-upgrade.h" -#include "Evolution-DataServer.h" #include <misc/e-cursors.h> #include "e-util/e-error.h" @@ -98,13 +88,11 @@ #define DEVELOPMENT 1 #endif -static EShell *shell = NULL; - /* Command-line options. */ static gboolean start_online = FALSE; static gboolean start_offline = FALSE; static gboolean setup_only = FALSE; -static gboolean killev = FALSE; +static gboolean force_shutdown = FALSE; #ifdef DEVELOPMENT static gboolean force_migrate = FALSE; #endif @@ -112,84 +100,43 @@ static gboolean disable_eplugin = FALSE; static gboolean disable_preview = FALSE; static gboolean idle_cb (gchar **uris); -static gchar *default_component_id = NULL; +static gchar *requested_view = NULL; static gchar *evolution_debug_log = NULL; static gchar **remaining_args; -static void -no_windows_left_cb (EShell *shell, gpointer data) -{ - bonobo_object_unref (BONOBO_OBJECT (shell)); - bonobo_main_quit (); -} - -static void -shell_weak_notify (gpointer data, - GObject *where_the_object_was) -{ - bonobo_main_quit (); -} - -#ifdef KILL_PROCESS_CMD +/* Defined in <e-shell.h> */ +extern EShell *default_shell; static void -kill_dataserver (void) +categories_icon_theme_hack (void) { - g_message ("Killing old version of evolution-data-server..."); - - system (KILL_PROCESS_CMD " -9 lt-evolution-data-server 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.0 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.2 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.4 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.6 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.8 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.10 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-data-server-1.12 2> /dev/null"); - - system (KILL_PROCESS_CMD " -9 lt-evolution-alarm-notify 2> /dev/null"); - system (KILL_PROCESS_CMD " -9 evolution-alarm-notify 2> /dev/null"); + GtkIconTheme *icon_theme; + const gchar *category_name; + const gchar *filename; + gchar *dirname; + + /* XXX Allow the category icons to be referenced as named + * icons, since GtkAction does not support GdkPixbufs. */ + + /* Get the icon file for some default category. Doesn't matter + * which, so long as it has an icon. We're just interested in + * the directory components. */ + category_name = _("Birthday"); + filename = e_categories_get_icon_file_for (category_name); + g_return_if_fail (filename != NULL && *filename != '\0'); + + /* Extract the directory components. */ + dirname = g_path_get_dirname (filename); + + /* Add it to the icon theme's search path. This relies on + * GtkIconTheme's legacy feature of using image files found + * directly in the search path. */ + icon_theme = gtk_icon_theme_get_default (); + gtk_icon_theme_append_search_path (icon_theme, dirname); + + g_free (dirname); } -static void -kill_old_dataserver (void) -{ - GNOME_Evolution_DataServer_InterfaceCheck iface; - CORBA_Environment ev; - CORBA_char *version; - - CORBA_exception_init (&ev); - - /* FIXME Should we really kill it off? We also shouldn't hard code the version */ - iface = bonobo_activation_activate_from_id ( - (Bonobo_ActivationID) "OAFIID:GNOME_Evolution_DataServer_InterfaceCheck", 0, NULL, &ev); - if (BONOBO_EX (&ev) || iface == CORBA_OBJECT_NIL) { - kill_dataserver (); - CORBA_exception_free (&ev); - return; - } - - version = GNOME_Evolution_DataServer_InterfaceCheck__get_interfaceVersion (iface, &ev); - if (BONOBO_EX (&ev)) { - kill_dataserver (); - CORBA_Object_release (iface, &ev); - CORBA_exception_free (&ev); - return; - } - - if (strcmp (version, DATASERVER_VERSION) != 0) { - CORBA_free (version); - kill_dataserver (); - CORBA_Object_release (iface, &ev); - CORBA_exception_free (&ev); - return; - } - - CORBA_free (version); - CORBA_Object_release (iface, &ev); - CORBA_exception_free (&ev); -} -#endif - #ifdef DEVELOPMENT /* Warning dialog to scare people off a little bit. */ @@ -269,8 +216,6 @@ show_development_warning(void) gtk_widget_destroy (warning_dialog); - idle_cb (NULL); - return skip; } @@ -291,124 +236,26 @@ destroy_config (GConfClient *client) #endif /* DEVELOPMENT */ -static void -open_uris (GNOME_Evolution_Shell corba_shell, gchar **uris) -{ - CORBA_Environment ev; - guint n_uris, ii; - - g_return_if_fail (uris != NULL); - n_uris = g_strv_length (uris); - - CORBA_exception_init (&ev); - - for (ii = 0; ii < n_uris; ii++) { - GNOME_Evolution_Shell_handleURI (corba_shell, uris[ii], &ev); - if (ev._major != CORBA_NO_EXCEPTION) { - g_warning ("Invalid URI: %s", uris[ii]); - CORBA_exception_free (&ev); - } - } - - CORBA_exception_free (&ev); -} - /* This is for doing stuff that requires the GTK+ loop to be running already. */ static gboolean idle_cb (gchar **uris) { - GNOME_Evolution_Shell corba_shell; - CORBA_Environment ev; - EShellConstructResult result; - EShellStartupLineMode startup_line_mode; - - g_return_val_if_fail (uris == NULL || g_strv_length (uris) > 0, FALSE); - -#ifdef KILL_PROCESS_CMD - kill_old_dataserver (); -#endif + EShell *shell; - CORBA_exception_init (&ev); - - if (! start_online && ! start_offline) - startup_line_mode = E_SHELL_STARTUP_LINE_MODE_CONFIG; - else if (start_online) - startup_line_mode = E_SHELL_STARTUP_LINE_MODE_ONLINE; - else - startup_line_mode = E_SHELL_STARTUP_LINE_MODE_OFFLINE; - - shell = e_shell_new (startup_line_mode, &result); - - switch (result) { - case E_SHELL_CONSTRUCT_RESULT_OK: - e_shell_set_crash_recovery (shell, e_file_lock_exists ()); - g_signal_connect (shell, "no_windows_left", G_CALLBACK (no_windows_left_cb), NULL); - g_object_weak_ref (G_OBJECT (shell), shell_weak_notify, NULL); - corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell)); - corba_shell = CORBA_Object_duplicate (corba_shell, &ev); - break; - - case E_SHELL_CONSTRUCT_RESULT_CANNOTREGISTER: - corba_shell = bonobo_activation_activate_from_id ( - (Bonobo_ActivationID) E_SHELL_OAFIID, 0, NULL, &ev); - if (ev._major != CORBA_NO_EXCEPTION || corba_shell == CORBA_OBJECT_NIL) { - e_error_run(NULL, "shell:noshell", NULL); - CORBA_exception_free (&ev); - bonobo_main_quit (); - return FALSE; - } - break; + shell = e_shell_get_default (); - default: - e_error_run(NULL, "shell:noshell-reason", - e_shell_construct_result_to_string(result), NULL); - CORBA_exception_free (&ev); - bonobo_main_quit (); - return FALSE; + /* These calls do the right thing when another Evolution + * process is running. */ + if (uris != NULL && *uris != NULL) { + if (e_shell_handle_uris (shell, uris) == 0) + gtk_main_quit (); + } else + e_shell_create_shell_window (shell, requested_view); - } - - if (shell != NULL) { - if (uris != NULL) - open_uris (corba_shell, uris); - else { - e_file_lock_create (); - e_shell_create_window (shell, default_component_id, NULL); - } - } else { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - if (uris != NULL) - open_uris (corba_shell, uris); - else - if (default_component_id == NULL) - GNOME_Evolution_Shell_createNewWindow (corba_shell, "", &ev); - else - GNOME_Evolution_Shell_createNewWindow (corba_shell, default_component_id, &ev); - - CORBA_exception_free (&ev); - } - - CORBA_Object_release (corba_shell, &ev); - - CORBA_exception_free (&ev); - - if (shell == NULL) { - /*there is another instance but because we don't open any windows - we must notify the startup was complete manually*/ - gdk_notify_startup_complete (); - bonobo_main_quit (); - } - - /* This must be done after Bonobo has created all the components. For - * example the mail component makes the global variable `session` which - * is being used by several EPlugins */ - - if (!disable_eplugin) { - e_plugin_load_plugins_with_missing_symbols (); - } + /* If another Evolution process is running, we're done. */ + if (unique_app_is_running (UNIQUE_APP (shell))) + gtk_main_quit (); return FALSE; } @@ -470,27 +317,15 @@ setup_segv_redirect (void) #define setup_segv_redirect() (void)0 #endif -static gint -gnome_master_client_save_yourself_cb (GnomeClient *client, GnomeSaveStyle save_style, gint shutdown, GnomeInteractStyle interact_style, gint fast, gpointer user_data) -{ - return !shell || e_shell_can_quit (shell); -} - -static void -gnome_master_client_die_cb (GnomeClient *client) -{ - e_shell_do_quit (shell); -} - -static const GOptionEntry options[] = { - { "component", 'c', 0, G_OPTION_ARG_STRING, &default_component_id, +static GOptionEntry entries[] = { + { "component", 'c', 0, G_OPTION_ARG_STRING, &requested_view, N_("Start Evolution activating the specified component"), NULL }, { "offline", '\0', 0, G_OPTION_ARG_NONE, &start_offline, N_("Start in offline mode"), NULL }, { "online", '\0', 0, G_OPTION_ARG_NONE, &start_online, N_("Start in online mode"), NULL }, #ifdef KILL_PROCESS_CMD - { "force-shutdown", '\0', 0, G_OPTION_ARG_NONE, &killev, + { "force-shutdown", '\0', 0, G_OPTION_ARG_NONE, &force_shutdown, N_("Forcibly shut down all Evolution components"), NULL }, #endif #ifdef DEVELOPMENT @@ -514,8 +349,7 @@ static void set_paths (void) { /* Set PATH to include the Evolution executable's folder - * and the lib/evolution/$(BASE_VERSION)/components folder. - */ + * and the lib/evolution/$(BASE_VERSION)/components folder. */ wchar_t exe_filename[MAX_PATH]; wchar_t *p; gchar *exe_folder_utf8; @@ -536,60 +370,99 @@ set_paths (void) *p = L'\0'; top_folder_utf8 = g_utf16_to_utf8 (exe_filename, -1, NULL, NULL, NULL); - components_folder_utf8 = - g_strconcat (top_folder_utf8, - "/lib/evolution/" BASE_VERSION "/components", - NULL); - - path = g_build_path (";", - exe_folder_utf8, - components_folder_utf8, - g_getenv ("PATH"), - NULL); + components_folder_utf8 = g_strconcat ( + top_folder_utf8, "/lib/evolution/" + BASE_VERSION "/components", NULL); + + path = g_build_path ( + ";", exe_folder_utf8, + components_folder_utf8, g_getenv ("PATH"), NULL); if (!g_setenv ("PATH", path, TRUE)) - g_warning ("Could not set PATH for Evolution and its child processes"); + g_warning ("Could not set PATH for Evolution " + "and its child processes"); g_free (path); g_free (exe_folder_utf8); g_free (components_folder_utf8); - /* Set BONOBO_ACTIVATION_PATH */ - if (g_getenv ("BONOBO_ACTIVATION_PATH" ) == NULL) { - path = g_build_filename (top_folder_utf8, - "lib/bonobo/servers", - NULL); - if (!g_setenv ("BONOBO_ACTIVATION_PATH", path, TRUE)) - g_warning ("Could not set BONOBO_ACTIVATION_PATH"); - g_free (path); - } g_free (top_folder_utf8); } #endif +static void +shell_window_destroyed_cb (EShell *shell) +{ + if (e_shell_get_watched_windows (shell) == NULL) + gtk_main_quit (); +} + +static void +create_default_shell (void) +{ + EShell *shell; + GConfClient *client; + gboolean online = TRUE; + GError *error = NULL; + + client = gconf_client_get_default (); + + if (start_online) + online = TRUE; + else if (start_offline) + online = FALSE; + else { + const gchar *key; + gboolean value; + + key = "/apps/evolution/shell/start_offline"; + value = gconf_client_get_bool (client, key, &error); + if (error == NULL) + online = !value; + else { + g_warning ("%s", error->message); + g_error_free (error); + } + } + + shell = g_object_new ( + E_TYPE_SHELL, + "name", "org.gnome.evolution", + "online", online, + NULL); + + g_signal_connect ( + shell, "window-destroyed", + G_CALLBACK (shell_window_destroyed_cb), NULL); + + g_object_unref (client); + + /* EShell keeps its own reference to the first instance for use + * in e_shell_get_default(), so it's safe to unreference here. */ + g_object_unref (shell); + + g_idle_add ((GSourceFunc) idle_cb, remaining_args); +} + gint main (gint argc, gchar **argv) { #ifdef G_OS_WIN32 - if (fileno (stdout) != -1 && - _get_osfhandle (fileno (stdout)) != -1) - { - /* stdout is fine, presumably redirected to a file or pipe */ - } - else - { - typedef BOOL (* WINAPI AttachConsole_t) (DWORD); + if (fileno (stdout) != -1 && _get_osfhandle (fileno (stdout)) != -1) { + /* stdout is fine, presumably redirected to a file or pipe */ + } else { + typedef BOOL (* WINAPI AttachConsole_t) (DWORD); - AttachConsole_t p_AttachConsole = - (AttachConsole_t) GetProcAddress (GetModuleHandle ("kernel32.dll"), "AttachConsole"); + AttachConsole_t p_AttachConsole = + (AttachConsole_t) GetProcAddress ( + GetModuleHandle ("kernel32.dll"), "AttachConsole"); - if (p_AttachConsole != NULL && p_AttachConsole (ATTACH_PARENT_PROCESS)) + if (p_AttachConsole != NULL && p_AttachConsole (ATTACH_PARENT_PROCESS)) { - freopen ("CONOUT$", "w", stdout); - dup2 (fileno (stdout), 1); - freopen ("CONOUT$", "w", stderr); - dup2 (fileno (stderr), 2); - - } + freopen ("CONOUT$", "w", stdout); + dup2 (fileno (stdout), 1); + freopen ("CONOUT$", "w", stderr); + dup2 (fileno (stderr), 2); + } } extern void link_shutdown (void); @@ -599,10 +472,8 @@ main (gint argc, gchar **argv) #ifdef DEVELOPMENT gboolean skip_warning_dialog; #endif - GnomeProgram *program; - GnomeClient *master_client; - GOptionContext *context; gchar *filename; + GError *error = NULL; /* Make ElectricFence work. */ free (malloc (10)); @@ -611,21 +482,19 @@ main (gint argc, gchar **argv) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - context = g_option_context_new (_("- The Evolution PIM and Email Client")); - - g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE); - - g_option_context_set_translation_domain(context, GETTEXT_PACKAGE); - #ifdef G_OS_WIN32 set_paths (); #endif - program = gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE, argc, argv, - GNOME_PROGRAM_STANDARD_PROPERTIES, - GNOME_PARAM_GOPTION_CONTEXT, context, - GNOME_PARAM_HUMAN_READABLE_NAME, _("Evolution"), - NULL); + gtk_init_with_args ( + &argc, &argv, + _("- The Evolution PIM and Email Client"), + entries, (gchar *) GETTEXT_PACKAGE, &error); + if (error != NULL) { + g_printerr ("%s\n", error->message); + g_error_free (error); + exit (1); + } #ifdef G_OS_WIN32 if (strcmp (gettext (""), "") == 0) { @@ -639,15 +508,14 @@ main (gint argc, gchar **argv) } #endif if (start_online && start_offline) { - fprintf (stderr, _("%s: --online and --offline cannot be used together.\n Use %s --help for more information.\n"), + g_printerr (_("%s: --online and --offline cannot be used together.\n Use %s --help for more information.\n"), argv[0], argv[0]); exit (1); } - if (killev) { - filename = g_build_filename (EVOLUTION_TOOLSDIR, - "killev", - NULL); + if (force_shutdown) { + filename = g_build_filename ( + EVOLUTION_TOOLSDIR, "killev", NULL); execl (filename, "killev", NULL); /* Not reached */ exit (0); @@ -656,11 +524,10 @@ main (gint argc, gchar **argv) client = gconf_client_get_default (); #ifdef DEVELOPMENT - - if (force_migrate) { + if (force_migrate) destroy_config (client); - } #endif + if (disable_preview) { gconf_client_set_bool (client, "/apps/evolution/mail/display/show_preview", FALSE, NULL); gconf_client_set_bool (client, "/apps/evolution/mail/display/safe_list", TRUE, NULL); @@ -682,37 +549,19 @@ main (gint argc, gchar **argv) g_warning ("Could not set up debugging output file."); } - master_client = gnome_master_client (); - - g_signal_connect (G_OBJECT (master_client), "save_yourself", G_CALLBACK (gnome_master_client_save_yourself_cb), NULL); - g_signal_connect (G_OBJECT (master_client), "die", G_CALLBACK (gnome_master_client_die_cb), NULL); - glade_init (); e_cursors_init (); e_icon_factory_init (); - e_passwords_init(); + e_passwords_init (); gtk_window_set_default_icon_name ("evolution"); if (setup_only) exit (0); - gnome_sound_init ("localhost"); + categories_icon_theme_hack (); gtk_accel_map_load (e_get_accels_filename ()); - if (!disable_eplugin) { - e_plugin_register_type(e_plugin_lib_get_type()); - e_plugin_hook_register_type(es_menu_hook_get_type()); - e_plugin_hook_register_type(es_event_hook_get_type()); -#ifdef ENABLE_PROFILING - e_plugin_hook_register_type(e_profile_event_hook_get_type()); -#endif - e_plugin_hook_register_type(e_plugin_type_hook_get_type()); - e_plugin_hook_register_type(e_import_hook_get_type()); - e_plugin_hook_register_type(E_TYPE_PLUGIN_UI_HOOK); - e_plugin_load_plugins (); - } - #ifdef DEVELOPMENT skip_warning_dialog = gconf_client_get_bool ( client, SKIP_WARNING_DIALOG_KEY, NULL); @@ -721,24 +570,41 @@ main (gint argc, gchar **argv) gconf_client_set_bool ( client, SKIP_WARNING_DIALOG_KEY, show_development_warning (), NULL); - else - g_idle_add ((GSourceFunc) idle_cb, remaining_args); - -#else - g_idle_add ((GSourceFunc) idle_cb, remaining_args); #endif + g_object_unref (client); - bonobo_main (); + create_default_shell (); + + if (!disable_eplugin) { + /* Register built-in plugin hook types. */ + es_event_hook_get_type (); +#ifdef ENABLE_PROFILING + e_profile_event_hook_get_type (); +#endif + e_import_hook_get_type (); + e_plugin_ui_hook_get_type (); + + /* All EPlugin and EPluginHook subclasses should be + * registered in GType now, so load plugins now. */ + e_plugin_load_plugins (); + } + + gtk_main (); + + /* Drop what should be the last reference to the shell. + * Emit a warning if references are leaking somewhere. */ + g_object_unref (default_shell); + if (E_IS_SHELL (default_shell)) + g_warning ("Shell not finalized on exit"); gtk_accel_map_save (e_get_accels_filename ()); e_icon_factory_shutdown (); - g_object_unref (program); - gnome_sound_shutdown (); e_cursors_shutdown (); #ifdef G_OS_WIN32 link_shutdown (); #endif + return 0; } diff --git a/shell/shell.error.xml b/shell/shell.error.xml index 7ae57dec58..603d5ed955 100644 --- a/shell/shell.error.xml +++ b/shell/shell.error.xml @@ -16,9 +16,8 @@ You will need to make more space available in your home directory before you can </error> <error id="upgrade-failed" type="error"> - <_primary>Upgrade from previous version failed: -{0}</_primary> - <_secondary xml:space="preserve">{1} + <_primary>Upgrade from previous version failed:</_primary> + <_secondary xml:space="preserve">{0} If you choose to continue, you may not have access to some of your old data. </_secondary> @@ -51,28 +50,6 @@ Once deleted, you cannot downgrade to the previous version of Evolution without <button stock="gtk-delete" response="GTK_RESPONSE_OK"/> </error> - <error id="noshell" type="error"> - <_title>Cannot start Evolution</_title> - <_primary>Evolution can not start.</_primary> - <_secondary xml:space="preserve">Your system configuration does not match your Evolution configuration. - -Click help for details</_secondary> - <help uri="http://go-evolution.org/FAQ#What_does_.22Your_system_configuration_does_not_match_your_Evolution_configuration.22_mean.3F"/> - <button stock="gtk-quit" response="GTK_RESPONSE_CANCEL"/> - </error> - - <error id="noshell-reason" type="error"> - <_title>Cannot start Evolution</_title> - <_primary>Evolution can not start.</_primary> - <_secondary xml:space="preserve">Your system configuration does not match your Evolution configuration: - -{0} - -Click help for details.</_secondary> - <help uri="http://go-evolution.org/FAQ#What_does_.22Your_system_configuration_does_not_match_your_Evolution_configuration.22_mean.3F"/> - <button stock="gtk-quit" response="GTK_RESPONSE_CANCEL"/> - </error> - <error id="forget-passwords" type="question" default="GTK_RESPONSE_CANCEL"> <_primary>Are you sure you want to forget all remembered passwords?</_primary> <_secondary xml:space="preserve">Forgetting your passwords will clear all remembered passwords. You will be reprompted next time they are needed.</_secondary> diff --git a/shell/test/GNOME_Evolution_Test.server.in.in b/shell/test/GNOME_Evolution_Test.server.in.in deleted file mode 100644 index ef0db8b1ac..0000000000 --- a/shell/test/GNOME_Evolution_Test.server.in.in +++ /dev/null @@ -1,39 +0,0 @@ -<oaf_info> - - <!-- (factory) --> - <oaf_server iid="OAFIID:GNOME_Evolution_Test_Factory:@VERSION@" - type="shlib" - location="@COMPONENTDIR_IN_SERVER_FILE@/libevolution-test@SOEXT@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/ObjectFactory:1.0"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" - _value="Evolution Test"/> - </oaf_server> - - <!-- Component Interface --> - - <oaf_server iid="OAFIID:GNOME_Evolution_Test_Component:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Test_Factory:@VERSION@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/Evolution/Component:@VERSION@"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" _value="Evolution Test component"/> - - <oaf_attribute name="evolution:component_alias" type="string" value="test"/> - - <oaf_attribute name="evolution:button_label" type="string" _value="Test"/> - <oaf_attribute name="evolution:button_sort_order" type="string" value="-1"/> - <oaf_attribute name="evolution:button_icon" type="string" value="stock_mail"/> - - <oaf_attribute name="evolution:component_icon" type="string" value="stock_mail"/> - <oaf_attribute name="evolution:component_display_order" type="number" value="1"/> - - </oaf_server> - -</oaf_info> diff --git a/shell/test/Makefile.am b/shell/test/Makefile.am index 8a2efd8a4a..10b1bfb81b 100644 --- a/shell/test/Makefile.am +++ b/shell/test/Makefile.am @@ -1,37 +1,27 @@ -component_LTLIBRARIES = libevolution-test.la +module_LTLIBRARIES = libevolution-module-test.la AM_CPPFLAGS = \ + -I$(top_srcdir) \ -I$(top_srcdir)/shell \ + -I$(top_srcdir)/widgets \ + -I$(top_srcdir)/widgets/menus \ -I$(top_srcdir)/widgets/misc \ -I$(top_builddir)/shell \ -DG_LOG_DOMAIN=\"evolution-test\" \ $(EVOLUTION_TEST_CFLAGS) -libevolution_test_la_SOURCES = \ - evolution-test-component.c \ - evolution-test-component.h +libevolution_module_test_la_SOURCES = \ + evolution-module-test.c \ + e-test-shell-backend.c \ + e-test-shell-backend.h \ + e-test-shell-view.c \ + e-test-shell-view.h -libevolution_test_la_LIBADD = \ +libevolution_module_test_la_LIBADD = \ $(top_builddir)/shell/libeshell.la \ $(EVOLUTION_TEST_LIBS) -libevolution_test_la_LDFLAGS = \ +libevolution_module_test_la_LDFLAGS = \ -avoid-version -module $(NO_UNDEFINED) -testserver_in_files = GNOME_Evolution_Test.server.in.in -testserver_DATA = $(testserver_in_files:.server.in.in=.server) -testserverdir = $(serverdir) -@EVO_SERVER_RULE@ -@INTLTOOL_SERVER_RULE@ - -BUILT_SOURCES = $(testserver_DATA) -CLEANFILES = $(BUILT_SOURCES) - -EXTRA_DIST = \ - $(testserver_in_files) \ - GNOME_Evolution_Test.server.in.in - -dist-hook: - cd $(distdir); rm -f $(BUILD_SOURCES) - -include $(top_srcdir)/git.mk diff --git a/shell/test/e-test-shell-backend.c b/shell/test/e-test-shell-backend.c new file mode 100644 index 0000000000..6a6c03bddd --- /dev/null +++ b/shell/test/e-test-shell-backend.c @@ -0,0 +1,222 @@ +/* + * e-test-shell-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-test-shell-backend.h" + +#include <glib/gi18n.h> + +#include "shell/e-shell.h" +#include "shell/e-shell-window.h" + +#include "e-test-shell-view.h" + +#define E_TEST_SHELL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TEST_SHELL_BACKEND, ETestShellBackendPrivate)) + +struct _ETestShellBackendPrivate { + gint placeholder; +}; + +static gpointer parent_class; +static GType test_shell_backend_type; + +static void +action_test_item_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + g_debug ("%s", G_STRFUNC); +} + +static void +action_test_source_new_cb (GtkAction *action, + EShellWindow *shell_window) +{ + g_debug ("%s", G_STRFUNC); +} + +static GtkActionEntry item_entries[] = { + + { "test-item-new", + "document-new", + NC_("New", "_Test Item"), + NULL, + N_("Create a new test item"), + G_CALLBACK (action_test_item_new_cb) } +}; + +static GtkActionEntry source_entries[] = { + + { "test-source-new", + "folder-new", + NC_("New", "Test _Source"), + NULL, + N_("Create a new test source"), + G_CALLBACK (action_test_source_new_cb) } +}; + +static void +test_shell_backend_start (EShellBackend *shell_backend) +{ + g_debug ("%s", G_STRFUNC); +} + +static gboolean +test_shell_backend_migrate (EShellBackend *shell_backend, + gint major, + gint minor, + gint micro, + GError **error) +{ + g_debug ("%s (from %d.%d.%d)", G_STRFUNC, major, minor, micro); + + return TRUE; +} + +static gboolean +test_shell_backend_handle_uri_cb (EShellBackend *shell_backend, + const gchar *uri) +{ + g_debug ("%s (uri=%s)", G_STRFUNC, uri); + + return FALSE; +} + +static void +test_shell_backend_send_receive_cb (EShellBackend *shell_backend, + GtkWindow *parent_window) +{ + g_debug ("%s (window=%p)", G_STRFUNC, parent_window); +} + +static void +test_shell_backend_window_created_cb (EShellBackend *shell_backend, + GtkWindow *window) +{ + const gchar *backend_name; + + g_debug ("%s (%s)", G_STRFUNC, G_OBJECT_TYPE_NAME (window)); + + if (!E_IS_SHELL_WINDOW (window)) + return; + + backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; + + e_shell_window_register_new_item_actions ( + E_SHELL_WINDOW (window), backend_name, + item_entries, G_N_ELEMENTS (item_entries)); + + e_shell_window_register_new_source_actions ( + E_SHELL_WINDOW (window), backend_name, + source_entries, G_N_ELEMENTS (source_entries)); +} + +static void +test_shell_backend_window_destroyed_cb (EShellBackend *shell_backend) +{ + g_debug ("%s", G_STRFUNC); +} + +static void +test_shell_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + g_signal_connect_swapped ( + shell, "handle-uri", + G_CALLBACK (test_shell_backend_handle_uri_cb), + shell_backend); + + g_signal_connect_swapped ( + shell, "send-receive", + G_CALLBACK (test_shell_backend_send_receive_cb), + shell_backend); + + g_signal_connect_swapped ( + shell, "window-created", + G_CALLBACK (test_shell_backend_window_created_cb), + shell_backend); + + g_signal_connect_swapped ( + shell, "window-destroyed", + G_CALLBACK (test_shell_backend_window_destroyed_cb), + shell_backend); +} + +static void +test_shell_backend_class_init (ETestShellBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETestShellBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = test_shell_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->shell_view_type = E_TYPE_TEST_SHELL_VIEW; + shell_backend_class->name = "test"; + shell_backend_class->aliases = "monkey"; + shell_backend_class->schemes = ""; + shell_backend_class->sort_order = 100; + shell_backend_class->start = test_shell_backend_start; + shell_backend_class->migrate = test_shell_backend_migrate; +} + +static void +test_shell_backend_init (ETestShellBackend *test_shell_backend) +{ + test_shell_backend->priv = + E_TEST_SHELL_BACKEND_GET_PRIVATE (test_shell_backend); +} + +GType +e_test_shell_backend_get_type (void) +{ + return test_shell_backend_type; +} + +void +e_test_shell_backend_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ETestShellBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) test_shell_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETestShellBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) test_shell_backend_init, + NULL /* value_table */ + }; + + test_shell_backend_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_BACKEND, + "ETestShellBackend", &type_info, 0); +} diff --git a/shell/test/e-test-shell-backend.h b/shell/test/e-test-shell-backend.h new file mode 100644 index 0000000000..0d342bfbcc --- /dev/null +++ b/shell/test/e-test-shell-backend.h @@ -0,0 +1,67 @@ +/* + * e-test-shell-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TEST_SHELL_BACKEND_H +#define E_TEST_SHELL_BACKEND_H + +#include <shell/e-shell-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_TEST_SHELL_BACKEND \ + (e_test_shell_backend_get_type ()) +#define E_TEST_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TEST_SHELL_BACKEND, ETestShellBackend)) +#define E_TEST_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TEST_SHELL_BACKEND, ETestShellBackendClass)) +#define E_IS_TEST_SHELL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TEST_SHELL_BACKEND)) +#define E_IS_TEST_SHELL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TEST_SHELL_BACKEND)) +#define E_TEST_SHELL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TEST_SHELL_BACKEND, ETestShellBackendClass)) + +G_BEGIN_DECLS + +typedef struct _ETestShellBackend ETestShellBackend; +typedef struct _ETestShellBackendClass ETestShellBackendClass; +typedef struct _ETestShellBackendPrivate ETestShellBackendPrivate; + +struct _ETestShellBackend { + EShellBackend parent; + ETestShellBackendPrivate *priv; +}; + +struct _ETestShellBackendClass { + EShellBackendClass parent_class; +}; + +GType e_test_shell_backend_get_type (void); +void e_test_shell_backend_register_type + (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_TEST_SHELL_BACKEND_H */ diff --git a/shell/test/e-test-shell-view.c b/shell/test/e-test-shell-view.c new file mode 100644 index 0000000000..b4464cc68f --- /dev/null +++ b/shell/test/e-test-shell-view.c @@ -0,0 +1,155 @@ +/* + * e-test-shell-view.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-test-shell-view.h" + +#include "shell/e-shell-content.h" +#include "shell/e-shell-sidebar.h" + +#define E_TEST_SHELL_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TEST_SHELL_VIEW, ETestShellViewPrivate)) + +struct _ETestShellViewPrivate { + EActivity *activity; +}; + +static gpointer parent_class; +static GType test_shell_view_type; + +static void +test_shell_view_toggled (EShellView *shell_view) +{ +#if 0 + gboolean is_active; + const gchar *active; + + is_active = e_shell_view_is_active (shell_view); + active = is_active ? "active" : "inactive"; + g_debug ("%s (now %s)", G_STRFUNC, active); +#endif +} + +static void +test_shell_view_dispose (GObject *object) +{ + ETestShellViewPrivate *priv; + + priv = E_TEST_SHELL_VIEW_GET_PRIVATE (object); + + if (priv->activity != NULL) { + e_activity_complete (priv->activity); + g_object_unref (priv->activity); + priv->activity = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +test_shell_view_constructed (GObject *object) +{ + ETestShellViewPrivate *priv; + EShellContent *shell_content; + EShellSidebar *shell_sidebar; + EShellBackend *shell_backend; + EShellView *shell_view; + EActivity *activity; + GtkWidget *widget; + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); + + priv = E_TEST_SHELL_VIEW_GET_PRIVATE (object); + + shell_view = E_SHELL_VIEW (object); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + + widget = gtk_label_new ("Content Widget"); + gtk_container_add (GTK_CONTAINER (shell_content), widget); + gtk_widget_show (widget); + + widget = gtk_label_new ("Sidebar Widget"); + gtk_container_add (GTK_CONTAINER (shell_sidebar), widget); + gtk_widget_show (widget); + + activity = e_activity_new ("Test Activity"); + e_activity_set_allow_cancel (activity, TRUE); + e_shell_backend_add_activity (shell_backend, activity); + priv->activity = activity; +} + +static void +test_shell_view_class_init (ETestShellViewClass *class, + GTypeModule *type_module) +{ + GObjectClass *object_class; + EShellViewClass *shell_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETestShellViewPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = test_shell_view_dispose; + object_class->constructed = test_shell_view_constructed; + + shell_view_class = E_SHELL_VIEW_CLASS (class); + shell_view_class->label = "Test"; + shell_view_class->icon_name = "face-monkey"; + shell_view_class->toggled = test_shell_view_toggled; +} + +static void +test_shell_view_init (ETestShellView *test_shell_view) +{ + test_shell_view->priv = + E_TEST_SHELL_VIEW_GET_PRIVATE (test_shell_view); +} + +GType +e_test_shell_view_get_type (void) +{ + return test_shell_view_type; +} + +void +e_test_shell_view_register_type (GTypeModule *type_module) +{ + const GTypeInfo type_info = { + sizeof (ETestShellViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) test_shell_view_class_init, + (GClassFinalizeFunc) NULL, + type_module, + sizeof (ETestShellView), + 0, /* n_preallocs */ + (GInstanceInitFunc) test_shell_view_init, + NULL /* value_table */ + }; + + test_shell_view_type = g_type_module_register_type ( + type_module, E_TYPE_SHELL_VIEW, + "ETestShellView", &type_info, 0); +} diff --git a/shell/test/e-test-shell-view.h b/shell/test/e-test-shell-view.h new file mode 100644 index 0000000000..85c33bfb39 --- /dev/null +++ b/shell/test/e-test-shell-view.h @@ -0,0 +1,66 @@ +/* + * e-test-shell-view.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef E_TEST_SHELL_VIEW_H +#define E_TEST_SHELL_VIEW_H + +#include <shell/e-shell-view.h> + +/* Standard GObject macros */ +#define E_TYPE_TEST_SHELL_VIEW \ + (e_test_shell_view_get_type ()) +#define E_TEST_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_TEST_SHELL_VIEW, ETestShellView)) +#define E_TEST_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_TEST_SHELL_VIEW, ETestShellViewClass)) +#define E_IS_TEST_SHELL_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_TEST_SHELL_VIEW)) +#define E_IS_TEST_SHELL_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_TEST_SHELL_VIEW)) +#define E_TEST_SHELL_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_TEST_SHELL_VIEW, ETestShellViewClass)) + +G_BEGIN_DECLS + +typedef struct _ETestShellView ETestShellView; +typedef struct _ETestShellViewClass ETestShellViewClass; +typedef struct _ETestShellViewPrivate ETestShellViewPrivate; + +struct _ETestShellView { + EShellView parent; + ETestShellViewPrivate *priv; +}; + +struct _ETestShellViewClass { + EShellViewClass parent_class; +}; + +GType e_test_shell_view_get_type (void); +void e_test_shell_view_register_type (GTypeModule *type_module); + +G_END_DECLS + +#endif /* E_TEST_SHELL_VIEW_H */ diff --git a/shell/e-shell-window-commands.h b/shell/test/evolution-module-test.c index 0696a8a5d0..1fe3c7c0d0 100644 --- a/shell/e-shell-window-commands.h +++ b/shell/test/evolution-module-test.c @@ -1,4 +1,5 @@ /* + * evolution-module-test.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -14,18 +15,27 @@ * License along with the program; if not, see <http://www.gnu.org/licenses/> * * - * Authors: - * Ettore Perazzoli <ettore@ximian.com> - * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef _E_SHELL_WINDOW_COMMANDS_H_ -#define _E_SHELL_WINDOW_COMMANDS_H_ +#include "e-test-shell-backend.h" +#include "e-test-shell-view.h" + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); -#include "e-shell-window.h" +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + /* Register dynamically loaded types. */ -void e_shell_window_commands_setup (EShellWindow *window); + e_test_shell_backend_register_type (type_module); + e_test_shell_view_register_type (type_module); +} -#endif /* _E_SHELL_WINDOW_COMMANDS_H_ */ +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} diff --git a/shell/test/evolution-test-component.c b/shell/test/evolution-test-component.c deleted file mode 100644 index aaca1339c7..0000000000 --- a/shell/test/evolution-test-component.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * JP Rosevear <jpr@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> -#include <string.h> -#include <glib/gi18n.h> -#include <bonobo/bonobo-shlib-factory.h> -#include <bonobo/bonobo-control.h> -#include <bonobo/bonobo-exception.h> -#include <gtk/gtk.h> -#include "e-task-bar.h" -#include "evolution-test-component.h" - -#define FACTORY_ID "OAFIID:GNOME_Evolution_Test_Factory:" BASE_VERSION -#define TEST_COMPONENT_ID "OAFIID:GNOME_Evolution_Test_Component:" BASE_VERSION -#define CREATE_TEST_ID "test" - -#define PARENT_TYPE bonobo_object_get_type () - -static BonoboObjectClass *parent_class = NULL; - -struct _EvolutionTestComponentPrivate { - BonoboControl *view_control; - BonoboControl *sidebar_control; - BonoboControl *status_control; -}; - -/* GObject methods */ - -static void -impl_dispose (GObject *object) -{ - EvolutionTestComponentPrivate *priv; - - priv = EVOLUTION_TEST_COMPONENT (object)->priv; - - (* G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -static void -impl_finalize (GObject *object) -{ - EvolutionTestComponentPrivate *priv = EVOLUTION_TEST_COMPONENT (object)->priv; - - g_free (priv); - - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} - -/* Evolution::Component CORBA methods */ - -static void -impl_upgradeFromVersion (PortableServer_Servant servant, - const CORBA_short major, - const CORBA_short minor, - const CORBA_short revision, - CORBA_Environment *ev) -{ - EvolutionTestComponent *component = EVOLUTION_TEST_COMPONENT (bonobo_object_from_servant (servant)); - EvolutionTestComponentPrivate *priv; - - priv = component->priv; - - g_message ("Upgrading from %d.%d.%d", major, minor, revision); -} - -static GNOME_Evolution_CreatableItemTypeList * -impl__get_userCreatableItems (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - GNOME_Evolution_CreatableItemTypeList *list = GNOME_Evolution_CreatableItemTypeList__alloc (); - - list->_length = 1; - list->_maximum = list->_length; - list->_buffer = GNOME_Evolution_CreatableItemTypeList_allocbuf (list->_length); - - CORBA_sequence_set_release (list, FALSE); - - list->_buffer[0].id = CREATE_TEST_ID; - list->_buffer[0].description = _("New Test"); - list->_buffer[0].menuDescription = (gchar *) C_("New", "_Test"); - list->_buffer[0].tooltip = _("Create a new test item"); - list->_buffer[0].menuShortcut = 'i'; - list->_buffer[0].iconName = ""; - - return list; -} - -static void -impl_requestCreateItem (PortableServer_Servant servant, - const CORBA_char *item_type_name, - CORBA_Environment *ev) -{ - EvolutionTestComponent *evolution_test_component = EVOLUTION_TEST_COMPONENT (bonobo_object_from_servant (servant)); - EvolutionTestComponentPrivate *priv; - - priv = evolution_test_component->priv; - - if (strcmp (item_type_name, CREATE_TEST_ID) == 0) { - g_message ("Creating test item"); - } else { - bonobo_exception_set (ev, ex_GNOME_Evolution_Component_UnknownType); - return; - } -} - -/* Initialization */ - -static void -evolution_test_component_class_init (EvolutionTestComponentClass *klass) -{ - POA_GNOME_Evolution_Component__epv *epv = &klass->epv; - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - epv->upgradeFromVersion = impl_upgradeFromVersion; - epv->_get_userCreatableItems = impl__get_userCreatableItems; - epv->requestCreateItem = impl_requestCreateItem; - - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; -} - -static void -evolution_test_component_init (EvolutionTestComponent *component, EvolutionTestComponentClass *klass) -{ - EvolutionTestComponentPrivate *priv; - - priv = g_new0 (EvolutionTestComponentPrivate, 1); - - component->priv = priv; -} - -BONOBO_TYPE_FUNC_FULL (EvolutionTestComponent, GNOME_Evolution_Component, PARENT_TYPE, evolution_test_component) - -static BonoboObject * -factory (BonoboGenericFactory *factory, - const gchar *component_id, - gpointer closure) -{ - if (strcmp (component_id, TEST_COMPONENT_ID) == 0) { - BonoboObject *object = BONOBO_OBJECT (g_object_new (EVOLUTION_TEST_TYPE_COMPONENT, NULL)); - bonobo_object_ref (object); - return object; - } - - g_warning (FACTORY_ID ": Don't know what to do with %s", component_id); - - return NULL; -} - -BONOBO_ACTIVATION_SHLIB_FACTORY (FACTORY_ID, "Evolution Calendar component factory", factory, NULL) diff --git a/shell/test/evolution-test-component.h b/shell/test/evolution-test-component.h deleted file mode 100644 index 5809348321..0000000000 --- a/shell/test/evolution-test-component.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * JP Rosevear <jpr@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _EVOLUTION_TEST_COMPONENT_H_ -#define _EVOLUTION_TEST_COMPONENT_H_ - -#include <bonobo/bonobo-object.h> -#include "Evolution.h" - -#define EVOLUTION_TEST_TYPE_COMPONENT (evolution_test_component_get_type ()) -#define EVOLUTION_TEST_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EVOLUTION_TEST_TYPE_COMPONENT, EvolutionTestComponent)) -#define EVOLUTION_TEST_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EVOLUTION_TEST_TYPE_COMPONENT, EvolutionTestComponentClass)) -#define EVOLUTION_TEST_IS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EVOLUTION_TEST_TYPE_COMPONENT)) -#define EVOLUTION_TEST_IS_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EVOLUTION_TEST_TYPE_COMPONENT)) - -typedef struct _EvolutionTestComponent EvolutionTestComponent; -typedef struct _EvolutionTestComponentPrivate EvolutionTestComponentPrivate; -typedef struct _EvolutionTestComponentClass EvolutionTestComponentClass; - -struct _EvolutionTestComponent { - BonoboObject parent; - - EvolutionTestComponentPrivate *priv; -}; - -struct _EvolutionTestComponentClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_Component__epv epv; -}; - -GType evolution_test_component_get_type (void); - -#endif /* _EVOLUTION_TEST_COMPONENT_H_ */ |