diff options
Diffstat (limited to 'addressbook')
71 files changed, 4716 insertions, 13426 deletions
diff --git a/addressbook/conduit/address-conduit.c b/addressbook/conduit/address-conduit.c index 172d45ee30..79c82cdb77 100644 --- a/addressbook/conduit/address-conduit.c +++ b/addressbook/conduit/address-conduit.c @@ -29,6 +29,14 @@ #define G_LOG_DOMAIN "eaddrconduit" +/* Work around deprecated API usage in GnomePilot. */ +#ifdef GTK_DISABLE_DEPRECATED +#include <glib-object.h> +#define GTK_CHECK_CAST G_TYPE_CHECK_INSTANCE_CAST +typedef GType GtkType; +#endif + +#include <glib/gi18n.h> #include <libxml/parser.h> #include <pi-source.h> #include <pi-socket.h> diff --git a/addressbook/gui/Makefile.am b/addressbook/gui/Makefile.am index 64bcd98356..7f08bf425d 100644 --- a/addressbook/gui/Makefile.am +++ b/addressbook/gui/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS = merging contact-editor contact-list-editor widgets component +SUBDIRS = merging widgets contact-editor contact-list-editor -include $(top_srcdir)/git.mk diff --git a/addressbook/gui/component/GNOME_Evolution_Addressbook.server.in.in b/addressbook/gui/component/GNOME_Evolution_Addressbook.server.in.in deleted file mode 100644 index 4000f01526..0000000000 --- a/addressbook/gui/component/GNOME_Evolution_Addressbook.server.in.in +++ /dev/null @@ -1,136 +0,0 @@ -<oaf_info> - -<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_Factory:@VERSION@" - type="shlib" - location="@COMPONENTDIR_IN_SERVER_FILE@/libevolution-addressbook@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 Address Book"/> - -</oaf_server> - -<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_VCard_Control:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Addressbook_Factory:@VERSION@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:Bonobo/Control:1.0"/> - <item value="IDL:Bonobo/PersistStream:1.0"/> - </oaf_attribute> - - <oaf_attribute name="bonobo:supported_mime_types" type="stringv"> - <item value="text/vcard"/> - <item value="text/x-vcard"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" - _value="Evolution Address Book card viewer"/> - -</oaf_server> - -<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_Component:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Addressbook_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 Address Book component"/> - - <oaf_attribute name="evolution:component_alias" type="string" value="contacts"/> - - <oaf_attribute name="evolution:menu_label" type="string" _value="C_ontacts"/> - <oaf_attribute name="evolution:menu_accelerator" type="string" value="*Control*2"/> - <oaf_attribute name="evolution:button_label" type="string" _value="Contacts"/> - <oaf_attribute name="evolution:button_tooltips" type="string" _value="Contacts"/> - <oaf_attribute name="evolution:button_sort_order" type="string" value="-9"/> - <oaf_attribute name="evolution:button_icon" type="string" value="x-office-address-book"/> - -</oaf_server> - -<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_AddressWidget:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Addressbook_Factory:@VERSION@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:BonoboControl/address-widget:@VERSION@"/> - <item value="IDL:GNOME/Control:1.0"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" - _value="Evolution Address Book address viewer"/> - -</oaf_server> - -<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_AddressPopup:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Addressbook_Factory:@VERSION@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:BonoboControl/address-widget:@VERSION@"/> - <item value="IDL:GNOME/Control:1.0"/> - </oaf_attribute> - - <oaf_attribute name="name" type="string" - _value="Evolution Address Book address popup"/> - -</oaf_server> - -<oaf_server iid="OAFIID:GNOME_Evolution_SMime_CertificateManager_ConfigControl:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Addressbook_Factory:@VERSION@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/Evolution/ConfigControl:@VERSION@"/> - </oaf_attribute> - - <oaf_attribute name="evolution2:config_item:title" type="string" - _value="Certificates"/> - - <oaf_attribute name="evolution2:config_item:description" type="string" - _value="Manage your S/MIME certificates here"/> - - <oaf_attribute name="evolution2:config_item:icon_name" type="string" - value="preferences-certificates"/> - - <oaf_attribute name="evolution2:config_item:priority" type="string" value="-6"/> - - <oaf_attribute name="name" type="string" - _value="Evolution S/MIME Certificate Management Control"/> - -</oaf_server> - -<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_Autocompletion_ConfigControl:@VERSION@" - type="factory" - location="OAFIID:GNOME_Evolution_Addressbook_Factory:@VERSION@"> - - <oaf_attribute name="repo_ids" type="stringv"> - <item value="IDL:GNOME/Evolution/ConfigControl:@VERSION@"/> - </oaf_attribute> - - <oaf_attribute name="evolution2:config_item:title" type="string" - _value="Contacts"/> - - <oaf_attribute name="evolution2:config_item:description" type="string" - _value="Configure contacts and autocompletion here"/> - - <oaf_attribute name="evolution2:config_item:icon_name" type="string" - value="preferences-autocompletion"/> - - <oaf_attribute name="evolution2:config_item:type" type="stringv"> - <item value="contacts"/> - </oaf_attribute> - - <oaf_attribute name="evolution2:config_item:priority" type="string" value="-9"/> - - <oaf_attribute name="name" type="string" - _value="Evolution folder settings configuration control"/> -</oaf_server> - -</oaf_info> diff --git a/addressbook/gui/component/Makefile.am b/addressbook/gui/component/Makefile.am deleted file mode 100644 index 6e43acd60c..0000000000 --- a/addressbook/gui/component/Makefile.am +++ /dev/null @@ -1,130 +0,0 @@ -if OS_WIN32 -WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libevolution-mail-shared.la -endif - -AM_CPPFLAGS = \ - -DG_LOG_DOMAIN=\"evolution-addressbook\" \ - -I$(top_srcdir) \ - -I$(top_srcdir)/widgets \ - -I$(top_srcdir)/shell \ - -I$(top_builddir)/shell \ - -I$(top_srcdir)/widgets/misc \ - -I$(top_srcdir)/addressbook/util \ - -I$(top_srcdir)/addressbook/gui/contact-editor \ - -I$(top_srcdir)/addressbook/gui/contact-list-editor \ - -I$(top_srcdir)/addressbook/gui/widgets \ - -I$(top_srcdir)/a11y/addressbook \ - -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ - -DEVOLUTION_LOCALEDIR=\""$(localedir)"\" \ - -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \ - -DPREFIX=\""$(prefix)"\" \ - $(LDAP_CFLAGS) \ - $(EVOLUTION_ADDRESSBOOK_CFLAGS) - -component_LTLIBRARIES = libevolution-addressbook.la - -libevolution_addressbook_la_SOURCES = \ - addressbook-component.c \ - addressbook-component.h \ - addressbook-config.c \ - addressbook-config.h \ - addressbook-migrate.c \ - addressbook-migrate.h \ - autocompletion-config.c \ - autocompletion-config.h \ - addressbook.c \ - addressbook.h \ - addressbook-view.c \ - addressbook-view.h \ - component-factory.c - -# $(top_builddir)/addressbook/printing/libecontactprint.la - -if ENABLE_SMIME -SMIME_LIB=$(top_builddir)/smime/gui/libevolution-smime.la -endif - -libevolution_addressbook_la_LIBADD = \ - $(SMIME_LIB) \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/addressbook/printing/libecontactprint.la \ - $(top_builddir)/shell/libeshell.la \ - $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ - $(top_builddir)/addressbook/gui/widgets/libeabwidgets.la \ - $(top_builddir)/filter/libfilter.la \ - $(top_builddir)/addressbook/util/libeabutil.la \ - $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ - $(top_builddir)/addressbook/gui/contact-list-editor/libecontactlisteditor.la \ - $(top_builddir)/widgets/table/libetable.la \ - $(top_builddir)/widgets/text/libetext.la \ - $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/widgets/misc/libefilterbar.la \ - $(top_builddir)/widgets/menus/libmenus.la \ - $(top_builddir)/a11y/addressbook/libevolution-addressbook-a11y.la \ - $(top_builddir)/addressbook/importers/libevolution-addressbook-importers.la \ - $(WIN32_BOOTSTRAP_LIBS) \ - $(EVOLUTION_ADDRESSBOOK_LIBS) $(LDAP_LIBS) - - -libevolution_addressbook_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) - -# GConf schemas - -schemadir = $(GCONF_SCHEMA_FILE_DIR) -schema_in_files = apps_evolution_addressbook.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) - -@INTLTOOL_SCHEMAS_RULE@ - -if OS_WIN32 -install-data-local: - if test -z "$(DESTDIR)" ; then \ - for p in $(schema_DATA) ; do \ - (echo set GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE); \ - echo $(GCONFTOOL) --makefile-install-rule $$p) >_temp.bat; \ - cmd /c _temp.bat; \ - done \ - fi -else -install-data-local: - if test -z "$(DESTDIR)" ; then \ - for p in $(schema_DATA) ; do \ - GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $$p; \ - done \ - fi -endif - -server_in_files = GNOME_Evolution_Addressbook.server.in.in -server_DATA = $(server_in_files:.server.in.in=.server) -@EVO_SERVER_RULE@ -@INTLTOOL_SERVER_RULE@ - -glade_DATA = \ - ldap-config.glade - -BUILT_SOURCES = $(server_DATA) -CLEANFILES = $(BUILT_SOURCES) - -DISTCLEANFILES = $(schema_DATA) - -EXTRA_DIST = \ - $(glade_DATA) \ - $(schema_in_files) \ - $(server_in_files) \ - openldap-extract.h - -dist-hook: - cd $(distdir); rm -f $(BUILT_SOURCES) - -if ENABLE_PURIFY -PLINK = $(LIBTOOL) --mode=link $(PURIFY) $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ - -all-local: evolution-addressbook.pure - -evolution-addressbook.pure: evolution-addressbook - @rm -f evolution-addressbook.pure - $(PLINK) $(evolution_addressbook_LDFLAGS) $(evolution_addressbook_OBJECTS) $(evolution_addressbook_LDADD) $(LIBS) - -endif - --include $(top_srcdir)/git.mk diff --git a/addressbook/gui/component/addressbook-component.c b/addressbook/gui/component/addressbook-component.c deleted file mode 100644 index 9bf63376fb..0000000000 --- a/addressbook/gui/component/addressbook-component.c +++ /dev/null @@ -1,527 +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) - * - */ - -/* EPFIXME: Add autocompletion setting. */ - -#include <config.h> - -#include "addressbook-component.h" -#include "addressbook-config.h" -#include "addressbook-migrate.h" -#include "addressbook-view.h" -#include "addressbook/gui/contact-editor/eab-editor.h" -#include "addressbook/gui/widgets/eab-gui-util.h" -#include "e-util/e-plugin.h" -#include "e-util/e-import.h" -#include "addressbook/gui/widgets/eab-popup.h" -#include "addressbook/gui/widgets/eab-menu.h" -#include "addressbook/gui/widgets/eab-config.h" -#include "addressbook/importers/evolution-addressbook-importers.h" - -#include "misc/e-task-bar.h" -#include "misc/e-info-label.h" - -#include "shell/e-component-view.h" - -#include <string.h> -#include <gtk/gtk.h> -#include <glib/gi18n-lib.h> -#include <gconf/gconf-client.h> -#include <e-util/e-util.h> -#include <libedataserver/e-url.h> - -#ifdef ENABLE_SMIME -#include "smime/gui/component.h" -#endif - -#define LDAP_BASE_URI "ldap://" -#define PERSONAL_RELATIVE_URI "system" - -#define PARENT_TYPE bonobo_object_get_type () -static BonoboObjectClass *parent_class = NULL; - -struct _AddressbookComponentPrivate { - GConfClient *gconf_client; - gchar *base_directory; - GList *views; -}; - -static void -ensure_sources (AddressbookComponent *component) -{ - ESourceList *source_list; - ESourceGroup *on_this_computer; - ESource *personal_source; - gchar *base_uri, *base_uri_proto, base_uri_proto_seventh; - const gchar *base_dir; - - personal_source = NULL; - - if (!e_book_get_addressbooks (&source_list, NULL)) { - g_warning ("Could not get addressbook source list from GConf!"); - return; - } - - base_dir = addressbook_component_peek_base_directory (component); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - if (strlen (base_uri_proto) >= 7) { - /* compare only file:// part. If user home dir name changes we do not want to create - one more group */ - base_uri_proto_seventh = base_uri_proto[7]; - base_uri_proto[7] = 0; - } else { - base_uri_proto_seventh = -1; - } - - on_this_computer = e_source_list_ensure_group (source_list, _("On This Computer"), base_uri_proto, TRUE); - e_source_list_ensure_group (source_list, _("On LDAP Servers"), LDAP_BASE_URI, FALSE); - - if (base_uri_proto_seventh != -1) { - base_uri_proto[7] = base_uri_proto_seventh; - } - - if (on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - personal_source = source; - break; - } - } - /* Make sure we have the correct base uri. This can change when user's - homedir name changes */ - if (strcmp (base_uri_proto, e_source_group_peek_base_uri (on_this_computer))) { - e_source_group_set_base_uri (on_this_computer, base_uri_proto); - - /* *sigh* . We shouldn't need this sync call here as set_base_uri - call results in synching to gconf, but that happens in idle loop - and too late to prevent user seeing "Can not Open ... because of invalid uri" error.*/ - e_source_list_sync (source_list,NULL); - } - } - - if (personal_source) { - /* ensure the source name is in current locale, not read from configuration */ - e_source_set_name (personal_source, _("Personal")); - } else { - /* Create the default Person addressbook */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (on_this_computer, source, -1); - g_object_unref (source); - - e_source_set_property (source, "completion", "true"); - - personal_source = source; - } - - g_object_unref (on_this_computer); - g_free (base_uri_proto); - g_free (base_uri); -} - -static void -view_destroyed_cb (gpointer data, GObject *where_the_object_was) -{ - AddressbookComponent *addressbook_component = data; - AddressbookComponentPrivate *priv; - GList *l; - - priv = addressbook_component->priv; - - for (l = priv->views; l; l = l->next) { - AddressbookView *view = l->data; - if (G_OBJECT (view) == where_the_object_was) { - priv->views = g_list_remove (priv->views, view); - break; - } - } -} - -/* Evolution::Component CORBA methods. */ - -static GNOME_Evolution_ComponentView -impl_createView (PortableServer_Servant servant, - GNOME_Evolution_ShellView parent, - CORBA_boolean select_item, - CORBA_Environment *ev) -{ - AddressbookComponent *addressbook_component = ADDRESSBOOK_COMPONENT (bonobo_object_from_servant (servant)); - AddressbookComponentPrivate *priv = addressbook_component->priv; - AddressbookView *view = addressbook_view_new (); - EComponentView *component_view; - - g_object_weak_ref (G_OBJECT (view), view_destroyed_cb, addressbook_component); - priv->views = g_list_append (priv->views, view); - - component_view = e_component_view_new_controls (parent, "contacts", - bonobo_control_new (addressbook_view_peek_sidebar (view)), - addressbook_view_peek_folder_view (view), - bonobo_control_new (addressbook_view_peek_statusbar (view))); - - return BONOBO_OBJREF(component_view); - -} - -static GNOME_Evolution_CreatableItemTypeList * -impl__get_userCreatableItems (PortableServer_Servant servant, - CORBA_Environment *ev) -{ - GNOME_Evolution_CreatableItemTypeList *list = GNOME_Evolution_CreatableItemTypeList__alloc (); - - list->_length = 3; - list->_maximum = list->_length; - list->_buffer = GNOME_Evolution_CreatableItemTypeList_allocbuf (list->_length); - - CORBA_sequence_set_release (list, FALSE); - - list->_buffer[0].id = (gchar *) "contact"; - list->_buffer[0].description = _("New Contact"); - list->_buffer[0].menuDescription = (gchar *) C_("New", "_Contact"); - list->_buffer[0].tooltip = _("Create a new contact"); - list->_buffer[0].menuShortcut = 'c'; - list->_buffer[0].iconName = (gchar *) "contact-new"; - list->_buffer[0].type = GNOME_Evolution_CREATABLE_OBJECT; - - list->_buffer[1].id = (gchar *) "contact_list"; - list->_buffer[1].description = _("New Contact List"); - list->_buffer[1].menuDescription = (gchar *) C_("New", "Contact _List"); - list->_buffer[1].tooltip = _("Create a new contact list"); - list->_buffer[1].menuShortcut = 'l'; - list->_buffer[1].iconName = (gchar *) "stock_contact-list"; - list->_buffer[1].type = GNOME_Evolution_CREATABLE_OBJECT; - - list->_buffer[2].id = (gchar *) "address_book"; - list->_buffer[2].description = _("New Address Book"); - list->_buffer[2].menuDescription = (gchar *) C_("New", "Address _Book"); - list->_buffer[2].tooltip = _("Create a new address book"); - list->_buffer[2].menuShortcut = '\0'; - list->_buffer[2].iconName = (gchar *) "address-book-new"; - list->_buffer[2].type = GNOME_Evolution_CREATABLE_FOLDER; - - return list; -} - -static void -book_loaded_cb (EBook *book, EBookStatus status, gpointer data) -{ - EContact *contact; - gchar *item_type_name = data; - - if (status != E_BOOK_ERROR_OK) { - /* XXX we really need a dialog here, but we don't have - access to the ESource so we can't use - eab_load_error_dialog. fun! */ - return; - } - - contact = e_contact_new (); - - if (!strcmp (item_type_name, "contact")) { - eab_show_contact_editor (book, contact, TRUE, TRUE); - } - else if (!strcmp (item_type_name, "contact_list")) { - eab_show_contact_list_editor (book, contact, TRUE, TRUE); - } - - g_object_unref (book); - g_object_unref (contact); - - g_free (item_type_name); -} - -static void -impl_requestCreateItem (PortableServer_Servant servant, - const CORBA_char *item_type_name, - CORBA_Environment *ev) -{ - EBook *book; - GConfClient *gconf_client; - ESourceList *source_list; - gchar *uid; - - if (!item_type_name || - (strcmp (item_type_name, "address_book") && - strcmp (item_type_name, "contact") && - strcmp (item_type_name, "contact_list"))) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UnknownType, NULL); - return; - } - - if (!strcmp (item_type_name, "address_book")) { - addressbook_config_create_new_source (NULL); - return; - } - - gconf_client = gconf_client_get_default(); - uid = gconf_client_get_string (gconf_client, "/apps/evolution/addressbook/display/primary_addressbook", - NULL); - g_object_unref (gconf_client); - if (!e_book_get_addressbooks (&source_list, NULL)) { - g_warning ("Could not get addressbook source list from GConf!"); - g_free (uid); - return; - } - if (uid) { - ESource *source = e_source_list_peek_source_by_uid(source_list, uid); - if (source) { - book = e_book_new (source, NULL); - } - else { - book = e_book_new_default_addressbook (NULL); - } - g_free (uid); - } - else { - book = e_book_new_default_addressbook (NULL); - } - - e_book_async_open (book, FALSE, book_loaded_cb, g_strdup (item_type_name)); -} - -static void -impl_handleURI (PortableServer_Servant servant, - const gchar * uri, - CORBA_Environment *ev) -{ - AddressbookComponent *addressbook_component = ADDRESSBOOK_COMPONENT (bonobo_object_from_servant (servant)); - AddressbookComponentPrivate *priv; - AddressbookView *view = NULL; - - GList *l; - gchar *src_uid = NULL; - gchar *contact_uid = NULL; - - priv = addressbook_component->priv; - l = g_list_last (priv->views); - if (!l) - return; - - view = l->data; - - if (!strncmp (uri, "contacts:", 9)) { - EUri *euri = e_uri_new (uri); - const gchar *p; - gchar *header, *content; - gsize len, clen; - - p = euri->query; - if (p) { - while (*p) { - len = strcspn (p, "=&"); - - /* If it's malformed, give up. */ - if (p[len] != '=') - break; - - header = (gchar *) p; - header[len] = '\0'; - p += len + 1; - - clen = strcspn (p, "&"); - - content = g_strndup (p, clen); - - if (!g_ascii_strcasecmp (header, "source-uid")) { - src_uid = g_strdup (content); - } else if (!g_ascii_strcasecmp (header, "contact-uid")) { - contact_uid = g_strdup (content); - } - - g_free (content); - - p += clen; - if (*p == '&') { - p++; - if (!strcmp (p, "amp;")) - p += 4; - } - } - - addressbook_view_edit_contact (view, src_uid, contact_uid); - - g_free (src_uid); - g_free (contact_uid); - } - e_uri_free (euri); - } - -} - -static void -impl_upgradeFromVersion (PortableServer_Servant servant, short major, short minor, short revision, CORBA_Environment *ev) -{ - GError *err = NULL; - - if (!addressbook_migrate (addressbook_component_peek (), major, minor, revision, &err)) { - GNOME_Evolution_Component_UpgradeFailed *failedex; - - failedex = GNOME_Evolution_Component_UpgradeFailed__alloc(); - failedex->what = CORBA_string_dup(_("Failed upgrading Address Book settings or folders.")); - failedex->why = CORBA_string_dup(err->message); - CORBA_exception_set(ev, CORBA_USER_EXCEPTION, ex_GNOME_Evolution_Component_UpgradeFailed, failedex); - } - - if (err) - g_error_free(err); -} - -static CORBA_boolean -impl_requestQuit (PortableServer_Servant servant, CORBA_Environment *ev) -{ - return eab_editor_request_close_all (); -} - -/* GObject methods. */ - -static void -impl_dispose (GObject *object) -{ - AddressbookComponentPrivate *priv = ADDRESSBOOK_COMPONENT (object)->priv; - GList *l; - - if (priv->gconf_client != NULL) { - g_object_unref (priv->gconf_client); - priv->gconf_client = NULL; - } - - for (l = priv->views; l; l = l->next) { - AddressbookView *view = l->data; - g_object_weak_unref (G_OBJECT (view), view_destroyed_cb, ADDRESSBOOK_COMPONENT (object)); - } - g_list_free (priv->views); - priv->views = NULL; - (* G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -static void -impl_finalize (GObject *object) -{ - AddressbookComponentPrivate *priv = ADDRESSBOOK_COMPONENT (object)->priv; - - g_free (priv); - - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} - -/* Initialization. */ - -static void -addressbook_component_class_init (AddressbookComponentClass *class) -{ - POA_GNOME_Evolution_Component__epv *epv = &class->epv; - GObjectClass *object_class = G_OBJECT_CLASS (class); - - bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - - epv->createView = impl_createView; - epv->_get_userCreatableItems = impl__get_userCreatableItems; - epv->requestCreateItem = impl_requestCreateItem; - epv->upgradeFromVersion = impl_upgradeFromVersion; - epv->requestQuit = impl_requestQuit; - epv->handleURI = impl_handleURI; - - object_class->dispose = impl_dispose; - object_class->finalize = impl_finalize; - - parent_class = g_type_class_peek_parent (class); -} - -static void -addressbook_component_init (AddressbookComponent *component) -{ - AddressbookComponentPrivate *priv; - static gint first = TRUE; - - priv = g_new0 (AddressbookComponentPrivate, 1); - - /* EPFIXME: Should use a custom one instead? */ - priv->gconf_client = gconf_client_get_default (); - - priv->base_directory = g_build_filename (e_get_user_data_dir (), "addressbook", NULL); - - component->priv = priv; - - ensure_sources (component); - -#ifdef ENABLE_SMIME - smime_component_init (); -#endif - - if (first) { - EImportClass *klass; - - first = FALSE; - e_plugin_hook_register_type(eab_popup_hook_get_type()); - e_plugin_hook_register_type(eab_menu_hook_get_type()); - e_plugin_hook_register_type(eab_config_hook_get_type()); - - klass = g_type_class_ref(e_import_get_type()); - e_import_class_add_importer(klass, evolution_ldif_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, evolution_vcard_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, evolution_csv_outlook_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, evolution_csv_mozilla_importer_peek(), NULL, NULL); - e_import_class_add_importer(klass, evolution_csv_evolution_importer_peek(), NULL, NULL); - } -} - -/* Public API. */ - -AddressbookComponent * -addressbook_component_peek (void) -{ - static AddressbookComponent *component = NULL; - - if (component == NULL) - component = g_object_new (addressbook_component_get_type (), NULL); - - return component; -} - -GConfClient* -addressbook_component_peek_gconf_client (AddressbookComponent *component) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_COMPONENT (component), NULL); - - return component->priv->gconf_client; -} - -const gchar * -addressbook_component_peek_base_directory (AddressbookComponent *component) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_COMPONENT (component), NULL); - - return component->priv->base_directory; -} - -BONOBO_TYPE_FUNC_FULL (AddressbookComponent, GNOME_Evolution_Component, PARENT_TYPE, addressbook_component) diff --git a/addressbook/gui/component/addressbook-component.h b/addressbook/gui/component/addressbook-component.h deleted file mode 100644 index e5119295b3..0000000000 --- a/addressbook/gui/component/addressbook-component.h +++ /dev/null @@ -1,62 +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 _ADDRESSBOOK_COMPONENT_H_ -#define _ADDRESSBOOK_COMPONENT_H_ - -#include <bonobo/bonobo-object.h> - -#include "Evolution.h" -#include "e-activity-handler.h" -#include <libedataserver/e-source-list.h> - -#define ADDRESSBOOK_TYPE_COMPONENT (addressbook_component_get_type ()) -#define ADDRESSBOOK_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ADDRESSBOOK_TYPE_COMPONENT, AddressbookComponent)) -#define ADDRESSBOOK_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ADDRESSBOOK_TYPE_COMPONENT, AddressbookComponentClass)) -#define ADDRESSBOOK_IS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ADDRESSBOOK_TYPE_COMPONENT)) -#define ADDRESSBOOK_IS_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), ADDRESSBOOK_TYPE_COMPONENT)) - -typedef struct _AddressbookComponent AddressbookComponent; -typedef struct _AddressbookComponentPrivate AddressbookComponentPrivate; -typedef struct _AddressbookComponentClass AddressbookComponentClass; - -struct _AddressbookComponent { - BonoboObject parent; - - AddressbookComponentPrivate *priv; -}; - -struct _AddressbookComponentClass { - BonoboObjectClass parent_class; - - POA_GNOME_Evolution_Component__epv epv; -}; - -GType addressbook_component_get_type (void); - -AddressbookComponent *addressbook_component_peek (void); - -GConfClient *addressbook_component_peek_gconf_client (AddressbookComponent *component); -const gchar *addressbook_component_peek_base_directory (AddressbookComponent *component); - -#endif /* _ADDRESSBOOK_COMPONENT_H_ */ diff --git a/addressbook/gui/component/addressbook-config.c b/addressbook/gui/component/addressbook-config.c deleted file mode 100644 index 248a9de9ea..0000000000 --- a/addressbook/gui/component/addressbook-config.c +++ /dev/null @@ -1,1252 +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: - * Chris Toshok <toshok@ximian.com> - * Chris Lahey <clahey@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * And no doubt others ... - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/*#define STANDALONE*/ - -#include <config.h> - -#include <string.h> -#include <stdlib.h> -#include <sys/time.h> - -#include <gtk/gtk.h> -#include <glib/gi18n.h> - -#include <bonobo/bonobo-generic-factory.h> - -#ifdef G_OS_WIN32 -/* Include <windows.h> early and work around DATADIR lossage */ -#define DATADIR crap_DATADIR -#include <windows.h> -#undef DATADIR -#endif - -#include <glade/glade.h> - -#include "addressbook.h" -#include "addressbook-component.h" -#include "addressbook-config.h" - -#include "e-util/e-error.h" -#include "e-util/e-util-private.h" - -#include "addressbook/gui/widgets/eab-config.h" - -#define d(x) - -#ifdef HAVE_LDAP -#ifndef G_OS_WIN32 -#include <ldap.h> -#ifndef SUNLDAP -#include <ldap_schema.h> -#endif -#else -#include <winldap.h> -#include "openldap-extract.h" -#endif -#endif - -#define LDAP_PORT_STRING "389" -#define LDAPS_PORT_STRING "636" - -#define GLADE_FILE_NAME "ldap-config.glade" -#define CONFIG_CONTROL_FACTORY_ID "OAFIID:GNOME_Evolution_Addressbook_ConfigControlFactory:" BASE_VERSION -#define LDAP_CONFIG_CONTROL_ID "OAFIID:GNOME_Evolution_LDAPStorage_ConfigControl:" BASE_VERSION - -GtkWidget* supported_bases_create_table (gchar *name, gchar *string1, gchar *string2, - gint num1, gint num2); - -/* default objectclasses */ -#define TOP "top" -#define PERSON "person" -#define ORGANIZATIONALPERSON "organizationalPerson" -#define INETORGPERSON "inetOrgPerson" -#define EVOLUTIONPERSON "evolutionPerson" -#define CALENTRY "calEntry" - - -typedef struct _AddressbookSourceDialog AddressbookSourceDialog; - -struct _AddressbookSourceDialog { - GladeXML *gui; - - EABConfig *config; /* the config manager */ - - GtkWidget *window; - - /* Source selection (druid only) */ - ESourceList *source_list; - GSList *menu_source_groups; - - /* ESource we're currently editing */ - ESource *source; - /* The original source in edit mode. Also used to flag when we are in edit mode. */ - ESource *original_source; - - /* Source group we're creating/editing a source in */ - ESourceGroup *source_group; - - /* info page fields */ - GtkWidget *host; - GtkWidget *auth_combobox; - AddressbookLDAPAuthType auth; - GtkWidget *auth_principal; - - /* connecting page fields */ - GtkWidget *port_comboentry; - GtkWidget *ssl_combobox; - AddressbookLDAPSSLType ssl; - - /* searching page fields */ - GtkWidget *rootdn; - AddressbookLDAPScopeType scope; - GtkWidget *scope_combobox; - GtkWidget *search_filter; - GtkWidget *timeout_scale; - GtkWidget *limit_spinbutton; - GtkWidget *canbrowsecheck; - - /* display name page fields */ - GtkWidget *display_name; -}; - - - -#ifdef HAVE_LDAP - -static const gchar * -ldap_unparse_auth (AddressbookLDAPAuthType auth_type) -{ - switch (auth_type) { - case ADDRESSBOOK_LDAP_AUTH_NONE: - return "none"; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - return "ldap/simple-email"; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - return "ldap/simple-binddn"; - default: - g_return_val_if_reached ("none"); - } -} - -static AddressbookLDAPAuthType -ldap_parse_auth (const gchar *auth) -{ - if (!auth) - return ADDRESSBOOK_LDAP_AUTH_NONE; - - if (!strcmp (auth, "ldap/simple-email") || !strcmp (auth, "simple")) - return ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL; - else if (!strcmp (auth, "ldap/simple-binddn")) - return ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN; - else - return ADDRESSBOOK_LDAP_AUTH_NONE; -} - -static const gchar * -ldap_unparse_scope (AddressbookLDAPScopeType scope_type) -{ - switch (scope_type) { - case ADDRESSBOOK_LDAP_SCOPE_BASE: - return "base"; - case ADDRESSBOOK_LDAP_SCOPE_ONELEVEL: - return "one"; - case ADDRESSBOOK_LDAP_SCOPE_SUBTREE: - return "sub"; - default: - g_return_val_if_reached (""); - } -} - -static const gchar * -ldap_unparse_ssl (AddressbookLDAPSSLType ssl_type) -{ - switch (ssl_type) { - case ADDRESSBOOK_LDAP_SSL_NEVER: - return "never"; - case ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE: - return "whenever_possible"; - case ADDRESSBOOK_LDAP_SSL_ALWAYS: - return "always"; - default: - g_return_val_if_reached (""); - } -} - -static AddressbookLDAPSSLType -ldap_parse_ssl (const gchar *ssl) -{ - if (!ssl) - return ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; /* XXX good default? */ - - if (!strcmp (ssl, "always")) - return ADDRESSBOOK_LDAP_SSL_ALWAYS; - else if (!strcmp (ssl, "never")) - return ADDRESSBOOK_LDAP_SSL_NEVER; - else - return ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; -} - -static const gchar * -ldap_get_ssl_tooltip (AddressbookLDAPSSLType ssl_type) -{ - switch (ssl_type) { - case ADDRESSBOOK_LDAP_SSL_ALWAYS: - return _("Selecting this option means that Evolution will only connect to your LDAP server if your LDAP server supports SSL."); - case ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE: - return _("Selecting this option means that Evolution will only connect to your LDAP server if your LDAP server supports TLS."); - case ADDRESSBOOK_LDAP_SSL_NEVER: - return _("Selecting this option means that your server does not support either SSL or TLS. This means that your connection will be insecure, and that you will be vulnerable to security exploits."); - } - - return NULL; -} - -static gboolean -source_to_uri_parts (ESource *source, gchar **host, gchar **rootdn, AddressbookLDAPScopeType *scope, gchar **search_filter, gint *port) -{ - gchar *uri; - LDAPURLDesc *lud; - gint ldap_error; - - g_return_val_if_fail (source, FALSE); - - uri = e_source_get_uri (source); - ldap_error = ldap_url_parse ((gchar *) uri, &lud); - g_free (uri); - - if (ldap_error != LDAP_SUCCESS) - return FALSE; - - if (host) - *host = g_strdup (lud->lud_host ? lud->lud_host : ""); - if (rootdn) - *rootdn = g_strdup (lud->lud_dn ? lud->lud_dn : ""); - if (port) - *port = lud->lud_port ? lud->lud_port : LDAP_PORT; - if (scope) - *scope = lud->lud_scope == LDAP_SCOPE_BASE ? ADDRESSBOOK_LDAP_SCOPE_BASE : - lud->lud_scope == LDAP_SCOPE_ONELEVEL ? ADDRESSBOOK_LDAP_SCOPE_ONELEVEL : - lud->lud_scope == LDAP_SCOPE_SUBTREE ? ADDRESSBOOK_LDAP_SCOPE_SUBTREE : - ADDRESSBOOK_LDAP_SCOPE_ONELEVEL; - if (search_filter && lud->lud_filter) - *search_filter = g_strdup (lud->lud_filter); - - ldap_free_urldesc (lud); - return TRUE; -} - -static gboolean -source_group_is_remote (ESourceGroup *group) -{ - return strncmp ("ldap:", e_source_group_peek_base_uri (group), 5) == 0; -} - -/* ldap api foo */ -static LDAP * -addressbook_ldap_init (GtkWidget *window, ESource *source) -{ - LDAP *ldap; - gchar *host; - gint port; - gint ldap_error; - gint protocol_version = LDAP_VERSION3; - - if (!source_to_uri_parts (source, &host, NULL, NULL, NULL, &port)) - return NULL; - - if (!(ldap = ldap_init (host, port))) { - e_error_run ((GtkWindow *) window, "addressbook:ldap-init", NULL); - goto done; - } - - ldap_error = ldap_set_option (ldap, LDAP_OPT_PROTOCOL_VERSION, &protocol_version); - if (LDAP_SUCCESS != ldap_error) - g_warning ("failed to set protocol version to LDAPv3"); - - /* XXX do TLS if it's configured in */ - - done: - g_free (host); - return ldap; -} - -static gint -addressbook_ldap_auth (GtkWidget *window, LDAP *ldap) -{ - gint ldap_error; - - /* XXX use auth info from source */ - ldap_error = ldap_simple_bind_s (ldap, NULL, NULL); - if (LDAP_SUCCESS != ldap_error) - e_error_run ((GtkWindow *) window, "addressbook:ldap-auth", NULL); - - return ldap_error; -} - -static gint -addressbook_root_dse_query (AddressbookSourceDialog *dialog, LDAP *ldap, - const gchar **attrs, LDAPMessage **resp) -{ - gint ldap_error; - struct timeval timeout; - - timeout.tv_sec = (gint) gtk_adjustment_get_value (GTK_RANGE(dialog->timeout_scale)->adjustment); - timeout.tv_usec = 0; - - ldap_error = ldap_search_ext_s (ldap, - LDAP_ROOT_DSE, LDAP_SCOPE_BASE, - "(objectclass=*)", - (gchar **) attrs, 0, NULL, NULL, &timeout, LDAP_NO_LIMIT, resp); - if (LDAP_SUCCESS != ldap_error) - e_error_run (GTK_WINDOW (dialog->window), "addressbook:ldap-search-base", NULL); - - return ldap_error; -} - -/* searching page */ -GtkWidget* -supported_bases_create_table (gchar *name, gchar *string1, gchar *string2, gint num1, gint num2) -{ - GtkWidget *table, *scrolled; - GtkTreeSelection *selection; - GtkCellRenderer *renderer; - GtkListStore *model; - - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); - - model = gtk_list_store_new (1, G_TYPE_STRING); - table = gtk_tree_view_new_with_model ((GtkTreeModel *) model); - g_object_unref (model); - renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes ((GtkTreeView *) table, -1, _("Base"), renderer, "text", 0, NULL); - gtk_tree_view_set_headers_visible ((GtkTreeView *) table, FALSE); - selection = gtk_tree_view_get_selection ((GtkTreeView *) table); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - gtk_container_add (GTK_CONTAINER (scrolled), table); - g_object_set_data((GObject *)scrolled, "table", table); - - return scrolled; -} - -static gboolean -do_ldap_root_dse_query (AddressbookSourceDialog *sdialog, GtkListStore *model, ESource *source) -{ - LDAP *ldap; - const gchar *attrs[2]; - gint ldap_error; - gchar **values; - LDAPMessage *resp; - gint i; - - ldap = addressbook_ldap_init (sdialog->window, source); - if (!ldap) - return FALSE; - - if (LDAP_SUCCESS != addressbook_ldap_auth (sdialog->window, ldap)) - goto fail; - - attrs[0] = "namingContexts"; - attrs[1] = NULL; - - ldap_error = addressbook_root_dse_query (sdialog, ldap, attrs, &resp); - - if (ldap_error != LDAP_SUCCESS) - goto fail; - - values = ldap_get_values (ldap, resp, "namingContexts"); - if (!values || values[0] == NULL || strlen (values[0]) == 0) { - e_error_run (GTK_WINDOW (sdialog->window), "addressbook:ldap-search-base", NULL); - goto fail; - } - - for (i = 0; values[i]; i++) { - GtkTreeIter iter; - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, 0, values[i], -1); - } - - ldap_value_free (values); - ldap_unbind_s (ldap); - return TRUE; - - fail: - ldap_unbind_s (ldap); - return FALSE; -} - -static void -search_base_selection_model_changed (GtkTreeSelection *selection, GtkWidget *dialog) -{ - gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - gtk_tree_selection_get_selected(selection, NULL, NULL)); -} - -static void -query_for_supported_bases (GtkWidget *button, AddressbookSourceDialog *sdialog) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeView *table; - GtkWidget *dialog; - GtkWidget *supported_bases_table; - GladeXML *gui; - GtkTreeIter iter; - gchar *gladefile; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, "supported-bases-dialog", NULL); - g_free (gladefile); - - dialog = glade_xml_get_widget (gui, "supported-bases-dialog"); - - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (sdialog->window)); - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - gtk_widget_ensure_style (dialog); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 0); - gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 12); - - supported_bases_table = glade_xml_get_widget (gui, "supported-bases-table"); - gtk_widget_show_all (supported_bases_table); - - table = g_object_get_data (G_OBJECT (supported_bases_table), "table"); - model = gtk_tree_view_get_model (table); - selection = gtk_tree_view_get_selection (table); - g_signal_connect (selection, "changed", G_CALLBACK (search_base_selection_model_changed), dialog); - search_base_selection_model_changed (selection, dialog); - - if (do_ldap_root_dse_query (sdialog, GTK_LIST_STORE (model), sdialog->source)) { - gtk_widget_show (dialog); - - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK - && gtk_tree_selection_get_selected (selection, &model, &iter)) { - gchar *dn; - - gtk_tree_model_get (model, &iter, 0, &dn, -1); - gtk_entry_set_text((GtkEntry *)sdialog->rootdn, dn); - g_free(dn); - } - } - - gtk_widget_destroy (dialog); -} - -#endif /* HAVE_LDAP */ - -GtkWidget* -addressbook_config_create_new_source (GtkWidget *parent) -{ - return addressbook_config_edit_source(parent, NULL); -} - -/* ********************************************************************** */ - -static void -eabc_type_changed(GtkComboBox *dropdown, AddressbookSourceDialog *sdialog) -{ - gint id = gtk_combo_box_get_active(dropdown); - GtkTreeModel *model; - GtkTreeIter iter; - - model = gtk_combo_box_get_model(dropdown); - if (id == -1 || !gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) - return; - - /* TODO: when we change the group type, we lose all of the pre-filled dialog info */ - - gtk_tree_model_get(model, &iter, 1, &sdialog->source_group, -1); - /* HACK: doesn't work if you don't do this */ - e_source_set_absolute_uri(sdialog->source, NULL); - e_source_set_group(sdialog->source, sdialog->source_group); - - /* BIG HACK: We load the defaults for each type here. - I guess plugins will have to use the do it in their factory callbacks */ - if (!strncmp(e_source_group_peek_base_uri(sdialog->source_group), "groupwise:", 10)) { - GSList *l; - ESource *source; - gchar *tmp; - - l = e_source_group_peek_sources(sdialog->source_group); - if (l && l->data ) { - source = l->data; - e_source_set_property(sdialog->source, "auth", e_source_get_property(source, "auth")); - e_source_set_property(sdialog->source, "user", e_source_get_property(source, "user")); - e_source_set_property(sdialog->source, "user_ssl", e_source_get_property(source, "use_ssl")); - } - - e_source_set_property(sdialog->source, "auth-domain", "Groupwise"); - tmp = g_strconcat (";", e_source_peek_name(sdialog->source), NULL); - e_source_set_relative_uri (sdialog->source, tmp); - g_free (tmp); -#ifdef HAVE_LDAP - } else if (!strncmp(e_source_group_peek_base_uri(sdialog->source_group), "ldap:", 5)) { - gchar *tmp; - - tmp = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s", - "", LDAP_PORT_STRING, - "", - "one"); - e_source_set_relative_uri (sdialog->source, tmp); - g_free (tmp); - e_source_set_property(sdialog->source, "timeout", "3"); - e_source_set_property(sdialog->source, "limit", "100"); -#endif - } else { - e_source_set_relative_uri (sdialog->source, e_source_peek_uid (sdialog->source)); - } - - e_config_target_changed((EConfig *)sdialog->config, E_CONFIG_TARGET_CHANGED_REBUILD); -} - -static GtkWidget * -eabc_general_type(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkComboBox *dropdown; - GtkCellRenderer *cell; - GtkListStore *store; - GtkTreeIter iter; - GSList *l; - GtkWidget *w, *label; - gint i, row = 0; - - if (old) - return old; - - w = gtk_hbox_new(FALSE, 6); - label = gtk_label_new_with_mnemonic(_("_Type:")); - gtk_box_pack_start((GtkBox *)w, label, FALSE, FALSE, 0); - - dropdown = (GtkComboBox *)gtk_combo_box_new(); - cell = gtk_cell_renderer_text_new(); - store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - i = 0; - for (l=sdialog->menu_source_groups;l;l=g_slist_next(l)) { - ESourceGroup *group = l->data; - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, e_source_group_peek_name(group), 1, group, -1); - if (e_source_peek_group(sdialog->source) == group) - row = i; - i++; - } - - gtk_cell_layout_pack_start((GtkCellLayout *)dropdown, cell, TRUE); - gtk_cell_layout_set_attributes((GtkCellLayout *)dropdown, cell, "text", 0, NULL); - gtk_combo_box_set_model(dropdown, (GtkTreeModel *)store); - gtk_combo_box_set_active(dropdown, -1); - gtk_combo_box_set_active(dropdown, row); - g_signal_connect(dropdown, "changed", G_CALLBACK(eabc_type_changed), sdialog); - gtk_widget_show((GtkWidget *)dropdown); - gtk_box_pack_start((GtkBox *)w, (GtkWidget *)dropdown, TRUE, TRUE, 0); - gtk_label_set_mnemonic_widget((GtkLabel *)label, (GtkWidget *)dropdown); - - gtk_box_pack_start((GtkBox *)parent, (GtkWidget *)w, FALSE, FALSE, 0); - - gtk_widget_show_all(w); - - return (GtkWidget *)w; -} - -static void -name_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - e_source_set_name (sdialog->source, gtk_entry_get_text (GTK_ENTRY (sdialog->display_name))); -} - -static void -offline_status_changed_cb (GtkWidget *widget, AddressbookSourceDialog *sdialog) -{ - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) - e_source_set_property (sdialog->source, "offline_sync", "1"); - else - e_source_set_property (sdialog->source, "offline_sync", "0"); - -} - -static GtkWidget * -eabc_general_name(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - const gchar *uri; - GtkWidget *w; - GladeXML *gui; - gchar *gladefile; - - if (old) - return old; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - sdialog->display_name = glade_xml_get_widget (gui, "account-editor-display-name-entry"); - g_signal_connect(sdialog->display_name, "changed", G_CALLBACK(name_changed_cb), sdialog); - gtk_entry_set_text((GtkEntry *)sdialog->display_name, e_source_peek_name(sdialog->source)); - - /* Hardcoded: groupwise can't edit the name (or anything else) */ - if (sdialog->original_source) { - uri = e_source_group_peek_base_uri (sdialog->source_group); - if (uri && strncmp(uri, "groupwise:", 10) == 0) { - gtk_widget_set_sensitive (GTK_WIDGET(sdialog->display_name), FALSE); - } - } - - g_object_unref(gui); - - return w; -} - -static GtkWidget * -eabc_general_offline(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *offline_setting; - const gchar *offline_sync; - gboolean is_local_book; - - is_local_book = g_str_has_prefix (e_source_group_peek_base_uri (sdialog->source_group), "file:"); - offline_sync = e_source_get_property (sdialog->source, "offline_sync"); - if (old) - return old; - else { - offline_setting = gtk_check_button_new_with_mnemonic (_("Copy _book content locally for offline operation")); - gtk_widget_show (offline_setting); - gtk_container_add (GTK_CONTAINER (parent), offline_setting); - g_signal_connect (offline_setting, "toggled", G_CALLBACK (offline_status_changed_cb), sdialog); - - } - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (offline_setting), (offline_sync && g_str_equal (offline_sync, "1")) ? TRUE : FALSE); - if (is_local_book) - gtk_widget_hide (offline_setting); - return offline_setting; - -} - -#ifdef HAVE_LDAP -static gchar * -form_ldap_search_filter (GtkWidget *w) -{ - gchar *filter; - const gchar *search_filter = gtk_entry_get_text ((GtkEntry *) w); - - /* this function can be used to format the search filter entered */ - if ((strlen (search_filter) !=0) && *search_filter != '(' && *(search_filter + (strlen (search_filter-1))) != ')') - filter = g_strdup_printf ("(%s)", search_filter); - else - filter = g_strdup_printf ("%s", search_filter); - - return filter; -} - -static void -url_changed(AddressbookSourceDialog *sdialog) -{ - gchar *str, *search_filter; - - search_filter = form_ldap_search_filter (sdialog->search_filter); - str = g_strdup_printf ("%s:%s/%s?" /* trigraph prevention */ "?%s?%s", - gtk_entry_get_text (GTK_ENTRY (sdialog->host)), - gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry)))), - gtk_entry_get_text (GTK_ENTRY (sdialog->rootdn)), - ldap_unparse_scope (sdialog->scope), - search_filter); - e_source_set_relative_uri (sdialog->source, str); - g_free (search_filter); - g_free (str); -} - -static void -host_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - url_changed(sdialog); -} - -static void -port_entry_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - const gchar *port = gtk_entry_get_text((GtkEntry *)w); - - if (!strcmp (port, LDAPS_PORT_STRING)) { - sdialog->ssl = ADDRESSBOOK_LDAP_SSL_ALWAYS; - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->ssl_combobox), sdialog->ssl); - gtk_widget_set_sensitive (sdialog->ssl_combobox, FALSE); - } else { - gtk_widget_set_sensitive (sdialog->ssl_combobox, TRUE); - } - - url_changed(sdialog); -} - -static void -ssl_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - sdialog->ssl = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); - e_source_set_property (sdialog->source, "ssl", ldap_unparse_ssl (sdialog->ssl)); - - gtk_widget_set_tooltip_text (sdialog->ssl_combobox, ldap_get_ssl_tooltip (sdialog->ssl)); -} - -static GtkWidget * -eabc_general_host(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - const gchar *tmp; - GtkWidget *w; - gchar *uri, port[16]; - LDAPURLDesc *lud; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - uri = e_source_get_uri(sdialog->source); - if (ldap_url_parse(uri, &lud) != LDAP_SUCCESS) - lud = NULL; - g_free(uri); - - sdialog->host = glade_xml_get_widget (gui, "server-name-entry"); - gtk_entry_set_text((GtkEntry *)sdialog->host, lud && lud->lud_host ? lud->lud_host : ""); - g_signal_connect (sdialog->host, "changed", G_CALLBACK (host_changed_cb), sdialog); - - sdialog->port_comboentry = glade_xml_get_widget (gui, "port-comboentry"); - gtk_widget_set_has_tooltip (sdialog->port_comboentry, TRUE); - gtk_widget_set_tooltip_text (sdialog->port_comboentry, _("This is the port on the LDAP server that Evolution will try to connect to. A list of standard ports has been provided. Ask your system administrator what port you should specify.")); - sprintf(port, "%u", lud && lud->lud_port? lud->lud_port : LDAP_PORT); - gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry))), port); - g_signal_connect (gtk_bin_get_child (GTK_BIN (sdialog->port_comboentry)), "changed", G_CALLBACK (port_entry_changed_cb), sdialog); - - if (lud) - ldap_free_urldesc (lud); - - sdialog->ssl_combobox = glade_xml_get_widget (gui, "ssl-combobox"); - gtk_widget_set_has_tooltip (sdialog->ssl_combobox, TRUE); - tmp = e_source_get_property (sdialog->source, "ssl"); - sdialog->ssl = tmp ? ldap_parse_ssl (tmp) : ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE; - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->ssl_combobox), sdialog->ssl); - gtk_widget_set_tooltip_text (sdialog->ssl_combobox, ldap_get_ssl_tooltip (sdialog->ssl)); - gtk_widget_set_sensitive (sdialog->ssl_combobox, strcmp (port, LDAPS_PORT_STRING) != 0); - g_signal_connect (sdialog->ssl_combobox, "changed", G_CALLBACK (ssl_combobox_changed_cb), sdialog); - - g_object_unref(gui); - - return w; -} - -static void -auth_entry_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - const gchar *principal = gtk_entry_get_text((GtkEntry *)w); - - /* seems messy ... but the api is */ - switch (sdialog->auth) { - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - e_source_set_property(sdialog->source, "email_addr", NULL); - e_source_set_property(sdialog->source, "binddn", principal); - break; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - e_source_set_property(sdialog->source, "binddn", NULL); - e_source_set_property(sdialog->source, "email_addr", principal); - break; - case ADDRESSBOOK_LDAP_AUTH_NONE: - default: - e_source_set_property(sdialog->source, "email_addr", NULL); - e_source_set_property(sdialog->source, "binddn", NULL); - break; - } -} - -static void -auth_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - sdialog->auth = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); - e_source_set_property (sdialog->source, "auth", ldap_unparse_auth (sdialog->auth)); - - /* make sure the right property is set for the auth - ugh, funny api */ - auth_entry_changed_cb(sdialog->auth_principal, sdialog); -} - -static GtkWidget * -eabc_general_auth(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *w; - const gchar *tmp; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - sdialog->auth_combobox = glade_xml_get_widget (gui, "auth-combobox"); - gtk_widget_set_has_tooltip (sdialog->auth_combobox, TRUE); - gtk_widget_set_tooltip_text (sdialog->auth_combobox, _("This is the method Evolution will use to authenticate you. Note that setting this to \"Email Address\" requires anonymous access to your LDAP server.")); - tmp = e_source_get_property(sdialog->source, "auth"); - sdialog->auth = tmp ? ldap_parse_auth(tmp) : ADDRESSBOOK_LDAP_AUTH_NONE; - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->auth_combobox), sdialog->auth); - g_signal_connect (sdialog->auth_combobox, "changed", G_CALLBACK(auth_combobox_changed_cb), sdialog); - - sdialog->auth_principal = glade_xml_get_widget (gui, "auth-entry"); - switch (sdialog->auth) { - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - tmp = e_source_get_property(sdialog->source, "email_addr"); - break; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - tmp = e_source_get_property(sdialog->source, "binddn"); - break; - case ADDRESSBOOK_LDAP_AUTH_NONE: - default: - tmp = ""; - break; - } - gtk_entry_set_text((GtkEntry *)sdialog->auth_principal, tmp?tmp:""); - g_signal_connect (sdialog->auth_principal, "changed", G_CALLBACK (auth_entry_changed_cb), sdialog); - - g_object_unref(gui); - - return w; -} - -static void -rootdn_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - url_changed(sdialog); -} - -static void -search_filter_changed_cb (GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - url_changed (sdialog); -} - -static void -scope_combobox_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - sdialog->scope = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); - url_changed(sdialog); -} - -static GtkWidget * -eabc_details_search(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *w; - LDAPURLDesc *lud; - gchar *uri; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - uri = e_source_get_uri(sdialog->source); - if (ldap_url_parse(uri, &lud) != LDAP_SUCCESS) - lud = NULL; - g_free(uri); - - sdialog->rootdn = glade_xml_get_widget (gui, "rootdn-entry"); - gtk_entry_set_text((GtkEntry *)sdialog->rootdn, lud && lud->lud_dn ? lud->lud_dn : ""); - g_signal_connect (sdialog->rootdn, "changed", G_CALLBACK (rootdn_changed_cb), sdialog); - - sdialog->scope_combobox = glade_xml_get_widget (gui, "scope-combobox"); - gtk_widget_set_has_tooltip (sdialog->scope_combobox, TRUE); - gtk_widget_set_tooltip_text (sdialog->scope_combobox, _("The search scope defines how deep you would like the search to extend down the directory tree. A search scope of \"sub\" will include all entries below your search base. A search scope of \"one\" will only include the entries one level beneath your base.")); - if (lud) { - switch (lud->lud_scope) { - case LDAP_SCOPE_BASE: - sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_BASE; - break; - default: - case LDAP_SCOPE_ONELEVEL: - sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_ONELEVEL; - break; - case LDAP_SCOPE_SUBTREE: - sdialog->scope = ADDRESSBOOK_LDAP_SCOPE_SUBTREE; - break; - } - } - gtk_combo_box_set_active (GTK_COMBO_BOX (sdialog->scope_combobox), sdialog->scope); - g_signal_connect (sdialog->scope_combobox, "changed", G_CALLBACK(scope_combobox_changed_cb), sdialog); - - sdialog->search_filter = glade_xml_get_widget (gui, "search-filter-entry"); - gtk_entry_set_text((GtkEntry *)sdialog->search_filter, lud && lud->lud_filter ? lud->lud_filter : ""); - g_signal_connect (sdialog->search_filter, "changed", G_CALLBACK (search_filter_changed_cb), sdialog); - - g_signal_connect (glade_xml_get_widget(gui, "rootdn-button"), "clicked", - G_CALLBACK(query_for_supported_bases), sdialog); - - if (lud) - ldap_free_urldesc (lud); - - g_object_unref(gui); - - return w; -} - -static void -timeout_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - gchar *timeout; - - timeout = g_strdup_printf("%f", gtk_adjustment_get_value(((GtkRange *)sdialog->timeout_scale)->adjustment)); - e_source_set_property(sdialog->source, "timeout", timeout); - g_free(timeout); -} - -static void -limit_changed_cb(GtkWidget *w, AddressbookSourceDialog *sdialog) -{ - gchar limit[16]; - - sprintf(limit, "%d", gtk_spin_button_get_value_as_int((GtkSpinButton *)sdialog->limit_spinbutton)); - e_source_set_property(sdialog->source, "limit", limit); -} - -static void -canbrowse_toggled_cb (GtkWidget *toggle_button, ESource *source) -{ - if (!source || !toggle_button) - return; - - e_source_set_property (source, "can-browse", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle_button)) ? "1" : NULL); -} - -static GtkWidget * -eabc_details_limit(EConfig *ec, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - GtkWidget *w; - const gchar *tmp; - GladeXML *gui; - gchar *gladefile; - - if (!source_group_is_remote(sdialog->source_group)) - return NULL; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - gui = glade_xml_new (gladefile, item->label, NULL); - g_free (gladefile); - - w = glade_xml_get_widget(gui, item->label); - gtk_box_pack_start((GtkBox *)parent, w, FALSE, FALSE, 0); - - sdialog->timeout_scale = glade_xml_get_widget (gui, "timeout-scale"); - tmp = e_source_get_property(sdialog->source, "timeout"); - gtk_adjustment_set_value(((GtkRange *)sdialog->timeout_scale)->adjustment, tmp?g_strtod(tmp, NULL):3.0); - g_signal_connect (GTK_RANGE(sdialog->timeout_scale)->adjustment, "value_changed", G_CALLBACK (timeout_changed_cb), sdialog); - - sdialog->limit_spinbutton = glade_xml_get_widget (gui, "download-limit-spinbutton"); - tmp = e_source_get_property(sdialog->source, "limit"); - gtk_spin_button_set_value((GtkSpinButton *)sdialog->limit_spinbutton, tmp?g_strtod(tmp, NULL):100.0); - g_signal_connect (sdialog->limit_spinbutton, "value_changed", G_CALLBACK (limit_changed_cb), sdialog); - - sdialog->canbrowsecheck = glade_xml_get_widget (gui, "canbrowsecheck"); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sdialog->canbrowsecheck), e_source_get_property (sdialog->source, "can-browse") && strcmp (e_source_get_property (sdialog->source, "can-browse"), "1") == 0); - g_signal_connect (sdialog->canbrowsecheck, "toggled", G_CALLBACK (canbrowse_toggled_cb), sdialog->source); - - g_object_unref(gui); - - return w; -} -#endif - -static EConfigItem eabc_items[] = { - { E_CONFIG_BOOK, (gchar *) (gchar *) "", }, - { E_CONFIG_PAGE, (gchar *) "00.general", (gchar *) N_("General") }, - { E_CONFIG_SECTION, (gchar *) "00.general/10.display", (gchar *) N_("Address Book") }, - { E_CONFIG_ITEM, (gchar *) "00.general/10.display/10.name", (gchar *) "hbox122", eabc_general_name }, - { E_CONFIG_ITEM, (gchar *) "00.general/10.display/20.offline", NULL, eabc_general_offline }, -#ifdef HAVE_LDAP - { E_CONFIG_SECTION, (gchar *) "00.general/20.server", (gchar *) N_("Server Information") }, - { E_CONFIG_ITEM, (gchar *) "00.general/20.server/00.host", (gchar *) "table31", eabc_general_host }, - { E_CONFIG_SECTION, (gchar *) "00.general/30.auth", (gchar *) N_("Authentication") }, - { E_CONFIG_ITEM, (gchar *) "00.general/30.auth/00.auth", (gchar *) "table32", eabc_general_auth }, - - { E_CONFIG_PAGE, (gchar *) "10.details", (gchar *) N_("Details") }, - { E_CONFIG_SECTION, (gchar *) "10.details/00.search", (gchar *) N_("Searching") }, - { E_CONFIG_ITEM, (gchar *) "10.details/00.search/00.search", (gchar *) "table33", eabc_details_search }, - { E_CONFIG_SECTION, (gchar *) "10.details/10.limit", (gchar *) N_("Downloading") }, - { E_CONFIG_ITEM, (gchar *) "10.details/10.limit/00.limit", (gchar *) "table34", eabc_details_limit }, -#endif - { 0 }, -}; - -/* items needed for the 'new addressbook' window */ -static EConfigItem eabc_new_items[] = { - { E_CONFIG_ITEM, (gchar *) "00.general/10.display/00.type", NULL, eabc_general_type }, - { 0 }, -}; - -static void -eabc_commit(EConfig *ec, GSList *items, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - xmlNodePtr xml; -#if d(!)0 - gchar *txt; -#endif - if (sdialog->original_source) { - d(printf("committing addressbook changes\n")); - - /* these api's kinda suck */ - xml = xmlNewNode(NULL, (const guchar *)"dummy"); - e_source_dump_to_xml_node(sdialog->source, xml); - e_source_update_from_xml_node(sdialog->original_source, xml->children, NULL); - xmlFreeNode(xml); -#if d(!)0 - txt = e_source_to_standalone_xml(sdialog->original_source); - printf("source is now:\n%s\n", txt); - g_free(txt); -#endif - } else { - d(printf("committing new source\n")); - e_source_group_add_source(sdialog->source_group, sdialog->source, -1); - e_source_list_sync(sdialog->source_list, NULL); - } - -#if d(!)0 - txt = e_source_to_standalone_xml(sdialog->source); - printf("running source is now:\n%s\n", txt); - g_free(txt); -#endif -} - -static void -eabc_free(EConfig *ec, GSList *items, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - - g_slist_free(items); - - g_object_unref(sdialog->source); - if (sdialog->original_source) - g_object_unref(sdialog->original_source); - if (sdialog->source_list) - g_object_unref(sdialog->source_list); - g_slist_free(sdialog->menu_source_groups); - - g_object_unref(sdialog->gui); - - g_free(sdialog); -} - -static gboolean -eabc_check_complete(EConfig *ec, const gchar *pageid, gpointer data) -{ - AddressbookSourceDialog *sdialog = data; - gint valid = TRUE; - const gchar *tmp; - ESource *source; - - d(printf("check complete, pageid = '%s'\n", pageid?pageid:"<all>")); - /* have name, and unique */ - tmp = e_source_peek_name(sdialog->source); - valid = tmp && tmp[0] != 0 - && ((source = e_source_group_peek_source_by_name(sdialog->source_group, tmp)) == NULL - || source == sdialog->original_source); - -#ifdef HAVE_LDAP - if (valid && source_group_is_remote(sdialog->source_group)) { - gchar *uri = e_source_get_uri(sdialog->source); - LDAPURLDesc *lud; - - /* check host and port set */ - if (ldap_url_parse(uri, &lud) == LDAP_SUCCESS) { - valid = lud->lud_host != NULL - && lud->lud_host[0] != 0 - && lud->lud_port != 0; - ldap_free_urldesc (lud); - } else - valid = FALSE; - g_free(uri); - - /* check auth name provided if auth set */ - if (valid && (tmp = e_source_get_property(sdialog->source, "auth"))) { - switch (ldap_parse_auth(tmp)) { - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL: - tmp = e_source_get_property(sdialog->source, "email_addr"); - break; - case ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN: - tmp = e_source_get_property(sdialog->source, "binddn"); - break; - default: - tmp = "dummy"; - break; - } - valid = tmp && tmp[0]; - } - - /* check timeout isn't too short (why don't we just force it?) */ - if (valid) { - tmp = e_source_get_property(sdialog->source, "timeout"); - valid = tmp && g_strtod(tmp, NULL) > 0.0; - } - } -#endif - return valid; -} - -/* debug only: */ -#if d(!)0 -static void -source_changed(ESource *source, AddressbookSourceDialog *sdialog) -{ - gchar *xml; - - xml = e_source_to_standalone_xml(source); - printf("source changed:\n%s\n", xml); - g_free(xml); -} -#endif - -GtkWidget* -addressbook_config_edit_source (GtkWidget *parent, ESource *source) -{ - AddressbookSourceDialog *sdialog = g_new0 (AddressbookSourceDialog, 1); - EABConfig *ec; - gint i; - GSList *items = NULL; - EABConfigTargetSource *target; - gchar *xml; - gchar *gladefile; - - gladefile = g_build_filename (EVOLUTION_GLADEDIR, - GLADE_FILE_NAME, - NULL); - sdialog->gui = glade_xml_new (gladefile, "account-editor-notebook", NULL); - g_free (gladefile); - - if (source) { - sdialog->original_source = source; - g_object_ref(source); - sdialog->source_group = e_source_peek_group (source); - xml = e_source_to_standalone_xml(source); - sdialog->source = e_source_new_from_standalone_xml(xml); - g_free(xml); - } else { - GConfClient *gconf; - GSList *l; - - sdialog->source = e_source_new("", ""); - gconf = gconf_client_get_default(); - sdialog->source_list = e_source_list_new_for_gconf(gconf, "/apps/evolution/addressbook/sources"); - l = e_source_list_peek_groups(sdialog->source_list); - if (!l) { - g_warning ("Address Book source groups are missing! Check your GConf setup."); - g_object_unref (gconf); - g_free (sdialog); - return NULL; - } - - sdialog->menu_source_groups = g_slist_copy(l); -#ifndef HAVE_LDAP - for (;l;l = g_slist_next(l)) - if (!strncmp("ldap:", e_source_group_peek_base_uri(l->data), 5)) - sdialog->menu_source_groups = g_slist_remove (sdialog->menu_source_groups, l->data); -#endif - sdialog->source_group = (ESourceGroup *)sdialog->menu_source_groups->data; - for (i=0;eabc_new_items[i].path;i++) - items = g_slist_prepend(items, &eabc_new_items[i]); - g_object_unref(gconf); - } - - /* HACK: doesn't work if you don't do this */ - e_source_set_group(sdialog->source, sdialog->source_group); - -#if d(!)0 - xml = e_source_to_standalone_xml(sdialog->source); - printf("but working standalone xml: %s\n", xml); - g_free(xml); - g_signal_connect(sdialog->source, "changed", source_changed, sdialog); -#endif - - sdialog->config = ec = eab_config_new(E_CONFIG_BOOK, "com.novell.evolution.addressbook.config.accountEditor"); - - for (i=0;eabc_items[i].path;i++) { - if (eabc_items[i].label) - eabc_items[i].label = gettext(eabc_items[i].label); - items = g_slist_prepend(items, &eabc_items[i]); - } - - e_config_add_items((EConfig *)ec, items, eabc_commit, NULL, eabc_free, sdialog); - e_config_add_page_check((EConfig *)ec, NULL, eabc_check_complete, sdialog); - - target = eab_config_target_new_source(ec, sdialog->source); - e_config_set_target((EConfig *)ec, (EConfigTarget *)target); - - if (source) - sdialog->window = e_config_create_window((EConfig *)ec, NULL, _("Address Book Properties")); - else - sdialog->window = e_config_create_window((EConfig *)ec, NULL, _("New Address Book")); - - /* forces initial validation */ - if (!sdialog->original_source) - e_config_target_changed((EConfig *)ec, E_CONFIG_TARGET_CHANGED_STATE); - - return sdialog->window; -} diff --git a/addressbook/gui/component/addressbook-config.h b/addressbook/gui/component/addressbook-config.h deleted file mode 100644 index 0cfcb95b56..0000000000 --- a/addressbook/gui/component/addressbook-config.h +++ /dev/null @@ -1,51 +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: - * Chris Toshok <toshok@ximian.com> - * Chris Lahey <clahey@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __ADDRESSBOOK_CONFIG_H__ -#define __ADDRESSBOOK_CONFIG_H__ - -#include "evolution-config-control.h" - -typedef enum { - ADDRESSBOOK_LDAP_AUTH_NONE, - ADDRESSBOOK_LDAP_AUTH_SIMPLE_EMAIL, - ADDRESSBOOK_LDAP_AUTH_SIMPLE_BINDDN -} AddressbookLDAPAuthType; - -typedef enum { - ADDRESSBOOK_LDAP_SCOPE_ONELEVEL, - ADDRESSBOOK_LDAP_SCOPE_SUBTREE, - ADDRESSBOOK_LDAP_SCOPE_BASE, - ADDRESSBOOK_LDAP_SCOPE_LAST -} AddressbookLDAPScopeType; - -typedef enum { - ADDRESSBOOK_LDAP_SSL_ALWAYS, - ADDRESSBOOK_LDAP_SSL_WHENEVER_POSSIBLE, - ADDRESSBOOK_LDAP_SSL_NEVER -} AddressbookLDAPSSLType; - -GtkWidget* addressbook_config_edit_source (GtkWidget *parent, ESource *source); -GtkWidget* addressbook_config_create_new_source (GtkWidget *parent); - -#endif /* __ADDRESSBOOK_CONFIG_H__ */ diff --git a/addressbook/gui/component/addressbook-migrate.c b/addressbook/gui/component/addressbook-migrate.c deleted file mode 100644 index 424a39c730..0000000000 --- a/addressbook/gui/component/addressbook-migrate.c +++ /dev/null @@ -1,1213 +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: - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include <config.h> - -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#include <gtk/gtk.h> - -#include <libebook/e-destination.h> -#include <libebook/e-book.h> -#include <glib/gi18n.h> - -#include <libedataserver/e-xml-utils.h> - -#include "e-util/e-util.h" -#include "e-util/e-util-private.h" -#include "e-util/e-xml-utils.h" -#include "e-util/e-folder-map.h" - -#include "addressbook-migrate.h" - -/*#define SLOW_MIGRATION*/ - -typedef struct { - /* this hash table maps old folder uris to new uids. It's - build in migrate_contact_folder and it's used in - migrate_completion_folders. */ - GHashTable *folder_uid_map; - - ESourceList *source_list; - - AddressbookComponent *component; - - GtkWidget *window; - GtkWidget *label; - GtkWidget *folder_label; - GtkWidget *progress; -} MigrationContext; - -static void -setup_progress_dialog (MigrationContext *context) -{ - GtkWidget *vbox, *hbox; - - context->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (context->window), _("Migrating...")); - gtk_window_set_modal (GTK_WINDOW (context->window), TRUE); - gtk_container_set_border_width (GTK_CONTAINER (context->window), 6); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_show (vbox); - gtk_container_add (GTK_CONTAINER (context->window), vbox); - - context->label = gtk_label_new (""); - gtk_label_set_line_wrap (GTK_LABEL (context->label), TRUE); - gtk_widget_show (context->label); - gtk_box_pack_start (GTK_BOX (vbox), context->label, TRUE, TRUE, 0); - - hbox = gtk_hbox_new (FALSE, 6); - gtk_widget_show (hbox); - gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0); - - context->folder_label = gtk_label_new (""); - gtk_widget_show (context->folder_label); - gtk_box_pack_start (GTK_BOX (hbox), context->folder_label, TRUE, TRUE, 0); - - context->progress = gtk_progress_bar_new (); - gtk_widget_show (context->progress); - gtk_box_pack_start (GTK_BOX (hbox), context->progress, TRUE, TRUE, 0); - - gtk_widget_show (context->window); -} - -static void -dialog_close (MigrationContext *context) -{ - gtk_widget_destroy (context->window); -} - -static void -dialog_set_label (MigrationContext *context, const gchar *str) -{ - gtk_label_set_text (GTK_LABEL (context->label), str); - - while (gtk_events_pending ()) - gtk_main_iteration (); - -#ifdef SLOW_MIGRATION - sleep (1); -#endif -} - -static void -dialog_set_folder_name (MigrationContext *context, const gchar *folder_name) -{ - gchar *text; - - text = g_strdup_printf (_("Migrating '%s':"), folder_name); - gtk_label_set_text (GTK_LABEL (context->folder_label), text); - g_free (text); - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (context->progress), 0.0); - - while (gtk_events_pending ()) - gtk_main_iteration (); - -#ifdef SLOW_MIGRATION - sleep (1); -#endif -} - -static void -dialog_set_progress (MigrationContext *context, double percent) -{ - gchar text[5]; - - snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f)); - - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (context->progress), percent); - gtk_progress_bar_set_text (GTK_PROGRESS_BAR (context->progress), text); - - while (gtk_events_pending ()) - gtk_main_iteration (); - -#ifdef SLOW_MIGRATION - sleep (1); -#endif -} - -static gboolean -check_for_conflict (ESourceGroup *group, gchar *name) -{ - GSList *sources; - GSList *s; - - sources = e_source_group_peek_sources (group); - - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - - if (!strcmp (e_source_peek_name (source), name)) - return TRUE; - } - - return FALSE; -} - -static gchar * -get_source_name (ESourceGroup *group, const gchar *path) -{ -#ifndef G_OS_WIN32 - gchar **p = g_strsplit (path, "/", 0); -#else - gchar **p = g_strsplit_set (path, "\\/", 0); -#endif - gint i, j, starting_index; - gint num_elements; - gboolean conflict; - GString *s = g_string_new (""); - - for (i = 0; p[i]; i ++); - - num_elements = i; - i--; - - /* p[i] is now the last path element */ - - /* check if it conflicts */ - starting_index = i; - do { - g_string_assign (s, ""); - for (j = starting_index; j < num_elements; j += 2) { - if (j != starting_index) - g_string_append_c (s, '_'); - g_string_append (s, p[j]); - } - - conflict = check_for_conflict (group, s->str); - - /* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */ - if (conflict) - starting_index -= 2; - - /* we always break out if we can't go any further, - regardless of whether or not we conflict. */ - if (starting_index < 0) - break; - - } while (conflict); - - g_strfreev (p); - - return g_string_free (s, FALSE); -} - -static void -migrate_contacts (MigrationContext *context, EBook *old_book, EBook *new_book) -{ - EBookQuery *query = e_book_query_any_field_contains (""); - GList *l, *contacts; - gint num_added = 0; - gint num_contacts; - - /* both books are loaded, start the actual migration */ - e_book_get_contacts (old_book, query, &contacts, NULL); - e_book_query_unref (query); - - num_contacts = g_list_length (contacts); - for (l = contacts; l; l = l->next) { - EContact *contact = l->data; - GError *e = NULL; - GList *attrs, *attr; - - /* do some last minute massaging of the contact's attributes */ - - attrs = e_vcard_get_attributes (E_VCARD (contact)); - for (attr = attrs; attr;) { - EVCardAttribute *a = attr->data; - - /* evo 1.4 used the non-standard X-EVOLUTION-OFFICE attribute, - evo 1.5 uses the third element in the ORG list attribute. */ - if (!strcmp ("X-EVOLUTION-OFFICE", e_vcard_attribute_get_name (a))) { - GList *v = e_vcard_attribute_get_values (a); - GList *next_attr; - - if (v && v->data) - e_contact_set (contact, E_CONTACT_OFFICE, v->data); - - next_attr = attr->next; - e_vcard_remove_attribute (E_VCARD (contact), a); - attr = next_attr; - } - /* evo 1.4 didn't put TYPE=VOICE in for phone numbers. - evo 1.5 does. - - so we search through the attribute params for - either TYPE=VOICE or TYPE=FAX. If we find - either we do nothing. If we find neither, we - add TYPE=VOICE. - */ - else if (!strcmp ("TEL", e_vcard_attribute_get_name (a))) { - GList *params, *param; - gboolean found = FALSE; - - params = e_vcard_attribute_get_params (a); - for (param = params; param; param = param->next) { - EVCardAttributeParam *p = param->data; - if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { - GList *v = e_vcard_attribute_param_get_values (p); - while (v && v->data) { - if (!strcmp ("VOICE", v->data) - || !strcmp ("FAX", v->data)) { - found = TRUE; - break; - } - v = v->next; - } - } - } - - if (!found) - e_vcard_attribute_add_param_with_value (a, - e_vcard_attribute_param_new (EVC_TYPE), - "VOICE"); - attr = attr->next; - } - /* Replace "POSTAL" (1.4) addresses with "OTHER" (1.5) */ - else if (!strcmp ("ADR", e_vcard_attribute_get_name (a))) { - GList *params, *param; - gboolean found = FALSE; - EVCardAttributeParam *p; - - params = e_vcard_attribute_get_params (a); - for (param = params; param; param = param->next) { - p = param->data; - if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { - GList *v = e_vcard_attribute_param_get_values (p); - while (v && v->data ) { - if (!strcmp ("POSTAL", v->data)) { - found = TRUE; - break; - } - v = v->next; - } - if (found) - break; - } - } - - if (found) { - e_vcard_attribute_param_remove_values (p); - e_vcard_attribute_param_add_value (p, "OTHER"); - } - - attr = attr->next; - } - /* this is kinda gross. The new vcard parser - needs ';'s to be escaped by \'s. but the - 1.4 vcard generator would put unescaped xml - (including entities like >) in the value - of attributes, so we need to go through and - escape those ';'s. */ - else if (!strcmp ("EMAIL", e_vcard_attribute_get_name (a))) { - GList *params; - GList *v = e_vcard_attribute_get_values (a); - - /* Add TYPE=OTHER if there is no type set */ - params = e_vcard_attribute_get_params (a); - if (!params) - e_vcard_attribute_add_param_with_value (a, - e_vcard_attribute_param_new (EVC_TYPE), - "OTHER"); - - if (v && v->data) { - if (!strncmp ((gchar *)v->data, "<?xml", 5)) { - /* k, this is the nasty part. we glomb all the - value strings back together again (if there is - more than one), then work our magic */ - GString *str = g_string_new (""); - while (v) { - g_string_append (str, v->data); - if (v->next) - g_string_append_c (str, ';'); - v = v->next; - } - - e_vcard_attribute_remove_values (a); - e_vcard_attribute_add_value (a, str->str); - g_string_free (str, TRUE); - } - } - - attr = attr->next; - } - else { - attr = attr->next; - } - } - - if (!e_book_add_contact (new_book, - contact, - &e)) - g_warning ("contact add failed: `%s'", e->message); - - num_added ++; - - dialog_set_progress (context, (double)num_added / num_contacts); - } - - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); -} - -static void -migrate_contact_folder_to_source (MigrationContext *context, gchar *old_path, ESource *new_source) -{ - gchar *old_uri = g_filename_to_uri (old_path, NULL, NULL); - GError *e = NULL; - - EBook *old_book = NULL, *new_book = NULL; - ESource *old_source; - ESourceGroup *group; - - group = e_source_group_new ("", old_uri); - old_source = e_source_new ("", ""); - e_source_group_add_source (group, old_source, -1); - - dialog_set_folder_name (context, e_source_peek_name (new_source)); - - old_book = e_book_new (old_source, &e); - if (!old_book - || !e_book_open (old_book, TRUE, &e)) { - g_warning ("failed to load source book for migration: `%s'", e->message); - goto finish; - } - - new_book = e_book_new (new_source, &e); - if (!new_book - || !e_book_open (new_book, FALSE, &e)) { - g_warning ("failed to load destination book for migration: `%s'", e->message); - goto finish; - } - - migrate_contacts (context, old_book, new_book); - - finish: - g_object_unref (old_source); - g_object_unref (group); - if (old_book) - g_object_unref (old_book); - if (new_book) - g_object_unref (new_book); - g_free (old_uri); -} - -static void -migrate_contact_folder (MigrationContext *context, gchar *old_path, ESourceGroup *dest_group, gchar *source_name) -{ - ESource *new_source; - - new_source = e_source_new (source_name, source_name); - e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); - e_source_group_add_source (dest_group, new_source, -1); - - g_hash_table_insert (context->folder_uid_map, g_strdup (old_path), g_strdup (e_source_peek_uid (new_source))); - - migrate_contact_folder_to_source (context, old_path, new_source); - - g_object_unref (new_source); -} - -#define LDAP_BASE_URI "ldap://" -#define PERSONAL_RELATIVE_URI "system" - -static void -create_groups (MigrationContext *context, - ESourceGroup **on_this_computer, - ESourceGroup **on_ldap_servers, - ESource **personal_source) -{ - GSList *groups; - ESourceGroup *group; - gchar *base_uri, *base_uri_proto; - const gchar *base_dir; - - *on_this_computer = NULL; - *on_ldap_servers = NULL; - *personal_source = NULL; - - base_dir = addressbook_component_peek_base_directory (context->component); - base_uri = g_build_filename (base_dir, "local", NULL); - - base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL); - - groups = e_source_list_peek_groups (context->source_list); - if (groups) { - /* groups are already there, we need to search for things... */ - GSList *g; - - for (g = groups; g; g = g->next) { - - group = E_SOURCE_GROUP (g->data); - - if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) - *on_this_computer = g_object_ref (group); - else if (!*on_ldap_servers && !strcmp (LDAP_BASE_URI, e_source_group_peek_base_uri (group))) - *on_ldap_servers = g_object_ref (group); - } - } - - if (*on_this_computer) { - /* make sure "Personal" shows up as a source under - this group */ - GSList *sources = e_source_group_peek_sources (*on_this_computer); - GSList *s; - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *relative_uri; - - relative_uri = e_source_peek_relative_uri (source); - if (relative_uri == NULL) - continue; - if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) { - *personal_source = g_object_ref (source); - break; - } - } - } - else { - /* create the local source group */ - group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (context->source_list, group, -1); - - *on_this_computer = group; - } - - if (!*personal_source) { - /* Create the default Person addressbook */ - ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (*on_this_computer, source, -1); - - e_source_set_property (source, "completion", "true"); - - *personal_source = source; - } - - if (!*on_ldap_servers) { - /* Create the LDAP source group */ - group = e_source_group_new (_("On LDAP Servers"), LDAP_BASE_URI); - e_source_list_add_group (context->source_list, group, -1); - - *on_ldap_servers = group; - } - - g_free (base_uri_proto); - g_free (base_uri); -} - -static gboolean -migrate_local_folders (MigrationContext *context, ESourceGroup *on_this_computer, ESource *personal_source) -{ - gchar *old_path = NULL; - GSList *dirs, *l; - gchar *local_contact_folder = NULL; - - old_path = g_strdup_printf ("%s/evolution/local", g_get_home_dir ()); - - dirs = e_folder_map_local_folders (old_path, "contacts"); - - /* migrate the local addressbook first, to local/system */ - local_contact_folder = g_build_filename (g_get_home_dir (), - "evolution", "local", "Contacts", - NULL); - - for (l = dirs; l; l = l->next) { - gchar *source_name; - /* we handle the system folder differently */ - if (personal_source && !strcmp ((gchar *)l->data, local_contact_folder)) { - g_hash_table_insert (context->folder_uid_map, g_strdup (l->data), g_strdup (e_source_peek_uid (personal_source))); - migrate_contact_folder_to_source (context, local_contact_folder, personal_source); - continue; - } - - source_name = get_source_name (on_this_computer, (gchar *)l->data); - migrate_contact_folder (context, l->data, on_this_computer, source_name); - g_free (source_name); - } - - g_slist_foreach (dirs, (GFunc)g_free, NULL); - g_slist_free (dirs); - g_free (local_contact_folder); - g_free (old_path); - - return TRUE; -} - -static gchar * -get_string_child (xmlNode *node, - const gchar *name) -{ - xmlNode *p; - xmlChar *xml_string; - gchar *retval; - - p = e_xml_get_child_by_name (node, (xmlChar *) name); - if (p == NULL) - return NULL; - - p = e_xml_get_child_by_name (p, (xmlChar *) "text"); - if (p == NULL) /* there's no text between the tags, return the empty string */ - return g_strdup(""); - - xml_string = xmlNodeListGetString (node->doc, p, 1); - retval = g_strdup ((gchar *) xml_string); - xmlFree (xml_string); - - return retval; -} - -static gint -get_integer_child (xmlNode *node, - const gchar *name, - gint defval) -{ - xmlNode *p; - xmlChar *xml_string; - gint retval; - - p = e_xml_get_child_by_name (node, (xmlChar *) name); - if (p == NULL) - return defval; - - p = e_xml_get_child_by_name (p, (xmlChar *) "text"); - if (p == NULL) /* there's no text between the tags, return the default */ - return defval; - - xml_string = xmlNodeListGetString (node->doc, p, 1); - retval = atoi ((gchar *)xml_string); - xmlFree (xml_string); - - return retval; -} - -static gboolean -migrate_ldap_servers (MigrationContext *context, ESourceGroup *on_ldap_servers) -{ - gchar *sources_xml = g_strdup_printf ("%s/evolution/addressbook-sources.xml", - g_get_home_dir ()); - - printf ("trying to migrate from %s\n", sources_xml); - - if (g_file_test (sources_xml, G_FILE_TEST_EXISTS)) { - xmlDoc *doc = xmlParseFile (sources_xml); - xmlNode *root; - xmlNode *child; - gint num_contactservers; - gint servernum; - - if (!doc) - return FALSE; - - root = xmlDocGetRootElement (doc); - if (root == NULL || strcmp ((const gchar *)root->name, "addressbooks") != 0) { - xmlFreeDoc (doc); - return FALSE; - } - - /* count the number of servers, so we can give progress */ - num_contactservers = 0; - for (child = root->children; child; child = child->next) { - if (!strcmp ((const gchar *)child->name, "contactserver")) { - num_contactservers++; - } - } - printf ("found %d contact servers to migrate\n", num_contactservers); - - dialog_set_folder_name (context, _("LDAP Servers")); - - servernum = 0; - for (child = root->children; child; child = child->next) { - if (!strcmp ((const gchar *)child->name, "contactserver")) { - gchar *port, *host, *rootdn, *scope, *authmethod, *ssl; - gchar *emailaddr, *binddn, *limitstr; - gint limit; - gchar *name, *description; - GString *uri = g_string_new (""); - ESource *source; - - name = get_string_child (child, "name"); - description = get_string_child (child, "description"); - port = get_string_child (child, "port"); - host = get_string_child (child, "host"); - rootdn = get_string_child (child, "rootdn"); - scope = get_string_child (child, "scope"); - authmethod = get_string_child (child, "authmethod"); - ssl = get_string_child (child, "ssl"); - emailaddr = get_string_child (child, "emailaddr"); - binddn = get_string_child (child, "binddn"); - limit = get_integer_child (child, "limit", 100); - limitstr = g_strdup_printf ("%d", limit); - - g_string_append_printf (uri, - "%s:%s/%s?"/*trigraph prevention*/"?%s", - host, port, rootdn, scope); - - source = e_source_new (name, uri->str); - e_source_set_property (source, "description", description); - e_source_set_property (source, "limit", limitstr); - e_source_set_property (source, "ssl", ssl); - e_source_set_property (source, "auth", authmethod); - if (emailaddr) - e_source_set_property (source, "email_addr", emailaddr); - if (binddn) - e_source_set_property (source, "binddn", binddn); - - e_source_group_add_source (on_ldap_servers, source, -1); - - g_string_free (uri, TRUE); - g_free (port); - g_free (host); - g_free (rootdn); - g_free (scope); - g_free (authmethod); - g_free (ssl); - g_free (emailaddr); - g_free (binddn); - g_free (limitstr); - g_free (name); - g_free (description); - - servernum++; - dialog_set_progress (context, (double)servernum/num_contactservers); - } - } - - xmlFreeDoc (doc); - } - - g_free (sources_xml); - - return TRUE; -} - -static ESource* -get_source_by_name (ESourceList *source_list, const gchar *name) -{ - GSList *groups; - GSList *g; - - groups = e_source_list_peek_groups (source_list); - if (!groups) - return NULL; - - for (g = groups; g; g = g->next) { - GSList *sources; - GSList *s; - ESourceGroup *group = E_SOURCE_GROUP (g->data); - - sources = e_source_group_peek_sources (group); - if (!sources) - continue; - - for (s = sources; s; s = s->next) { - ESource *source = E_SOURCE (s->data); - const gchar *source_name = e_source_peek_name (source); - - if (!strcmp (name, source_name)) - return source; - } - } - - return NULL; -} - -static gboolean -migrate_completion_folders (MigrationContext *context) -{ - gchar *uris_xml = gconf_client_get_string (addressbook_component_peek_gconf_client (context->component), - "/apps/evolution/addressbook/completion/uris", - NULL); - - printf ("trying to migrate completion folders\n"); - - if (uris_xml) { - xmlDoc *doc = xmlParseMemory (uris_xml, strlen (uris_xml)); - xmlNode *root; - xmlNode *child; - - if (!doc) - return FALSE; - - dialog_set_folder_name (context, _("Autocompletion Settings")); - - root = xmlDocGetRootElement (doc); - if (root == NULL || strcmp ((const gchar *)root->name, "EvolutionFolderList") != 0) { - xmlFreeDoc (doc); - return FALSE; - } - - for (child = root->children; child; child = child->next) { - if (!strcmp ((const gchar *)child->name, "folder")) { - gchar *physical_uri = e_xml_get_string_prop_by_name (child, (const guchar *)"physical-uri"); - ESource *source = NULL; - - /* if the physical uri is file://... - we look it up in our folder_uid_map - hashtable. If it's a folder we - converted over, we should get back - a uid we can search for. - - if the physical_uri is anything - else, we strip off the args - (anything after;) before searching - for the uri. */ - - if (!strncmp (physical_uri, "file://", 7)) { - gchar *filename = g_filename_from_uri (physical_uri, NULL, NULL); - gchar *uid = NULL; - - if (filename) - uid = g_hash_table_lookup (context->folder_uid_map, - filename); - g_free (filename); - if (uid) - source = e_source_list_peek_source_by_uid (context->source_list, uid); - } - else { - gchar *name = e_xml_get_string_prop_by_name (child, (const guchar *)"display-name"); - - source = get_source_by_name (context->source_list, name); - - g_free (name); - } - - if (source) { - e_source_set_property (source, "completion", "true"); - } - else { - g_warning ("found completion folder with uri `%s' that " - "doesn't correspond to anything we migrated.", physical_uri); - } - - g_free (physical_uri); - } - } - - g_free (uris_xml); - } - else { - g_message ("no completion folder settings to migrate"); - } - - return TRUE; -} - -static void -migrate_contact_lists_for_local_folders (MigrationContext *context, ESourceGroup *on_this_computer) -{ - GSList *sources, *s; - - sources = e_source_group_peek_sources (on_this_computer); - for (s = sources; s; s = s->next) { - ESource *source = s->data; - EBook *book; - EBookQuery *query; - GList *l, *contacts; - gint num_contacts, num_converted; - - dialog_set_folder_name (context, e_source_peek_name (source)); - - book = e_book_new (source, NULL); - if (!book - || !e_book_open (book, TRUE, NULL)) { - gchar *uri = e_source_get_uri (source); - g_warning ("failed to migrate contact lists for source %s", uri); - g_free (uri); - continue; - } - - query = e_book_query_any_field_contains (""); - e_book_get_contacts (book, query, &contacts, NULL); - e_book_query_unref (query); - - num_converted = 0; - num_contacts = g_list_length (contacts); - for (l = contacts; l; l = l->next) { - EContact *contact = l->data; - GError *e = NULL; - GList *attrs, *attr; - gboolean converted = FALSE; - - attrs = e_contact_get_attributes (contact, E_CONTACT_EMAIL); - for (attr = attrs; attr; attr = attr->next) { - EVCardAttribute *a = attr->data; - GList *v = e_vcard_attribute_get_values (a); - - if (v && v->data) { - if (!strncmp ((gchar *)v->data, "<?xml", 5)) { - EDestination *dest = e_destination_import ((gchar *)v->data); - - e_destination_export_to_vcard_attribute (dest, a); - - g_object_unref (dest); - - converted = TRUE; - } - } - } - - if (converted) { - e_contact_set_attributes (contact, E_CONTACT_EMAIL, attrs); - - if (!e_book_commit_contact (book, - contact, - &e)) - g_warning ("contact commit failed: `%s'", e->message); - } - - num_converted ++; - - dialog_set_progress (context, (double)num_converted / num_contacts); - } - - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); - - g_object_unref (book); - } -} - -static void -migrate_company_phone_for_local_folders (MigrationContext *context, ESourceGroup *on_this_computer) -{ - GSList *sources, *s; - - sources = e_source_group_peek_sources (on_this_computer); - for (s = sources; s; s = s->next) { - ESource *source = s->data; - EBook *book; - EBookQuery *query; - GList *l, *contacts; - gint num_contacts, num_converted; - - dialog_set_folder_name (context, e_source_peek_name (source)); - - book = e_book_new (source, NULL); - if (!book - || !e_book_open (book, TRUE, NULL)) { - gchar *uri = e_source_get_uri (source); - g_warning ("failed to migrate company phone numbers for source %s", uri); - g_free (uri); - continue; - } - - query = e_book_query_any_field_contains (""); - e_book_get_contacts (book, query, &contacts, NULL); - e_book_query_unref (query); - - num_converted = 0; - num_contacts = g_list_length (contacts); - for (l = contacts; l; l = l->next) { - EContact *contact = l->data; - GError *e = NULL; - GList *attrs, *attr; - gboolean converted = FALSE; - gint num_work_voice = 0; - - attrs = e_vcard_get_attributes (E_VCARD (contact)); - for (attr = attrs; attr;) { - EVCardAttribute *a = attr->data; - GList *next_attr = attr->next; - - if (!strcmp ("TEL", e_vcard_attribute_get_name (a))) { - GList *params, *param; - gboolean found_voice = FALSE; - gboolean found_work = FALSE; - - params = e_vcard_attribute_get_params (a); - for (param = params; param; param = param->next) { - EVCardAttributeParam *p = param->data; - if (!strcmp (EVC_TYPE, e_vcard_attribute_param_get_name (p))) { - GList *v = e_vcard_attribute_param_get_values (p); - while (v && v->data) { - if (!strcmp ("VOICE", v->data)) - found_voice = TRUE; - else if (!strcmp ("WORK", v->data)) - found_work = TRUE; - v = v->next; - } - } - - if (found_work && found_voice) - num_work_voice++; - - if (num_work_voice == 3) { - GList *v = e_vcard_attribute_get_values (a); - - if (v && v->data) - e_contact_set (contact, E_CONTACT_PHONE_COMPANY, v->data); - - e_vcard_remove_attribute (E_VCARD (contact), a); - - converted = TRUE; - break; - } - } - } - - attr = next_attr; - - if (converted) - break; - } - - if (converted) { - if (!e_book_commit_contact (book, - contact, - &e)) - g_warning ("contact commit failed: `%s'", e->message); - } - - num_converted ++; - - dialog_set_progress (context, (double)num_converted / num_contacts); - } - - g_list_foreach (contacts, (GFunc)g_object_unref, NULL); - g_list_free (contacts); - - g_object_unref (book); - } -} - -static void -migrate_pilot_data (const gchar *old_path, const gchar *new_path) -{ - const gchar *dent; - const gchar *ext; - gchar *filename; - GDir *dir; - - if (!(dir = g_dir_open (old_path, 0, NULL))) - return; - - while ((dent = g_dir_read_name (dir))) { - if ((!strncmp (dent, "pilot-map-", 10) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) || - (!strncmp (dent, "pilot-sync-evolution-addressbook-", 33) && - ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db")))) { - /* src and dest file formats are identical for both map and changelog files */ - guchar inbuf[4096]; - gsize nread, nwritten; - gint fd0, fd1; - gssize n; - - filename = g_build_filename (old_path, dent, NULL); - if ((fd0 = g_open (filename, O_RDONLY | O_BINARY, 0)) == -1) { - g_free (filename); - continue; - } - - g_free (filename); - filename = g_build_filename (new_path, dent, NULL); - if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) { - g_free (filename); - close (fd0); - continue; - } - - do { - do { - n = read (fd0, inbuf, sizeof (inbuf)); - } while (n == -1 && errno == EINTR); - - if (n < 1) - break; - - nread = n; - nwritten = 0; - do { - do { - n = write (fd1, inbuf + nwritten, nread - nwritten); - } while (n == -1 && errno == EINTR); - - if (n > 0) - nwritten += n; - } while (nwritten < nread && n != -1); - - if (n == -1) - break; - } while (1); - - if (n != -1) - n = fsync (fd1); - - if (n == -1) { - g_warning ("Failed to migrate %s: %s", dent, g_strerror (errno)); - g_unlink (filename); - } - - close (fd0); - close (fd1); - g_free (filename); - } - } - - g_dir_close (dir); -} - -static MigrationContext* -migration_context_new (AddressbookComponent *component) -{ - MigrationContext *context = g_new (MigrationContext, 1); - - /* set up the mapping from old uris to new uids */ - context->folder_uid_map = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free); - - e_book_get_addressbooks (&context->source_list, NULL); - - context->component = component; - - return context; -} - -static void -migration_context_free (MigrationContext *context) -{ - e_source_list_sync (context->source_list, NULL); - - g_hash_table_destroy (context->folder_uid_map); - - g_object_unref (context->source_list); - - g_free (context); -} - -gint -addressbook_migrate (AddressbookComponent *component, gint major, gint minor, gint revision, GError **err) -{ - ESourceGroup *on_this_computer; - ESourceGroup *on_ldap_servers; - ESource *personal_source; - MigrationContext *context = migration_context_new (component); - gboolean need_dialog = FALSE; - - printf ("addressbook_migrate (%d.%d.%d)\n", major, minor, revision); - - /* we call this unconditionally now - create_groups either - creates the groups/sources or it finds the necessary - groups/sources. */ - create_groups (context, &on_this_computer, &on_ldap_servers, &personal_source); - - /* figure out if we need the dialog displayed */ - if (major == 1 - /* we only need the most recent upgrade point here. - further decomposition will happen below. */ - && (minor < 5 || (minor == 5 && revision <= 10))) - need_dialog = TRUE; - - if (need_dialog) - setup_progress_dialog (context); - - if (major == 1) { - - if (minor < 5 || (minor == 5 && revision <= 2)) { - /* initialize our dialog */ - dialog_set_label (context, - _("The location and hierarchy of the Evolution contact " - "folders has changed since Evolution 1.x.\n\nPlease be " - "patient while Evolution migrates your folders...")); - - if (on_this_computer) - migrate_local_folders (context, on_this_computer, personal_source); - if (on_ldap_servers) - migrate_ldap_servers (context, on_ldap_servers); - - migrate_completion_folders (context); - } - - if (minor < 5 || (minor == 5 && revision <= 7)) { - dialog_set_label (context, - _("The format of mailing list contacts has changed.\n\n" - "Please be patient while Evolution migrates your " - "folders...")); - - migrate_contact_lists_for_local_folders (context, on_this_computer); - } - - if (minor < 5 || (minor == 5 && revision <= 8)) { - dialog_set_label (context, - _("The way Evolution stores some phone numbers has changed.\n\n" - "Please be patient while Evolution migrates your " - "folders...")); - - migrate_company_phone_for_local_folders (context, on_this_computer); - } - - if (minor < 5 || (minor == 5 && revision <= 10)) { - gchar *old_path, *new_path; - - dialog_set_label (context, _("Evolution's Palm Sync changelog and map files have changed.\n\n" - "Please be patient while Evolution migrates your Pilot Sync data...")); - - old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Contacts", NULL); - new_path = g_build_filename (addressbook_component_peek_base_directory (component), - "local", "system", NULL); - migrate_pilot_data (old_path, new_path); - g_free (new_path); - g_free (old_path); - } - - /* we only need to do this next step if people ran - older versions of 1.5. We need to clear out the - absolute URI's that were assigned to ESources - during one phase of development, as they take - precedent over relative uris (but aren't updated - when editing an ESource). */ - if (minor == 5 && revision <= 11) { - GSList *g; - for (g = e_source_list_peek_groups (context->source_list); g; g = g->next) { - ESourceGroup *group = g->data; - GSList *s; - - for (s = e_source_group_peek_sources (group); s; s = s->next) { - ESource *source = s->data; - e_source_set_absolute_uri (source, NULL); - } - } - } - } - - if (need_dialog) - dialog_close (context); - - if (on_this_computer) - g_object_unref (on_this_computer); - if (on_ldap_servers) - g_object_unref (on_ldap_servers); - if (personal_source) - g_object_unref (personal_source); - - migration_context_free (context); - - return TRUE; -} diff --git a/addressbook/gui/component/addressbook-view.c b/addressbook/gui/component/addressbook-view.c deleted file mode 100644 index 6a66a94913..0000000000 --- a/addressbook/gui/component/addressbook-view.c +++ /dev/null @@ -1,1533 +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: - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <gtk/gtk.h> -#include <glib/gi18n.h> -#include <gdk/gdkkeysyms.h> -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-ui-util.h> -#include <bonobo/bonobo-exception.h> -#include <e-util/e-util.h> -#include <libedataserverui/e-source-selector.h> -#include <libedataserverui/e-passwords.h> - -#include "e-util/e-error.h" -#include "e-util/e-request.h" -#include "misc/e-task-bar.h" -#include "misc/e-info-label.h" - -#include "e-util/e-icon-factory.h" -#include "e-util/e-util-private.h" -#include "shell/e-user-creatable-items-handler.h" - -#include "evolution-shell-component-utils.h" -#include "e-activity-handler.h" -#include "e-contact-editor.h" -#include "addressbook-config.h" -#include "addressbook.h" -#include "addressbook-view.h" -#include "addressbook-component.h" -#include "addressbook/gui/widgets/e-addressbook-view.h" -#include "addressbook/gui/widgets/eab-gui-util.h" -#include "addressbook/gui/merging/eab-contact-merging.h" -#include "addressbook/printing/e-contact-print.h" -#include "addressbook/util/eab-book-util.h" -#include "addressbook/gui/widgets/eab-popup.h" -#include "addressbook/gui/widgets/eab-menu.h" - -#define PARENT_TYPE G_TYPE_OBJECT -static GObjectClass *parent_class = NULL; - -#define d(x) - -struct _AddressbookViewPrivate { - GtkWidget *notebook; - BonoboControl *folder_view_control; - - GtkWidget *statusbar_widget; - EActivityHandler *activity_handler; - - GtkWidget *info_widget; - GtkWidget *sidebar_widget; - GtkWidget *selector; - - GConfClient *gconf_client; - - GHashTable *uid_to_view; - GHashTable *uid_to_editor; - - EBook *book; - guint activity_id; - ESourceList *source_list; - gchar *passwd; - EUserCreatableItemsHandler *creatable_items_handler; - - EABMenu *menu; -}; - -enum DndTargetType { - DND_TARGET_TYPE_VCARD_LIST, - DND_TARGET_TYPE_SOURCE_VCARD_LIST -}; -#define VCARD_TYPE "text/x-vcard" -#define SOURCE_VCARD_TYPE "text/x-source-vcard" -static GtkTargetEntry drag_types[] = { - { (gchar *) SOURCE_VCARD_TYPE, 0, DND_TARGET_TYPE_SOURCE_VCARD_LIST }, - { (gchar *) VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD_LIST } -}; -static gint num_drag_types = sizeof(drag_types) / sizeof(drag_types[0]); - -static void set_status_message (EABView *eav, const gchar *message, AddressbookView *view); -static void search_result (EABView *eav, EBookViewStatus status, AddressbookView *view); - -static void activate_source (AddressbookView *view, ESource *source); - -static void addressbook_view_init (AddressbookView *view); -static void addressbook_view_class_init (AddressbookViewClass *klass); -static void addressbook_view_dispose (GObject *object); - -static ESource *find_first_source (ESourceList *source_list); -static ESource *get_primary_source (AddressbookView *view); - -typedef struct { - GtkWidget *editor; - gchar *uid; - AddressbookView *view; -} EditorUidClosure; - -static void -editor_weak_notify (gpointer data, GObject *o) -{ - EditorUidClosure *closure = data; - AddressbookViewPrivate *priv = closure->view->priv; - - g_hash_table_remove (priv->uid_to_editor, - closure->uid); -} - -static EABView * -get_current_view (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - - return EAB_VIEW (gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), - gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook)))); -} - -static void -save_all_contacts_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - - if (v) - eab_view_save_as (v, TRUE); -} - -static void -save_contact_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_save_as(v, FALSE); -} - -static void -view_contact_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_view(v); -} - -static void -delete_contact_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_delete_selection(v, TRUE); -} - -static void -print_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_print (v, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); -} - -static void -print_preview_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_print (v, GTK_PRINT_OPERATION_ACTION_PREVIEW); -} - -static void -stop_loading_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_stop(v); -} - -static void -cut_contacts_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_cut(v); -} - -static void -copy_contacts_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_copy(v); -} - -static void -paste_contacts_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_paste(v); -} - -static void -select_all_contacts_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_select_all (v); -} - -static void -send_contact_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_send (v); -} - -static void -send_contact_to_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_send_to (v); -} - -static void -copy_all_contacts_to_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - - if (v) - eab_view_copy_to_folder (v, TRUE); -} - -static void -copy_contact_to_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_copy_to_folder (v, FALSE); -} - -static void -move_all_contacts_to_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_move_to_folder (v, TRUE); -} - -static void -move_contact_to_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - EABView *v = get_current_view (view); - if (v) - eab_view_move_to_folder (v, FALSE); -} - -static void -forget_passwords_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - e_passwords_forget_passwords(); -} - -static void -new_addressbook_folder (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - addressbook_config_create_new_source (gtk_widget_get_toplevel(priv->notebook)); -} - -static void -new_folder_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - new_addressbook_folder (view); -} - -static void -delete_addressbook_folder (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *selected_source; - EBook *book; - GError *error = NULL; - GtkWindow *toplevel; - - selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (!selected_source) - return; - toplevel = (GtkWindow *) gtk_widget_get_toplevel (priv->notebook); - - if (e_error_run (toplevel, "addressbook:ask-delete-addressbook", - e_source_peek_name(selected_source), NULL) != GTK_RESPONSE_YES) - return; - - /* Remove local data */ - book = e_book_new (selected_source, &error); - if (book) { - if (e_book_remove (book, NULL)) { - if (e_source_selector_source_is_selected (E_SOURCE_SELECTOR (priv->selector), - selected_source)) - e_source_selector_unselect_source (E_SOURCE_SELECTOR (priv->selector), - selected_source); - - e_source_group_remove_source (e_source_peek_group (selected_source), selected_source); - - e_source_list_sync (priv->source_list, NULL); - } - else { - e_error_run (toplevel, "addressbook:remove-addressbook", NULL); - } - g_object_unref (book); - } - else { - g_warning ("error removing addressbook : %s", error->message); - g_error_free (error); - } -} - -static void -delete_folder_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - if (view) - delete_addressbook_folder (view); - -} - -static void -edit_addressbook_folder (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *selected_source; - const gchar *uid; - EditorUidClosure *closure; - - selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (!selected_source) - return; - - uid = e_source_peek_uid (selected_source); - - closure = g_hash_table_lookup (priv->uid_to_editor, uid); - if (!closure) { - gchar *uid_copy = g_strdup (uid); - - closure = g_new (EditorUidClosure, 1); - closure->editor = addressbook_config_edit_source (gtk_widget_get_toplevel(priv->notebook), selected_source); - closure->uid = uid_copy; - closure->view = view; - - g_hash_table_insert (priv->uid_to_editor, - uid_copy, - closure); - - g_object_weak_ref (G_OBJECT (closure->editor), - editor_weak_notify, closure); - } - - gtk_window_present (GTK_WINDOW (closure->editor)); - -} - -static void -edit_folder_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - if (view) - edit_addressbook_folder (view); - -} - -static void -rename_addressbook_folder (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *source; - const gchar *old_name; - gchar *prompt, *new_name; - gboolean done = FALSE; - - source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - old_name = e_source_peek_name(source); - prompt = g_strdup_printf (_("Rename the \"%s\" folder to:"), old_name); - - while (!done) { - new_name = e_request_string (NULL, _("Rename Folder"), prompt, old_name); - if (new_name == NULL || !strcmp (old_name, new_name)) { - done = TRUE; - } else if (strchr(new_name, '/') != NULL) { - e_error_run (NULL, - "addressbook:no-rename-folder", old_name, new_name, _("Folder names cannot contain '/'"), NULL); - done = TRUE; - } else if (e_source_group_peek_source_by_name(e_source_peek_group(source), new_name)) { - e_error_run (NULL, "addressbook:no-rename-folder-exists", old_name, new_name, NULL); - } else { - e_source_set_name (source, new_name); - done = TRUE; - } - } - g_free (new_name); - -} - -static void -rename_folder_cb (BonoboUIComponent *uih, gpointer user_data, const gchar *path) -{ - AddressbookView *view = (AddressbookView *) user_data; - if (view) - rename_addressbook_folder (view); -} - -static gboolean -folder_can_delete (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *source; - const gchar *source_uri; - - source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (source) { - source_uri = e_source_peek_relative_uri (source); - if (source_uri && !strcmp("system", source_uri)) - return 0; - else - return 1; - } - else - return 0; -} - -static void -set_status_message (EABView *eav, const gchar *message, AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - EActivityHandler *activity_handler = priv->activity_handler; - - if (!message || !*message) { - if (priv->activity_id != 0) { - e_activity_handler_operation_finished (activity_handler, priv->activity_id); - priv->activity_id = 0; - } - } else if (priv->activity_id == 0) { - gchar *clientid = g_strdup_printf ("%p", (gpointer) view); - - priv->activity_id = e_activity_handler_operation_started ( - activity_handler, clientid, message, TRUE); - - g_free (clientid); - } else { - e_activity_handler_operation_progressing (activity_handler, priv->activity_id, message, -1.0); - } - -} - -static void -set_folder_bar_message (EABView *eav, const gchar *message, AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - EABView *current_view = get_current_view (view); - - if (eav == current_view) { - ESource *source = eav->source; - - if (source) { - const gchar *name = e_source_peek_name (source); - - e_info_label_set_info((EInfoLabel*)priv->info_widget, name, message); - } - } -} - -static void -search_result (EABView *eav, EBookViewStatus status, AddressbookView *view) -{ - eab_search_result_dialog (NULL /* XXX */, status); -} - -static void -update_command_state (EABView *eav, AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - BonoboUIComponent *uic; - EABMenuTargetSelect *target; - - if (eav != get_current_view (view)) - return; - - g_object_ref (view); - - target = eab_view_get_menu_target(eav, priv->menu); - e_menu_update_target((EMenu *)priv->menu, target); - - uic = bonobo_control_get_ui_component (priv->folder_view_control); - - /* TODO: this stuff can mostly be made to use the target bits instead */ - - if (bonobo_ui_component_get_container (uic) != CORBA_OBJECT_NIL) { -#define SET_SENSITIVE(verb,f) \ - bonobo_ui_component_set_prop (uic, (verb), "sensitive", (f)(eav) ? "1" : "0", NULL) - - SET_SENSITIVE ("/commands/ContactsSaveAsVCard", eab_view_can_save_as); - SET_SENSITIVE ("/commands/ContactsView", eab_view_can_view); - - /* Print Contact */ - SET_SENSITIVE ("/commands/ContactsPrint", eab_view_can_print); - SET_SENSITIVE ("/commands/ContactsPrintPreview", eab_view_can_print); - - /* Delete Contact */ - SET_SENSITIVE ("/commands/ContactDelete", eab_view_can_delete); - SET_SENSITIVE ("/commands/ContactsCut", eab_view_can_cut); - - SET_SENSITIVE ("/commands/ContactsCopy", eab_view_can_copy); - SET_SENSITIVE ("/commands/ContactsPaste", eab_view_can_paste); - SET_SENSITIVE ("/commands/ContactsSelectAll", eab_view_can_select_all); - SET_SENSITIVE ("/commands/ContactsSendContactToOther", eab_view_can_send); - SET_SENSITIVE ("/commands/ContactsSendMessageToContact", eab_view_can_send_to); - SET_SENSITIVE ("/commands/ContactsMoveToFolder", eab_view_can_move_to_folder); - SET_SENSITIVE ("/commands/ContactsCopyToFolder", eab_view_can_copy_to_folder); - - bonobo_ui_component_set_prop (uic, ("/commands/FolderDelete"), "sensitive", folder_can_delete(view) ? "1" : "0", NULL); - - /* Stop */ - SET_SENSITIVE ("/commands/ContactStop", eab_view_can_stop); -#undef SET_SENSITIVE - } - - g_object_unref (view); -} - -static BonoboUIVerb verbs [] = { - BONOBO_UI_UNSAFE_VERB ("ContactsPrint", print_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsPrintPreview", print_preview_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsSaveAsVCard", save_contact_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsView", view_contact_cb), - - BONOBO_UI_UNSAFE_VERB ("ContactDelete", delete_contact_cb), - BONOBO_UI_UNSAFE_VERB ("ContactStop", stop_loading_cb), - - BONOBO_UI_UNSAFE_VERB ("ContactsCut", cut_contacts_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsCopy", copy_contacts_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsPaste", paste_contacts_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsSelectAll", select_all_contacts_cb), - - BONOBO_UI_UNSAFE_VERB ("ContactsSendContactToOther", send_contact_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsSendMessageToContact", send_contact_to_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsMoveToFolder", move_contact_to_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsCopyToFolder", copy_contact_to_cb), - BONOBO_UI_UNSAFE_VERB ("ContactsForgetPasswords", forget_passwords_cb), - /* ContactsViewPreview is a toggle */ - - BONOBO_UI_UNSAFE_VERB ("FolderCreate", new_folder_cb), - BONOBO_UI_UNSAFE_VERB ("FolderCopy", copy_all_contacts_to_cb), - BONOBO_UI_UNSAFE_VERB ("FolderMove", move_all_contacts_to_cb), - BONOBO_UI_UNSAFE_VERB ("FolderSave", save_all_contacts_cb), - BONOBO_UI_UNSAFE_VERB ("FolderDelete", delete_folder_cb), - BONOBO_UI_UNSAFE_VERB ("FolderRename", rename_folder_cb), - BONOBO_UI_UNSAFE_VERB ("ChangeFolderProperties", edit_folder_cb), - - BONOBO_UI_VERB_END -}; - -static EPixmap pixmaps [] = { - E_PIXMAP ("/commands/ChangeFolderProperties", "document-properties", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactDelete", "edit-delete", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsCopy", "edit-copy", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsCut", "edit-cut", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsPaste", "edit-paste", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsPrint", "document-print", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsPrintPreview", "document-print-preview", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsSaveAsVCard", "document-save-as", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsSendContactToOther", "mail-forward", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/ContactsSendMessageToContact", "mail-message-new", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/FolderCopy", "edit-copy", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/FolderDelete", "edit-delete", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/FolderMove", "folder-move", GTK_ICON_SIZE_MENU), - E_PIXMAP ("/commands/FolderSave", "document-save-as", GTK_ICON_SIZE_MENU), - - E_PIXMAP ("/Toolbar/ContactsPrint", "document-print", GTK_ICON_SIZE_LARGE_TOOLBAR), - E_PIXMAP ("/Toolbar/ContactDelete", "edit-delete", GTK_ICON_SIZE_LARGE_TOOLBAR), - - E_PIXMAP_END -}; - -static void -control_activate (BonoboControl *control, - BonoboUIComponent *uic, - AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - Bonobo_UIContainer remote_ui_container; - EABView *v = get_current_view (view); - gchar *xmlfile; - - remote_ui_container = bonobo_control_get_remote_ui_container (control, NULL); - bonobo_ui_component_set_container (uic, remote_ui_container, NULL); - bonobo_object_release_unref (remote_ui_container, NULL); - - bonobo_ui_component_add_verb_list_with_data ( - uic, verbs, view); - - bonobo_ui_component_freeze (uic, NULL); - - xmlfile = g_build_filename (EVOLUTION_UIDIR, - "evolution-addressbook.xml", - NULL); - bonobo_ui_util_set_ui (uic, PREFIX, - xmlfile, - "evolution-addressbook", NULL); - g_free (xmlfile); - - if (v) - eab_view_setup_menus (v, uic); - - e_pixmaps_update (uic, pixmaps); - - e_user_creatable_items_handler_activate (priv->creatable_items_handler, uic); - - bonobo_ui_component_thaw (uic, NULL); - - if (v) - update_command_state (v, view); -} - -static void -control_activate_cb (BonoboControl *control, - gboolean activate, - AddressbookView *view) -{ - BonoboUIComponent *uic; - EABView *v = get_current_view (view); - - uic = bonobo_control_get_ui_component (control); - g_return_if_fail (uic != NULL); - - if (activate) { - control_activate (control, uic, view); - e_menu_activate((EMenu *)view->priv->menu, uic, activate); - if (activate && v && v->model) - eab_model_force_folder_bar_message (v->model); - } else { - e_menu_activate((EMenu *)view->priv->menu, uic, activate); - bonobo_ui_component_unset_container (uic, NULL); - eab_view_discard_menus (v); - } -} - -static void -gather_uids_foreach (gchar *key, - gpointer value, - GList **list) -{ - (*list) = g_list_prepend (*list, key); -} - -static void -source_list_changed_cb (ESourceList *source_list, AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - GList *uids, *l; - EABView *v; - - uids = NULL; - g_hash_table_foreach (priv->uid_to_view, (GHFunc)gather_uids_foreach, &uids); - for (l = uids; l; l = l->next) { - gchar *uid = l->data; - if (e_source_list_peek_source_by_uid (source_list, uid)) { - /* the source still exists, do nothing */ - } - else { - /* the source no longer exists, remove its - view remove it from our hash table. */ - v = g_hash_table_lookup (priv->uid_to_view, - uid); - gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), - gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), - GTK_WIDGET (v))); - g_hash_table_remove (priv->uid_to_view, uid); - } - } - g_list_free (uids); - - uids = NULL; - g_hash_table_foreach (priv->uid_to_editor, (GHFunc)gather_uids_foreach, &uids); - for (l = uids; l; l = l->next) { - gchar *uid = l->data; - if (e_source_list_peek_source_by_uid (source_list, uid)) { - /* the source still exists, do nothing */ - } - else { - /* the source no longer exists, remove its - editor remove it from our hash table. */ - EditorUidClosure *closure = g_hash_table_lookup (priv->uid_to_editor, - uid); - g_object_weak_unref (G_OBJECT (closure->editor), - editor_weak_notify, closure); - gtk_widget_destroy (closure->editor); - g_hash_table_remove (priv->uid_to_editor, uid); - } - } - g_list_free (uids); - - /* make sure we've got the current view selected and updated - properly */ - v = get_current_view (view); - if (v) { - eab_view_setup_menus (v, bonobo_control_get_ui_component (priv->folder_view_control)); - update_command_state (v, view); - } -} - -static void -load_uri_for_selection (ESourceSelector *selector, - AddressbookView *view, - gboolean force) -{ - ESource *selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (selector)); - ESource *primary = get_primary_source (view); - - if (selected_source != NULL && - ((primary && (!g_str_equal (e_source_peek_uid (primary),e_source_peek_uid (selected_source) )))||force)) - activate_source (view, selected_source); -} - -static ESource * -find_first_source (ESourceList *source_list) -{ - GSList *groups, *sources, *l, *m; - - groups = e_source_list_peek_groups (source_list); - for (l = groups; l; l = l->next) { - ESourceGroup *group = l->data; - - sources = e_source_group_peek_sources (group); - for (m = sources; m; m = m->next) { - ESource *source = m->data; - - return source; - } - } - - return NULL; -} - -static void -save_primary_selection (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *source; - - source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (!source) - return; - - /* Save the selection for next time we start up */ - gconf_client_set_string (priv->gconf_client, - "/apps/evolution/addressbook/display/primary_addressbook", - e_source_peek_uid (source), NULL); -} - -static ESource * -get_primary_source (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *source; - gchar *uid; - - uid = gconf_client_get_string (priv->gconf_client, - "/apps/evolution/addressbook/display/primary_addressbook", - NULL); - if (uid) { - source = e_source_list_peek_source_by_uid (priv->source_list, uid); - g_free (uid); - } else { - /* Try to create a default if there isn't one */ - source = find_first_source (priv->source_list); - } - - return source; -} - -static void -load_primary_selection (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *source; - - source = get_primary_source (view); - if (source) - e_source_selector_set_primary_selection (E_SOURCE_SELECTOR (priv->selector), source); -} - -/* Folder popup menu callbacks */ -typedef struct { - AddressbookView *view; - ESource *selected_source; - GtkWidget *toplevel; -} BookRemovedClosure; - -static void -book_removed (EBook *book, EBookStatus status, gpointer data) -{ - BookRemovedClosure *closure = data; - AddressbookView *view = closure->view; - AddressbookViewPrivate *priv = view->priv; - ESource *source = closure->selected_source; - GtkWidget *toplevel = closure->toplevel; - - g_free (closure); - - g_object_unref (book); - - if (E_BOOK_ERROR_OK == status) { - /* Remove source */ - if (e_source_selector_source_is_selected (E_SOURCE_SELECTOR (priv->selector), - source)) - e_source_selector_unselect_source (E_SOURCE_SELECTOR (priv->selector), - source); - - e_source_group_remove_source (e_source_peek_group (source), source); - - e_source_list_sync (priv->source_list, NULL); - } - else { - e_error_run (GTK_WINDOW (toplevel), - "addressbook:remove-addressbook", - NULL); - } -} - -static void -delete_addressbook_cb(EPopup *ep, EPopupItem *pitem, gpointer data) -{ - AddressbookView *view = data; - AddressbookViewPrivate *priv = view->priv; - ESource *selected_source; - EBook *book; - GError *error = NULL; - GtkWindow *toplevel; - - selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (!selected_source) - return; - - toplevel = (GtkWindow *)gtk_widget_get_toplevel(ep->target->widget); - - if (e_error_run (toplevel, "addressbook:ask-delete-addressbook", e_source_peek_name(selected_source), NULL) != GTK_RESPONSE_YES) - return; - - /* Remove local data */ - book = e_book_new (selected_source, &error); - if (book) { - BookRemovedClosure *closure = g_new (BookRemovedClosure, 1); - - closure->toplevel = (GtkWidget *)toplevel; - closure->view = view; - closure->selected_source = selected_source; - - if (e_book_async_remove (book, book_removed, closure)) { - e_error_run (toplevel, "addressbook:remove-addressbook", NULL); - g_free (closure); - g_object_unref (book); - } - } -} - -static void -new_addressbook_cb(EPopup *ep, EPopupItem *pitem, gpointer data) -{ - addressbook_config_create_new_source (gtk_widget_get_toplevel(ep->target->widget)); -} - -static void -rename_addressbook_cb (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - AddressbookView *view = data; - ESourceSelector *selector; - - selector = E_SOURCE_SELECTOR (view->priv->selector); - e_source_selector_edit_primary_selection (selector); -} - -static void -save_addressbook_cb(EPopup *ep, EPopupItem *pitem, gpointer data) -{ - AddressbookView *view = data; - EABView *v = get_current_view (view); - if (v) - eab_view_save_as (v, TRUE); -} - -static void -edit_addressbook_cb(EPopup *ep, EPopupItem *pitem, gpointer data) -{ - AddressbookView *view = data; - if (view) - edit_addressbook_folder (view); -} - -/* Callbacks. */ - -static void -primary_source_selection_changed_callback (ESourceSelector *selector, - AddressbookView *view) -{ - load_uri_for_selection (selector, view, FALSE); - save_primary_selection (view); -} - -static EPopupItem abv_source_popups[] = { - { E_POPUP_ITEM, (gchar *) "10.new", (gchar *) N_("_New Address Book"), new_addressbook_cb, NULL, (gchar *) "address-book-new", 0, 0 }, - { E_POPUP_ITEM, (gchar *) "20.saveasvcard", (gchar *) N_("Save As vCard..."), save_addressbook_cb, NULL, (gchar *) "document-save-as", 0, EAB_POPUP_SOURCE_PRIMARY }, - { E_POPUP_ITEM, (gchar *) "25.rename", (gchar *) N_("_Rename..."), rename_addressbook_cb, NULL, NULL, 0, EAB_POPUP_SOURCE_PRIMARY }, - - { E_POPUP_BAR, (gchar *) "30.bar" }, - { E_POPUP_ITEM, (gchar *) "30.delete", (gchar *) N_("_Delete"), delete_addressbook_cb, NULL, (gchar *) "edit-delete", 0, EAB_POPUP_SOURCE_USER|EAB_POPUP_SOURCE_PRIMARY }, - - { E_POPUP_BAR, (gchar *) "99.bar" }, - { E_POPUP_ITEM, (gchar *) "99.properties", (gchar *) N_("_Properties"), edit_addressbook_cb, NULL, (gchar *) "document-properties", 0, EAB_POPUP_SOURCE_PRIMARY }, -}; - -static void -abv_source_popup_free(EPopup *ep, GSList *list, gpointer data) -{ - g_slist_free(list); -} - -static gboolean -popup_event_callback(ESourceSelector *selector, ESource *source, GdkEventButton *event, AddressbookView *view) -{ - EABPopup *ep; - EABPopupTargetSource *t; - GSList *menus = NULL; - gint i; - GtkMenu *menu; - - /** @HookPoint-EABPopup:Addressbook Source Selector Context Menu - * @Id: org.gnome.evolution.addressbook.source.popup - * @Class: org.gnome.evolution.addresbook.popup:1.0 - * @Target: EABPopupTargetSource - * - * The context menu on the source selector in the contacts window. - */ - - ep = eab_popup_new("org.gnome.evolution.addressbook.source.popup"); - t = eab_popup_target_new_source(ep, selector); - t->target.widget = (GtkWidget *)view->priv->notebook; - - for (i=0;i<sizeof(abv_source_popups)/sizeof(abv_source_popups[0]);i++) - menus = g_slist_prepend(menus, &abv_source_popups[i]); - - e_popup_add_items((EPopup *)ep, menus, NULL, abv_source_popup_free, view); - - menu = e_popup_create_menu_once((EPopup *)ep, (EPopupTarget *)t, 0); - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event?event->button:0, event?event->time:gtk_get_current_event_time()); - - return TRUE; -} - -typedef struct -{ - guint remove_from_source : 1; - guint copy_done : 1; - gint pending_removals; - - EContact *current_contact; - GList *remaining_contacts; - - EBook *source_book; - EBook *target_book; -} -MergeContext; - -static void -destroy_merge_context (MergeContext *merge_context) -{ - if (merge_context->source_book) - g_object_unref (merge_context->source_book); - if (merge_context->target_book) - g_object_unref (merge_context->target_book); - - g_free (merge_context); -} - -static void -removed_contact_cb (EBook *book, EBookStatus status, gpointer closure) -{ - MergeContext *merge_context = closure; - - merge_context->pending_removals--; - - if (merge_context->copy_done && merge_context->pending_removals == 0) { - /* Finished */ - - destroy_merge_context (merge_context); - } -} - -static void -merged_contact_cb (EBook *book, EBookStatus status, const gchar *id, gpointer closure) -{ - MergeContext *merge_context = closure; - - if (merge_context->remove_from_source && status == E_BOOK_ERROR_OK) { - /* Remove previous contact from source */ - - e_book_async_remove_contact (merge_context->source_book, merge_context->current_contact, - removed_contact_cb, merge_context); - merge_context->pending_removals++; - } - - g_object_unref (merge_context->current_contact); - - if (merge_context->remaining_contacts) { - /* Copy next contact */ - - merge_context->current_contact = merge_context->remaining_contacts->data; - merge_context->remaining_contacts = g_list_delete_link (merge_context->remaining_contacts, - merge_context->remaining_contacts); - eab_merging_book_add_contact (merge_context->target_book, merge_context->current_contact, - merged_contact_cb, merge_context); - } else if (merge_context->pending_removals == 0) { - /* Finished */ - - destroy_merge_context (merge_context); - } else { - /* Finished, but have pending removals */ - - merge_context->copy_done = TRUE; - } -} - -static gboolean -selector_tree_data_dropped (ESourceSelector *selector, - GtkSelectionData *data, - ESource *destination, - GdkDragAction action, - guint info, - AddressbookView *view) -{ - EBook *source_book, *target_book; - MergeContext *merge_context = NULL; - GList *contactlist; - EABView *v; - - target_book = e_book_new (destination, NULL); - if (!target_book) { - g_message (G_STRLOC ":Couldn't create EBook."); - return FALSE; - } - e_book_open (target_book, FALSE, NULL); - - eab_book_and_contact_list_from_string ((gchar *)data->data, &source_book, &contactlist); - - v = get_current_view (view); - g_object_get (v->model, "book",&source_book, NULL); - - /* Set up merge context */ - - merge_context = g_new0 (MergeContext, 1); - - merge_context->source_book = source_book; - merge_context->target_book = target_book; - - merge_context->current_contact = contactlist->data; - merge_context->remaining_contacts = g_list_delete_link (contactlist, contactlist); - - merge_context->remove_from_source = action == GDK_ACTION_MOVE ? TRUE : FALSE; - - /* Start merge */ - - eab_merging_book_add_contact (target_book, merge_context->current_contact, - merged_contact_cb, merge_context); - - return TRUE; -} - -static void -destroy_callback(gpointer data, GObject *where_object_was) -{ - AddressbookView *view = data; - g_object_unref (view); -} - -GType -addressbook_view_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (AddressbookViewClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) addressbook_view_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABView), - 0, /* n_preallocs */ - (GInstanceInitFunc) addressbook_view_init, - }; - - type = g_type_register_static (PARENT_TYPE, "AddressbookView", &info, 0); - } - - return type; -} - -static void -addressbook_view_class_init (AddressbookViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = addressbook_view_dispose; - - parent_class = g_type_class_peek_parent (klass); -} - -static gboolean -source_selector_key_press_event_callback (GtkWidget *widget, GdkEventKey *event, AddressbookView *view) -{ - if (event->keyval == GDK_Delete) { - /* suppress delete key press in a source selector */ - return TRUE; - } - return FALSE; -} - -static void -addressbook_view_init (AddressbookView *view) -{ - AddressbookViewPrivate *priv; - GtkWidget *selector_scrolled_window; - AtkObject *a11y; - - view->priv = - priv = g_new0 (AddressbookViewPrivate, 1); - - priv->gconf_client = addressbook_component_peek_gconf_client (addressbook_component_peek ()); - - priv->uid_to_view = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_object_unref); - priv->uid_to_editor = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free); - - priv->notebook = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->notebook), FALSE); - - g_object_weak_ref (G_OBJECT (priv->notebook), destroy_callback, view); - - /* Create the control. */ - priv->folder_view_control = bonobo_control_new (priv->notebook); - - gtk_widget_show (priv->notebook); - - e_book_get_addressbooks (&priv->source_list, NULL); - g_signal_connect (priv->source_list, - "changed", - G_CALLBACK (source_list_changed_cb), view); - - priv->creatable_items_handler = e_user_creatable_items_handler_new ("contacts", NULL, NULL); - priv->menu = eab_menu_new("org.gnome.evolution.addressbook.view"); - - g_signal_connect (priv->folder_view_control, "activate", - G_CALLBACK (control_activate_cb), view); - - priv->activity_handler = e_activity_handler_new (); - - priv->statusbar_widget = e_task_bar_new (); - gtk_widget_show (priv->statusbar_widget); - - e_activity_handler_attach_task_bar (priv->activity_handler, - E_TASK_BAR (priv->statusbar_widget)); - - priv->info_widget = e_info_label_new("x-office-address-book"); - e_info_label_set_info((EInfoLabel*)priv->info_widget, _("Contacts"), ""); - gtk_widget_show (priv->info_widget); - - priv->selector = e_source_selector_new (priv->source_list); - - g_signal_connect ( - priv->selector, "data-dropped", - G_CALLBACK (selector_tree_data_dropped), view); - gtk_drag_dest_set (priv->selector, GTK_DEST_DEFAULT_ALL, drag_types, num_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE); - a11y = gtk_widget_get_accessible (GTK_WIDGET (priv->selector)); - atk_object_set_name (a11y, _("Contact Source Selector")); - - e_source_selector_show_selection (E_SOURCE_SELECTOR (priv->selector), FALSE); - gtk_widget_show (priv->selector); - - selector_scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (selector_scrolled_window), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (selector_scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_container_add (GTK_CONTAINER (selector_scrolled_window), priv->selector); - gtk_widget_show (selector_scrolled_window); - - priv->sidebar_widget = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX (priv->sidebar_widget), priv->info_widget, FALSE, TRUE, 0); - gtk_box_pack_start(GTK_BOX (priv->sidebar_widget), selector_scrolled_window, TRUE, TRUE, 0); - gtk_widget_show (priv->sidebar_widget); - - g_signal_connect_object (priv->selector, "primary_selection_changed", - G_CALLBACK (primary_source_selection_changed_callback), - G_OBJECT (view), 0); - g_signal_connect_after (priv->selector, "key_press_event", - G_CALLBACK (source_selector_key_press_event_callback), - G_OBJECT (view)); - g_signal_connect_object (priv->selector, "popup_event", - G_CALLBACK (popup_event_callback), - G_OBJECT (view), 0); - - load_primary_selection (view); - load_uri_for_selection (E_SOURCE_SELECTOR (priv->selector), view, TRUE); -} - -static void -destroy_editor (gchar *key, - gpointer value, - gpointer nada) -{ - EditorUidClosure *closure = value; - - g_object_weak_unref (G_OBJECT (closure->editor), - editor_weak_notify, closure); - - gtk_widget_destroy (GTK_WIDGET (closure->editor)); -} - -static void -addressbook_view_dispose (GObject *object) -{ - AddressbookView *view = ADDRESSBOOK_VIEW (object); - AddressbookViewPrivate *priv = view->priv; - - if (view->priv) { - if (priv->book) - g_object_unref (priv->book); - - g_free(priv->passwd); - - if (priv->source_list) - g_object_unref (priv->source_list); - - if (priv->uid_to_view) - g_hash_table_destroy (priv->uid_to_view); - - if (priv->uid_to_editor) { - g_hash_table_foreach (priv->uid_to_editor, (GHFunc)destroy_editor, NULL); - g_hash_table_destroy (priv->uid_to_editor); - } - - if (priv->creatable_items_handler) - g_object_unref (priv->creatable_items_handler); - - if (priv->menu) - g_object_unref (priv->menu); - - g_free (view->priv); - view->priv = NULL; - } - - if (G_OBJECT_CLASS (parent_class)->dispose) - (* G_OBJECT_CLASS (parent_class)->dispose) (object); -} - -typedef struct { - EABView *view; - ESource *source; -} BookOpenData; - -static void -book_open_cb (EBook *book, EBookStatus status, gpointer closure) -{ - BookOpenData *data = closure; - EABView *view = data->view; - ESource *source = data->source; - - g_free (data); - - /* we always set the "source" property on the EABView, since - we use it to reload a previously failed book. */ - g_object_set(view, - "source", source, - NULL); - - if (status == E_BOOK_ERROR_OK) { - g_object_set(view, - "book", book, - NULL); - - if (view->model) - eab_model_force_folder_bar_message (view->model); - } - else if (status != E_BOOK_ERROR_CANCELLED) { - eab_load_error_dialog (NULL /* XXX */, source, status); - } - - g_object_unref (source); -} - -static void -activate_source (AddressbookView *view, - ESource *source) -{ - AddressbookViewPrivate *priv = view->priv; - const gchar *uid; - GtkWidget *uid_view; - EBook *book; - BookOpenData *data; - - uid = e_source_peek_uid (source); - uid_view = g_hash_table_lookup (priv->uid_to_view, uid); - - if (uid_view) { - /* there is a view for this uid. make - sure that the view actually - contains an EBook (if it doesn't - contain an EBook a previous load - failed. try to load it again */ - g_object_get (uid_view, - "book", &book, - NULL); - - if (book) { - g_object_unref (book); - } - else { - g_object_get (uid_view, - "source", &source, - NULL); - - /* source can be NULL here, if - a previous load hasn't - actually made it to - book_open_cb yet. */ - if (source) { - book = e_book_new (source, NULL); - - if (!book) { - g_object_unref (source); - } - else { - data = g_new (BookOpenData, 1); - data->view = g_object_ref (uid_view); - data->source = source; /* transfer the ref we get back from g_object_get */ - - addressbook_load (book, book_open_cb, data); - } - } - } - } - else { - /* we don't have a view for this uid already - set up. */ - GtkWidget *label = gtk_label_new (uid); - GError *error = NULL; - - uid_view = eab_view_new (); - - gtk_widget_show (uid_view); - gtk_widget_show (label); - - g_object_set (uid_view, "type", EAB_VIEW_TABLE, NULL); - - gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), - uid_view, - label); - - g_hash_table_insert (priv->uid_to_view, g_strdup (uid), uid_view); - - g_signal_connect (uid_view, "status_message", - G_CALLBACK(set_status_message), view); - - g_signal_connect (uid_view, "search_result", - G_CALLBACK(search_result), view); - - g_signal_connect (uid_view, "folder_bar_message", - G_CALLBACK(set_folder_bar_message), view); - - g_signal_connect (uid_view, "command_state_change", - G_CALLBACK(update_command_state), view); - - book = e_book_new (source, &error); - - if (book) { - data = g_new (BookOpenData, 1); - data->view = g_object_ref (uid_view); - data->source = g_object_ref (source); - - addressbook_load (book, book_open_cb, data); - } - else { - g_warning ("error loading addressbook : %s", error->message); - g_error_free (error); - } - } - - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), - gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), - uid_view)); - - if (EAB_VIEW (uid_view)->model) - eab_model_force_folder_bar_message (EAB_VIEW (uid_view)->model); - - /* change menus/toolbars to reflect the new view, assuming we are already displayed */ - if (bonobo_ui_component_get_container (bonobo_control_get_ui_component (priv->folder_view_control)) != CORBA_OBJECT_NIL) { - eab_view_setup_menus (EAB_VIEW (uid_view), bonobo_control_get_ui_component (priv->folder_view_control)); - update_command_state (EAB_VIEW (uid_view), view); - } -} - -AddressbookView * -addressbook_view_new (void) -{ - return g_object_new (ADDRESSBOOK_TYPE_VIEW, NULL); -} - -EActivityHandler* -addressbook_view_peek_activity_handler (AddressbookView *view) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_VIEW (view), NULL); - - return view->priv->activity_handler; -} - -GtkWidget* -addressbook_view_peek_info_label (AddressbookView *view) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_VIEW (view), NULL); - - return view->priv->info_widget; -} - -GtkWidget* -addressbook_view_peek_sidebar (AddressbookView *view) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_VIEW (view), NULL); - - return view->priv->sidebar_widget; -} - -GtkWidget* -addressbook_view_peek_statusbar (AddressbookView *view) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_VIEW (view), NULL); - - return view->priv->statusbar_widget; -} - -BonoboControl* -addressbook_view_peek_folder_view (AddressbookView *view) -{ - g_return_val_if_fail (ADDRESSBOOK_IS_VIEW (view), NULL); - - return view->priv->folder_view_control; -} - -void -addressbook_view_edit_contact (AddressbookView* view, - const gchar * source_uid, - const gchar * contact_uid) -{ - AddressbookViewPrivate *priv = view->priv; - - ESource* source = NULL; - EContact* contact = NULL; - EBook* book = NULL; - - if (!source_uid || !contact_uid) - return; - - source = e_source_list_peek_source_by_uid (priv->source_list, source_uid); - if (!source) - return; - - /* FIXME: Can I unref this book? */ - book = e_book_new (source, NULL); - if (!book) - return; - - if (!e_book_open (book, TRUE, NULL)) { - g_object_unref (book); - return; - } - - e_book_get_contact (book, contact_uid, &contact, NULL); - - if (!contact) { - g_object_unref (book); - return; - } - eab_show_contact_editor (book, contact, FALSE, FALSE); - g_object_unref (contact); - g_object_unref (book); -} diff --git a/addressbook/gui/component/addressbook-view.h b/addressbook/gui/component/addressbook-view.h deleted file mode 100644 index 38554b7acf..0000000000 --- a/addressbook/gui/component/addressbook-view.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: - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _ADDRESSBOOK_VIEW_H_ -#define _ADDRESSBOOK_VIEW_H_ - -#include <bonobo/bonobo-control.h> - -#define ADDRESSBOOK_TYPE_VIEW (addressbook_view_get_type ()) -#define ADDRESSBOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ADDRESSBOOK_TYPE_VIEW, AddressbookView)) -#define ADDRESSBOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ADDRESSBOOK_TYPE_VIEW, AddressbookViewClass)) -#define ADDRESSBOOK_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ADDRESSBOOK_TYPE_VIEW)) -#define ADDRESSBOOK_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), ADDRESSBOOK_TYPE_VIEW)) - -typedef struct _AddressbookView AddressbookView; -typedef struct _AddressbookViewPrivate AddressbookViewPrivate; -typedef struct _AddressbookViewClass AddressbookViewClass; - -struct _AddressbookView { - GObject parent; - - AddressbookViewPrivate *priv; -}; - -struct _AddressbookViewClass { - GObjectClass parent_class; -}; - -GType addressbook_view_get_type (void); - -AddressbookView *addressbook_view_new (void); - -EActivityHandler *addressbook_view_peek_activity_handler (AddressbookView *view); -GtkWidget *addressbook_view_peek_info_label (AddressbookView *view); -GtkWidget *addressbook_view_peek_sidebar (AddressbookView *view); -GtkWidget *addressbook_view_peek_statusbar (AddressbookView *view); -BonoboControl *addressbook_view_peek_folder_view (AddressbookView *view); - -void addressbook_view_edit_contact (AddressbookView* view, - const gchar * source_id, - const gchar * contact_id); - -#endif /* _ADDRESSBOOK_VIEW_H_ */ diff --git a/addressbook/gui/component/apps_evolution_addressbook.schemas.in b/addressbook/gui/component/apps_evolution_addressbook.schemas.in deleted file mode 100644 index 4a336409df..0000000000 --- a/addressbook/gui/component/apps_evolution_addressbook.schemas.in +++ /dev/null @@ -1,82 +0,0 @@ -<gconfschemafile> - <schemalist> - - <!-- Completion uris --> - - <schema> - <key>/schemas/apps/evolution/addressbook/completion/uris</key> - <applyto>/apps/evolution/addressbook/completion/uris</applyto> - <owner>evolution-addressbook</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>EFolderList XML for the list of completion URIs</short> - <long>EFolderList XML for the list of completion URIs.</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/evolution/addressbook/completion/minimum_query_length</key> - <applyto>/apps/evolution/addressbook/completion/minimum_query_length</applyto> - <owner>evolution-addressbook</owner> - <type>int</type> - <default>3</default> - <locale name="C"> - <short>Autocomplete length</short> - <long>The number of characters that must be typed before Evolution will attempt to autocomplete.</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/evolution/addressbook/completion/show_address</key> - <applyto>/apps/evolution/addressbook/completion/show_address</applyto> - <owner>evolution-addressbook</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Show autocompleted name with an address</short> - <long>Whether force showing the mail address with the name of the autocompleted contact in the entry.</long> - </locale> - </schema> - - <!-- Select names last used uri --> - - <schema> - <key>/schemas/apps/evolution/addressbook/select_names/last_used_uri</key> - <applyto>/apps/evolution/addressbook/select_names/last_used_uri</applyto> - <owner>evolution-addressbook</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>URI for the folder last used in the select names dialog</short> - <long>URI for the folder last used in the select names dialog.</long> - </locale> - </schema> - - <!-- View state --> - - <schema> - <key>/schemas/apps/evolution/addressbook/display/vpane_position</key> - <applyto>/apps/evolution/addressbook/display/vpane_position</applyto> - <owner>evolution-addressbook</owner> - <type>int</type> - <locale name="C"> - <short>Vertical pane position</short> - <long>Position of the vertical pane, between the card and list views and the preview pane, in pixels.</long> - </locale> - </schema> - - <schema> - <key>/schemas/apps/evolution/addressbook/display/show_preview</key> - <applyto>/apps/evolution/addressbook/display/show_preview</applyto> - <owner>evolution-addressbook</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> - <short>Show preview pane</short> - <long>Whether to show the preview pane.</long> - </locale> - </schema> - - </schemalist> -</gconfschemafile> diff --git a/addressbook/gui/component/autocompletion-config.c b/addressbook/gui/component/autocompletion-config.c deleted file mode 100644 index ebb2381e1e..0000000000 --- a/addressbook/gui/component/autocompletion-config.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * e-shell-config-autocompletion.h - Configuration page for addressbook autocompletion. - * - * 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: - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - - -#include "autocompletion-config.h" - -#include "Evolution.h" - -#include <bonobo/bonobo-exception.h> - -#include <libedataserver/e-source-list.h> -#include <libedataserverui/e-source-selector.h> -#include <libedataserverui/e-name-selector-entry.h> -#include <gtk/gtk.h> -#include <glib/gi18n.h> - -#include "e-util/e-datetime-format.h" - - -typedef struct { - EvolutionConfigControl *config_control; - - GtkWidget *control_widget; - - ESourceList *source_list; - GConfClient *gconf; -} AutocompletionConfig; - -static void -source_selection_changed (ESourceSelector *selector, - AutocompletionConfig *ac) -{ - GSList *selection; - GSList *l; - GSList *groups; - - /* first we clear all the completion flags from all sources */ - for (groups = e_source_list_peek_groups (ac->source_list); groups; groups = groups->next) { - ESourceGroup *group = E_SOURCE_GROUP (groups->data); - GSList *sources; - for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) { - ESource *source = E_SOURCE (sources->data); - - e_source_set_property (source, "completion", NULL); - } - } - - /* then we loop over the selector's selection, setting the - property on those sources */ - selection = e_source_selector_get_selection (selector); - for (l = selection; l; l = l->next) { - e_source_set_property (E_SOURCE (l->data), "completion", "true"); - } - e_source_selector_free_selection (selection); - - e_source_list_sync (ac->source_list, NULL); /* XXX we should pop up a dialog if this fails */ -} - -static void -config_control_destroy_notify (gpointer data, - GObject *where_the_config_control_was) -{ - AutocompletionConfig *ac = (AutocompletionConfig *) data; - - g_object_unref (ac->source_list); - g_object_unref (ac->gconf); - - g_free (ac); -} - -static void -initialize_selection (AutocompletionConfig *ac) -{ - GSList *groups; - - for (groups = e_source_list_peek_groups (ac->source_list); groups; groups = groups->next) { - ESourceGroup *group = E_SOURCE_GROUP (groups->data); - GSList *sources; - for (sources = e_source_group_peek_sources (group); sources; sources = sources->next) { - ESource *source = E_SOURCE (sources->data); - const gchar *completion = e_source_get_property (source, "completion"); - if (completion && !g_ascii_strcasecmp (completion, "true")) - e_source_selector_select_source (E_SOURCE_SELECTOR (ac->control_widget), - source); - } - } -} - -static GtkWidget * -add_section (GtkWidget *vbox, const gchar *caption, gboolean expand) -{ - GtkWidget *label, *hbox, *itembox; - gchar *txt; - - g_return_val_if_fail (vbox != NULL, NULL); - g_return_val_if_fail (caption != NULL, NULL); - - txt = g_strconcat ("<b>", caption, "</b>", NULL); - - label = gtk_label_new (NULL); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - gtk_label_set_markup (GTK_LABEL (label), txt); - - g_free (txt); - - /* bold caption of the section */ - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); - - hbox = gtk_hbox_new (FALSE, 12); - - /* space on the left for the items in the section */ - gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (""), FALSE, FALSE, 0); - - /* itembox, here will all section items go */ - itembox = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (hbox), itembox, TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (vbox), hbox, expand, expand, 0); - - return itembox; -} - -static void -show_address_check_toggled_cb (GtkToggleButton *check, AutocompletionConfig *ac) -{ - g_return_if_fail (check != NULL); - g_return_if_fail (ac != NULL); - g_return_if_fail (ac->gconf != NULL); - - gconf_client_set_bool (ac->gconf, FORCE_SHOW_ADDRESS, gtk_toggle_button_get_active (check), NULL); -} - -EvolutionConfigControl* -autocompletion_config_control_new (void) -{ - AutocompletionConfig *ac; - CORBA_Environment ev; - GtkWidget *scrolledwin, *vbox, *itembox, *w, *table; - - ac = g_new0 (AutocompletionConfig, 1); - - CORBA_exception_init (&ev); - - ac->gconf = gconf_client_get_default (); - - vbox = gtk_vbox_new (FALSE, 6); - gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); - - itembox = add_section (vbox, _("Autocompletion"), FALSE); - - w = gtk_check_button_new_with_mnemonic (_("Always _show address of the autocompleted contact")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), gconf_client_get_bool (ac->gconf, FORCE_SHOW_ADDRESS, NULL)); - g_signal_connect (w, "toggled", (GCallback)show_address_check_toggled_cb, ac); - gtk_box_pack_start (GTK_BOX (itembox), w, FALSE, FALSE, 0); - - itembox = add_section (vbox, _("Date/Time Format"), FALSE); - table = gtk_table_new (1, 3, FALSE); - gtk_box_pack_start (GTK_BOX (itembox), table, TRUE, TRUE, 0); - e_datetime_format_add_setup_widget (table, 0, "addressbook", "table", DTFormatKindDateTime, _("Table column:")); - - itembox = add_section (vbox, _("Look up in address books"), TRUE); - - ac->source_list = e_source_list_new_for_gconf_default ("/apps/evolution/addressbook/sources"); - /* XXX should we watch for the source list to change and - update it in the control? what about our local changes? */ - /* g_signal_connect (ac->source_list, "changed", G_CALLBACK (source_list_changed), ac); */ - - scrolledwin = gtk_scrolled_window_new (NULL, NULL); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwin), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwin), - GTK_SHADOW_IN); - - ac->control_widget = e_source_selector_new (ac->source_list); - - gtk_container_add (GTK_CONTAINER (scrolledwin), ac->control_widget); - - initialize_selection (ac); - - gtk_widget_show (ac->control_widget); - gtk_widget_show (scrolledwin); - - gtk_widget_show_all (vbox); - gtk_box_pack_start (GTK_BOX (itembox), scrolledwin, TRUE, TRUE, 0); - - ac->config_control = evolution_config_control_new (vbox); - - g_signal_connect (ac->control_widget, "selection_changed", - G_CALLBACK (source_selection_changed), ac); - - g_object_weak_ref (G_OBJECT (ac->config_control), config_control_destroy_notify, ac); - - CORBA_exception_free (&ev); - - return ac->config_control; -} - diff --git a/addressbook/gui/component/autocompletion-config.h b/addressbook/gui/component/autocompletion-config.h deleted file mode 100644 index 0690604bc7..0000000000 --- a/addressbook/gui/component/autocompletion-config.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * e-shell-config-autocompletion.h - Configuration page for addressbook autocompletion. - * - * 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: - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _AUTOCOMPLETION_CONFIG_H -#define _AUTOCOMPLETION_CONFIG_H - -#include "evolution-config-control.h" - -EvolutionConfigControl* autocompletion_config_control_new (void); - -#endif /* _AUTOCOMPLETION_CONFIG_H */ diff --git a/addressbook/gui/component/component-factory.c b/addressbook/gui/component/component-factory.c deleted file mode 100644 index eddabd7b48..0000000000 --- a/addressbook/gui/component/component-factory.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * component-factory.c - Factory for Evolution's Addressbook component. - * - * 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 "addressbook.h" -#include "addressbook-component.h" -#include "addressbook-config.h" -#include "addressbook-view.h" -#include "autocompletion-config.h" -#include "eab-popup-control.h" -#ifdef ENABLE_SMIME -#include "smime/gui/certificate-manager.h" -#endif -#include <bonobo/bonobo-shlib-factory.h> - - -#define FACTORY_ID "OAFIID:GNOME_Evolution_Addressbook_Factory:" BASE_VERSION - -#define COMPONENT_ID "OAFIID:GNOME_Evolution_Addressbook_Component:" BASE_VERSION -#define ADDRESS_POPUP_ID "OAFIID:GNOME_Evolution_Addressbook_AddressPopup:" BASE_VERSION -#define COMPLETION_CONFIG_CONTROL_ID "OAFIID:GNOME_Evolution_Addressbook_Autocompletion_ConfigControl:" BASE_VERSION -#define CERTIFICATE_MANAGER_CONFIG_CONTROL_ID "OAFIID:GNOME_Evolution_SMime_CertificateManager_ConfigControl:" BASE_VERSION - -#define d(x) - - -static BonoboObject * -factory (BonoboGenericFactory *factory, - const gchar *component_id, - gpointer closure) -{ - d(printf ("asked to activate component_id `%s'\n", component_id)); - - if (strcmp (component_id, COMPONENT_ID) == 0) { - BonoboObject *object = BONOBO_OBJECT (addressbook_component_peek ()); - bonobo_object_ref (object); - return object; - } - if (strcmp (component_id, ADDRESS_POPUP_ID) == 0) - return BONOBO_OBJECT (eab_popup_control_new ()); - if (strcmp (component_id, COMPLETION_CONFIG_CONTROL_ID) == 0) - return BONOBO_OBJECT (autocompletion_config_control_new ()); -#ifdef ENABLE_SMIME - if (strcmp (component_id, CERTIFICATE_MANAGER_CONFIG_CONTROL_ID) == 0) - return BONOBO_OBJECT (certificate_manager_config_control_new ()); -#endif - - g_warning (FACTORY_ID ": Don't know what to do with %s", component_id); - return NULL; -} - -BONOBO_ACTIVATION_SHLIB_FACTORY (FACTORY_ID, "Evolution Addressbook component factory", factory, NULL) diff --git a/addressbook/gui/component/ldap-config.glade b/addressbook/gui/component/ldap-config.glade deleted file mode 100644 index f87cf84b14..0000000000 --- a/addressbook/gui/component/ldap-config.glade +++ /dev/null @@ -1,1454 +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="account-editor-window"> - <property name="visible">True</property> - <property name="title" translatable="yes">Address Book Properties</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_NONE</property> - <property name="modal">False</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - <property name="has_separator">False</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox7"> - <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_area7"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - - <child> - <widget class="GtkButton" id="account-editor-cancel-button"> - <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="focus_on_click">True</property> - <property name="response_id">-6</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="account-editor-ok-button"> - <property name="visible">True</property> - <property name="can_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="focus_on_click">True</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="GtkNotebook" id="account-editor-notebook"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="show_tabs">True</property> - <property name="show_border">True</property> - <property name="tab_pos">GTK_POS_TOP</property> - <property name="scrollable">False</property> - <property name="enable_popup">False</property> - - <child> - <widget class="GtkVBox" id="account-editor-general-vbox"> - <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="label564"> - <property name="visible">True</property> - <property name="label">Display</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">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="hbox122"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label563"> - <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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label431"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Name:</property> - <property name="use_underline">True</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> - <property name="mnemonic_widget">account-editor-display-name-entry</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="account-editor-display-name-entry"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">This is the name for this server that will appear in your Evolution folder list. It is for display purposes only. </property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </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">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="account-editor-connecting-vbox"> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label557"> - <property name="visible">True</property> - <property name="label">Server Information</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">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="hbox123"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label558"> - <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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table31"> - <property name="visible">True</property> - <property name="n_rows">3</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="label554"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Port:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label556"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Server:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">server-name-entry</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkHBox" id="hbox123"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label555"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Use secure connection:</property> - <property name="use_underline">True</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> - <property name="mnemonic_widget">ssl-combobox</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="ssl-combobox"> - <property name="visible">True</property> - <property name="items" translatable="yes">SSL encryption -TLS encryption -No encryption</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">2</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="server-name-entry"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">This is the full name of your LDAP server. For example, "ldap.mycompany.com".</property> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkComboBoxEntry" id="port-comboentry"> - <property name="visible">True</property> - <property name="items" translatable="yes">389 -636 -3268</property> - <property name="add_tearoffs">False</property> - <property name="has_frame">True</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options">fill</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> - - <child> - <widget class="GtkLabel" id="label559"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Authentication</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">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="hbox124"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label562"> - <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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table32"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="n_columns">2</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="label560"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Login method:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label561"> - <property name="visible">True</property> - <property name="label" translatable="yes">Lo_gin:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">auth-entry</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="auth-entry"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">Evolution will use this email address to authenticate you with the server.</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="auth-combobox"> - <property name="visible">True</property> - <property name="items" translatable="yes">Anonymously -Using email address -Using distinguished name (DN)</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">shrink|fill</property> - <property name="y_options">shrink|fill</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">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label334"> - <property name="visible">True</property> - <property name="label" translatable="yes">General</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.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</property> - </packing> - </child> - - <child> - <widget class="GtkVBox" id="account-editor-searching-vbox"> - <property name="border_width">12</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label565"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Searching</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">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="hbox125"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label571"> - <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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table33"> - <property name="visible">True</property> - <property name="n_rows">4</property> - <property name="n_columns">3</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkLabel" id="label569"> - <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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">fill</property> - <property name="y_options"></property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label566"> - <property name="visible">True</property> - <property name="label" translatable="yes">Search _base:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">rootdn-entry</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label567"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Search scope:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="rootdn-entry"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">The search base is the distinguished name (DN) of the entry where your searches will begin. If you leave this blank, the search will begin at the root of the directory tree.</property> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkButton" id="rootdn-button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - - <child> - <widget class="GtkAlignment" id="alignment61"> - <property name="visible">True</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xscale">0</property> - <property name="yscale">0</property> - <property name="top_padding">0</property> - <property name="bottom_padding">0</property> - <property name="left_padding">0</property> - <property name="right_padding">0</property> - - <child> - <widget class="GtkHBox" id="hbox126"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">2</property> - - <child> - <widget class="GtkImage" id="image10"> - <property name="visible">True</property> - <property name="stock">gtk-find</property> - <property name="icon_size">4</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="GtkLabel" id="label568"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Find Possible Search Bases</property> - <property name="use_underline">True</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - </child> - </widget> - </child> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label581"> - <property name="visible">True</property> - <property name="label" translatable="yes">Search _filter:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">search-filter-entry</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkEntry" id="search-filter-entry"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="editable">True</property> - <property name="visibility">True</property> - <property name="max_length">0</property> - <property name="text" translatable="yes"></property> - <property name="has_frame">True</property> - <property name="invisible_char">*</property> - <property name="activates_default">False</property> - <accessibility> - <atkproperty name="AtkObject::accessible_name" translatable="yes">Search Filter</atkproperty> - <atkproperty name="AtkObject::accessible_description" translatable="yes">Search filter is the type of object to be searched for. If this is not modified, the default search will be performed on the type "person".</atkproperty> - </accessibility> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">3</property> - <property name="bottom_attach">4</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkComboBox" id="scope-combobox"> - <property name="visible">True</property> - <property name="items" translatable="yes">One -Sub</property> - <property name="add_tearoffs">False</property> - <property name="focus_on_click">True</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">shrink|fill</property> - <property name="y_options">shrink|fill</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">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label572"> - <property name="visible">True</property> - <property name="label" translatable="yes"><b>Downloading</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">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="hbox127"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">12</property> - - <child> - <widget class="GtkLabel" id="label579"> - <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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkTable" id="table34"> - <property name="visible">True</property> - <property name="n_rows">3</property> - <property name="n_columns">3</property> - <property name="homogeneous">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">6</property> - - <child> - <widget class="GtkHBox" id="hbox128"> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">6</property> - - <child> - <widget class="GtkLabel" id="label575"> - <property name="visible">True</property> - <property name="label" translatable="yes">1</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">False</property> - <property name="fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkHScale" id="timeout-scale"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="draw_value">False</property> - <property name="value_pos">GTK_POS_TOP</property> - <property name="digits">1</property> - <property name="update_policy">GTK_UPDATE_CONTINUOUS</property> - <property name="inverted">False</property> - <property name="adjustment">3 1 5 0.5 1 0</property> - </widget> - <packing> - <property name="padding">0</property> - <property name="expand">True</property> - <property name="fill">True</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label576"> - <property name="visible">True</property> - <property name="label" translatable="yes">5</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> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">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="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label574"> - <property name="visible">True</property> - <property name="label" translatable="yes">minutes</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label578"> - <property name="visible">True</property> - <property name="label" translatable="yes">cards</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">2</property> - <property name="right_attach">3</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label573"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Timeout:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">timeout-scale</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">0</property> - <property name="bottom_attach">1</property> - <property name="x_options">shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label577"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Download limit:</property> - <property name="use_underline">True</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</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="mnemonic_widget">download-limit-spinbutton</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">1</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkSpinButton" id="download-limit-spinbutton"> - <property name="visible">True</property> - <property name="tooltip" translatable="yes">This is the maximum number of entries to download. Setting this number to be too large will slow down your address book.</property> - <property name="can_focus">True</property> - <property name="climb_rate">1</property> - <property name="digits">0</property> - <property name="numeric">False</property> - <property name="update_policy">GTK_UPDATE_ALWAYS</property> - <property name="snap_to_ticks">False</property> - <property name="wrap">False</property> - <property name="adjustment">0 0 1000 1 10 0</property> - </widget> - <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - <property name="x_options">expand|shrink|fill</property> - <property name="y_options">shrink|fill</property> - </packing> - </child> - - <child> - <widget class="GtkCheckButton" id="canbrowsecheck"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes" comments="To translators: If enabled, addressbook will only fetch contacts from the server until either set time limit or amount of contacts limit reached">B_rowse this book until limit reached</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="active">False</property> - <property name="inconsistent">False</property> - <property name="draw_indicator">True</property> - </widget> - <packing> - <property name="left_attach">0</property> - <property name="right_attach">3</property> - <property name="top_attach">2</property> - <property name="bottom_attach">3</property> - <property name="x_options">fill</property> - <property name="y_options"></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">False</property> - <property name="fill">False</property> - </packing> - </child> - </widget> - <packing> - <property name="tab_expand">False</property> - <property name="tab_fill">False</property> - </packing> - </child> - - <child> - <widget class="GtkLabel" id="label344"> - <property name="visible">True</property> - <property name="label" translatable="yes">Details</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.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> - </widget> - <packing> - <property name="type">tab</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> - -<widget class="GtkDialog" id="supported-bases-dialog"> - <property name="title" translatable="yes">Supported Search Bases</property> - <property name="type">GTK_WINDOW_TOPLEVEL</property> - <property name="window_position">GTK_WIN_POS_CENTER</property> - <property name="modal">False</property> - <property name="default_width">320</property> - <property name="default_height">200</property> - <property name="resizable">True</property> - <property name="destroy_with_parent">False</property> - <property name="decorated">True</property> - <property name="skip_taskbar_hint">False</property> - <property name="skip_pager_hint">False</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> - <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> - <property name="has_separator">False</property> - - <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox8"> - <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_area8"> - <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="focus_on_click">True</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="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="focus_on_click">True</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="vbox40"> - <property name="border_width">12</property> - <property name="visible">True</property> - <property name="homogeneous">False</property> - <property name="spacing">0</property> - - <child> - <widget class="Custom" id="supported-bases-table"> - <property name="visible">True</property> - <property name="creation_function">supported_bases_create_table</property> - <property name="int1">0</property> - <property name="int2">0</property> - <property name="last_modification_time">Fri, 12 Apr 2002 20:06:45 GMT</property> - </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/addressbook/gui/component/openldap-extract.h b/addressbook/gui/component/openldap-extract.h deleted file mode 100644 index 29175fb494..0000000000 --- a/addressbook/gui/component/openldap-extract.h +++ /dev/null @@ -1,1426 +0,0 @@ -/* This is extracted from the OpenLDAP sources. - * - * Stuff that isn't used in e-book-backend-ldap.c was dropped, like - * the LDAPSchemaExtensionItem stuff. - * - * This file basically has three parts: - * - * - some general macros from OpenLDAP that work as such on all - * implementations. - * - * - ldap_str2objectclass() - * - * - ldap_url_parse() - */ - -/* This work is part of OpenLDAP Software <http://www.openldap.org/>. - * - * Copyright 1998-2005 The OpenLDAP Foundation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in file COPYING.OPENLDAP in - * the top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include <string.h> -#include <assert.h> - -/* from various header files */ - -#define LDAP_CONST const - -#define LDAP_PORT 389 /* ldap:/// default LDAP port */ -#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ - -#define LDAP_ROOT_DSE "" - -#define LDAP_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') -#define LDAP_DIGIT(c) ((c) >= '0' && (c) <= '9') - -#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037" /* RFC 2830 */ - -#define LDAP_MALLOC(n) malloc((n)) -#define LDAP_CALLOC(n,s) calloc((n),(s)) -#define LDAP_REALLOC(p,s) realloc((p),(s)) -#define LDAP_FREE(p) free((p)) -#define LDAP_VFREE(p) vfree((gpointer *)(p)) -#define LDAP_STRDUP(s) strdup((s)) - -#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y))) -#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */ - -#define ldap_msgtype(lm) (lm)->lm_msgtype -#define ldap_msgid(lm) (lm)->lm_msgid - -#define LDAP_SCHERR_OUTOFMEM 1 -#define LDAP_SCHERR_UNEXPTOKEN 2 -#define LDAP_SCHERR_NOLEFTPAREN 3 -#define LDAP_SCHERR_NORIGHTPAREN 4 -#define LDAP_SCHERR_NODIGIT 5 -#define LDAP_SCHERR_BADNAME 6 -#define LDAP_SCHERR_BADDESC 7 -#define LDAP_SCHERR_BADSUP 8 -#define LDAP_SCHERR_DUPOPT 9 -#define LDAP_SCHERR_EMPTY 10 -#define LDAP_SCHERR_MISSING 11 -#define LDAP_SCHERR_OUT_OF_ORDER 12 - -#define LDAP_SCHEMA_YES 1 - -#define LDAP_SCHEMA_ABSTRACT 0 -#define LDAP_SCHEMA_STRUCTURAL 1 -#define LDAP_SCHEMA_AUXILIARY 2 - -#define LDAP_SCHEMA_ALLOW_NONE 0x00U /* Strict parsing */ -#define LDAP_SCHEMA_ALLOW_NO_OID 0x01U /* Allow missing oid */ -#define LDAP_SCHEMA_ALLOW_QUOTED 0x02U /* Allow bogus extra quotes */ -#define LDAP_SCHEMA_ALLOW_DESCR 0x04U /* Allow descr instead of OID */ -#define LDAP_SCHEMA_ALLOW_DESCR_PREFIX 0x08U /* Allow descr as OID prefix */ -#define LDAP_SCHEMA_ALLOW_OID_MACRO 0x10U /* Allow OID macros in slapd */ -#define LDAP_SCHEMA_ALLOW_OUT_OF_ORDER_FIELDS 0x20U /* Allow fields in most any order */ -#define LDAP_SCHEMA_ALLOW_ALL 0x3fU /* Be very liberal in parsing */ -#define LDAP_SCHEMA_SKIP 0x80U /* Don't malloc any result */ - -typedef struct ldap_objectclass { - gchar *oc_oid; /* REQUIRED */ - gchar **oc_names; /* OPTIONAL */ - gchar *oc_desc; /* OPTIONAL */ - gint oc_obsolete; /* 0=no, 1=yes */ - gchar **oc_sup_oids; /* OPTIONAL */ - gint oc_kind; /* 0=ABSTRACT, 1=STRUCTURAL, 2=AUXILIARY */ - gchar **oc_at_oids_must; /* OPTIONAL */ - gchar **oc_at_oids_may; /* OPTIONAL */ -} LDAPObjectClass; - -static void -vfree(gpointer *vec) -{ - gint i; - - for (i = 0; vec[i] != NULL; i++) - free(vec[i]); -} - -/* from schema.c */ - -/* - * Now come the parsers. There is one parser for each entity type: - * objectclasses, attributetypes, etc. - * - * Each of them is written as a recursive-descent parser, except that - * none of them is really recursive. But the idea is kept: there - * is one routine per non-terminal that eithers gobbles lexical tokens - * or calls lower-level routines, etc. - * - * The scanner is implemented in the routine get_token. Actually, - * get_token is more than a scanner and will return tokens that are - * in fact non-terminals in the grammar. So you can see the whole - * approach as the combination of a low-level bottom-up recognizer - * combined with a scanner and a number of top-down parsers. Or just - * consider that the real grammars recognized by the parsers are not - * those of the standards. As a matter of fact, our parsers are more - * liberal than the spec when there is no ambiguity. - * - * The difference is pretty academic (modulo bugs or incorrect - * interpretation of the specs). - */ - -#define TK_NOENDQUOTE -2 -#define TK_OUTOFMEM -1 -#define TK_EOS 0 -#define TK_UNEXPCHAR 1 -#define TK_BAREWORD 2 -#define TK_QDSTRING 3 -#define TK_LEFTPAREN 4 -#define TK_RIGHTPAREN 5 -#define TK_DOLLAR 6 -#define TK_QDESCR TK_QDSTRING - -struct token { - gint type; - gchar *sval; -}; - -static gint -get_token( const gchar ** sp, gchar ** token_val ) -{ - gint kind; - const gchar * p; - const gchar * q; - gchar * res; - - *token_val = NULL; - switch (**sp) { - case '\0': - kind = TK_EOS; - (*sp)++; - break; - case '(': - kind = TK_LEFTPAREN; - (*sp)++; - break; - case ')': - kind = TK_RIGHTPAREN; - (*sp)++; - break; - case '$': - kind = TK_DOLLAR; - (*sp)++; - break; - case '\'': - kind = TK_QDSTRING; - (*sp)++; - p = *sp; - while ( **sp != '\'' && **sp != '\0' ) - (*sp)++; - if ( **sp == '\'' ) { - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - (*sp)++; - } else { - kind = TK_NOENDQUOTE; - } - break; - default: - kind = TK_BAREWORD; - p = *sp; - while ( !LDAP_SPACE(**sp) && - **sp != '(' && - **sp != ')' && - **sp != '$' && - **sp != '\'' && - **sp != '\0' ) - (*sp)++; - q = *sp; - res = LDAP_MALLOC(q-p+1); - if ( !res ) { - kind = TK_OUTOFMEM; - } else { - strncpy(res,p,q-p); - res[q-p] = '\0'; - *token_val = res; - } - break; -/* kind = TK_UNEXPCHAR; */ -/* break; */ - } - - return kind; -} - -/* Gobble optional whitespace */ -static void -parse_whsp(const gchar **sp) -{ - while (LDAP_SPACE(**sp)) - (*sp)++; -} - -/* Parse a sequence of dot-separated decimal strings */ -static gchar * -ldap_int_parse_numericoid(const gchar **sp, gint *code, const gint flags) -{ - gchar * res = NULL; - const gchar * start = *sp; - gint len; - gint quoted = 0; - - /* Netscape puts the SYNTAX value in quotes (incorrectly) */ - if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && **sp == '\'' ) { - quoted = 1; - (*sp)++; - start++; - } - /* Each iteration of this loop gets one decimal string */ - while (**sp) { - if ( !LDAP_DIGIT(**sp) ) { - /* - * Initial gchar is not a digit or gchar after dot is - * not a digit - */ - *code = LDAP_SCHERR_NODIGIT; - return NULL; - } - (*sp)++; - while ( LDAP_DIGIT(**sp) ) - (*sp)++; - if ( **sp != '.' ) - break; - /* Otherwise, gobble the dot and loop again */ - (*sp)++; - } - /* Now *sp points at the gchar past the numericoid. Perfect. */ - len = *sp - start; - if ( flags & LDAP_SCHEMA_ALLOW_QUOTED && quoted ) { - if ( **sp == '\'' ) { - (*sp)++; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - return NULL; - } - } - if (flags & LDAP_SCHEMA_SKIP) { - res = (gchar *)start; - } else { - res = LDAP_MALLOC(len+1); - if (!res) { - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - strncpy(res,start,len); - res[len] = '\0'; - } - return(res); -} - -/* Parse a qdescr or a list of them enclosed in () */ -static gchar ** -parse_qdescrs(const gchar **sp, gint *code) -{ - gchar ** res; - gchar ** res1; - gint kind; - gchar * sval; - gint size; - gint pos; - - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_LEFTPAREN ) { - /* Let's presume there will be at least 2 entries */ - size = 3; - res = LDAP_CALLOC(3,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - pos = 0; - while (1) { - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_RIGHTPAREN ) - break; - if ( kind == TK_QDESCR ) { - if ( pos == size-2 ) { - size++; - res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); - if ( !res1 ) { - LDAP_VFREE(res); - LDAP_FREE(sval); - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - res = res1; - } - res[pos++] = sval; - res[pos] = NULL; - parse_whsp(sp); - } else { - LDAP_VFREE(res); - LDAP_FREE(sval); - *code = LDAP_SCHERR_UNEXPTOKEN; - return(NULL); - } - } - parse_whsp(sp); - return(res); - } else if ( kind == TK_QDESCR ) { - res = LDAP_CALLOC(2,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - res[0] = sval; - res[1] = NULL; - parse_whsp(sp); - return res; - } else { - LDAP_FREE(sval); - *code = LDAP_SCHERR_BADNAME; - return NULL; - } -} - -/* Parse a woid or a $-separated list of them enclosed in () */ -static gchar ** -parse_oids(const gchar **sp, gint *code, const gint allow_quoted) -{ - gchar ** res; - gchar ** res1; - gint kind; - gchar * sval; - gint size; - gint pos; - - /* - * Strictly speaking, doing this here accepts whsp before the - * ( at the begining of an oidlist, but this is harmless. Also, - * we are very liberal in what we accept as an OID. Maybe - * refine later. - */ - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_LEFTPAREN ) { - /* Let's presume there will be at least 2 entries */ - size = 3; - res = LDAP_CALLOC(3,sizeof(gchar *)); - if ( !res ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - pos = 0; - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_BAREWORD || - ( allow_quoted && kind == TK_QDSTRING ) ) { - res[pos++] = sval; - res[pos] = NULL; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - parse_whsp(sp); - while (1) { - kind = get_token(sp,&sval); - if ( kind == TK_RIGHTPAREN ) - break; - if ( kind == TK_DOLLAR ) { - parse_whsp(sp); - kind = get_token(sp,&sval); - if ( kind == TK_BAREWORD || - ( allow_quoted && - kind == TK_QDSTRING ) ) { - if ( pos == size-2 ) { - size++; - res1 = LDAP_REALLOC(res,size*sizeof(gchar *)); - if ( !res1 ) { - LDAP_FREE(sval); - LDAP_VFREE(res); - *code = LDAP_SCHERR_OUTOFMEM; - return(NULL); - } - res = res1; - } - res[pos++] = sval; - res[pos] = NULL; - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - parse_whsp(sp); - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - LDAP_FREE(sval); - LDAP_VFREE(res); - return NULL; - } - } - parse_whsp(sp); - return(res); - } else if ( kind == TK_BAREWORD || - ( allow_quoted && kind == TK_QDSTRING ) ) { - res = LDAP_CALLOC(2,sizeof(gchar *)); - if ( !res ) { - LDAP_FREE(sval); - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - res[0] = sval; - res[1] = NULL; - parse_whsp(sp); - return res; - } else { - LDAP_FREE(sval); - *code = LDAP_SCHERR_BADNAME; - return NULL; - } -} - -static void -ldap_objectclass_free(LDAPObjectClass * oc) -{ - LDAP_FREE(oc->oc_oid); - if (oc->oc_names) LDAP_VFREE(oc->oc_names); - if (oc->oc_desc) LDAP_FREE(oc->oc_desc); - if (oc->oc_sup_oids) LDAP_VFREE(oc->oc_sup_oids); - if (oc->oc_at_oids_must) LDAP_VFREE(oc->oc_at_oids_must); - if (oc->oc_at_oids_may) LDAP_VFREE(oc->oc_at_oids_may); - LDAP_FREE(oc); -} - -static LDAPObjectClass * -ldap_str2objectclass( LDAP_CONST gchar * s, - gint * code, - LDAP_CONST gchar ** errp, - LDAP_CONST unsigned flags ) -{ - gint kind; - const gchar * ss = s; - gchar * sval; - gint seen_name = 0; - gint seen_desc = 0; - gint seen_obsolete = 0; - gint seen_sup = 0; - gint seen_kind = 0; - gint seen_must = 0; - gint seen_may = 0; - LDAPObjectClass * oc; - gchar ** ext_vals; - const gchar * savepos; - - if ( !s ) { - *code = LDAP_SCHERR_EMPTY; - *errp = ""; - return NULL; - } - - *errp = s; - oc = LDAP_CALLOC(1,sizeof(LDAPObjectClass)); - - if ( !oc ) { - *code = LDAP_SCHERR_OUTOFMEM; - return NULL; - } - oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; - - kind = get_token(&ss,&sval); - if ( kind != TK_LEFTPAREN ) { - *code = LDAP_SCHERR_NOLEFTPAREN; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - - /* - * Definitions MUST begin with an OID in the numericoid format. - * However, this routine is used by clients to parse the response - * from servers and very well known servers will provide an OID - * in the wrong format or even no OID at all. We do our best to - * extract info from those servers. - */ - parse_whsp(&ss); - savepos = ss; - oc->oc_oid = ldap_int_parse_numericoid(&ss,code,0); - if ( !oc->oc_oid ) { - if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { - /* Backtracking */ - ss = savepos; - kind = get_token(&ss,&sval); - if ( kind == TK_BAREWORD ) { - if ( !strcasecmp(sval, "NAME") || - !strcasecmp(sval, "DESC") || - !strcasecmp(sval, "OBSOLETE") || - !strcasecmp(sval, "SUP") || - !strcasecmp(sval, "ABSTRACT") || - !strcasecmp(sval, "STRUCTURAL") || - !strcasecmp(sval, "AUXILIARY") || - !strcasecmp(sval, "MUST") || - !strcasecmp(sval, "MAY") || - !strncasecmp(sval, "X-", 2) ) { - /* Missing OID, backtrack */ - ss = savepos; - } else if ( flags & - LDAP_SCHEMA_ALLOW_OID_MACRO ) { - /* Non-numerical OID, ignore */ - gint len = ss-savepos; - oc->oc_oid = LDAP_MALLOC(len+1); - strncpy(oc->oc_oid, savepos, len); - oc->oc_oid[len] = 0; - } - } - LDAP_FREE(sval); - } else { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } - parse_whsp(&ss); - - /* - * Beyond this point we will be liberal an accept the items - * in any order. - */ - while (1) { - kind = get_token(&ss,&sval); - switch (kind) { - case TK_EOS: - *code = LDAP_SCHERR_NORIGHTPAREN; - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - case TK_RIGHTPAREN: - return oc; - case TK_BAREWORD: - if ( !strcasecmp(sval,"NAME") ) { - LDAP_FREE(sval); - if ( seen_name ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_name = 1; - oc->oc_names = parse_qdescrs(&ss,code); - if ( !oc->oc_names ) { - if ( *code != LDAP_SCHERR_OUTOFMEM ) - *code = LDAP_SCHERR_BADNAME; - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } else if ( !strcasecmp(sval,"DESC") ) { - LDAP_FREE(sval); - if ( seen_desc ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_desc = 1; - parse_whsp(&ss); - kind = get_token(&ss,&sval); - if ( kind != TK_QDSTRING ) { - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - oc->oc_desc = sval; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"OBSOLETE") ) { - LDAP_FREE(sval); - if ( seen_obsolete ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_obsolete = 1; - oc->oc_obsolete = LDAP_SCHEMA_YES; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"SUP") ) { - LDAP_FREE(sval); - if ( seen_sup ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_sup = 1; - oc->oc_sup_oids = parse_oids(&ss, - code, - flags); - if ( !oc->oc_sup_oids ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - } else if ( !strcasecmp(sval,"ABSTRACT") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_ABSTRACT; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"STRUCTURAL") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_STRUCTURAL; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"AUXILIARY") ) { - LDAP_FREE(sval); - if ( seen_kind ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_kind = 1; - oc->oc_kind = LDAP_SCHEMA_AUXILIARY; - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"MUST") ) { - LDAP_FREE(sval); - if ( seen_must ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_must = 1; - oc->oc_at_oids_must = parse_oids(&ss,code,0); - if ( !oc->oc_at_oids_must ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - parse_whsp(&ss); - } else if ( !strcasecmp(sval,"MAY") ) { - LDAP_FREE(sval); - if ( seen_may ) { - *code = LDAP_SCHERR_DUPOPT; - *errp = ss; - ldap_objectclass_free(oc); - return(NULL); - } - seen_may = 1; - oc->oc_at_oids_may = parse_oids(&ss,code,0); - if ( !oc->oc_at_oids_may ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } - parse_whsp(&ss); - } else if ( sval[0] == 'X' && sval[1] == '-' ) { - /* Should be parse_qdstrings */ - ext_vals = parse_qdescrs(&ss, code); - if ( !ext_vals ) { - *errp = ss; - ldap_objectclass_free(oc); - return NULL; - } -#if 0 - if ( add_extension(&oc->oc_extensions, - sval, ext_vals) ) { - *code = LDAP_SCHERR_OUTOFMEM; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } -#endif - } else { - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - break; - default: - *code = LDAP_SCHERR_UNEXPTOKEN; - *errp = ss; - LDAP_FREE(sval); - ldap_objectclass_free(oc); - return NULL; - } - } -} - -/* from utf-8.c */ - -#define LDAP_UTF8_NEXT(p) g_utf8_next_char((p)) -#define LDAP_UTF8_INCR(p) ((p)=LDAP_UTF8_NEXT((p))) -#define ldap_x_utf8_to_ucs4(str) g_utf8_get_char(str) - -static gchar *ldap_utf8_strchr( const gchar *str, const gchar *chr ) -{ - for (; *str != '\0'; LDAP_UTF8_INCR(str) ) { - if ( ldap_x_utf8_to_ucs4( str ) == ldap_x_utf8_to_ucs4( chr ) ) { - return (gchar *) str; - } - } - - return NULL; -} - -static gsize ldap_utf8_strcspn( const gchar *str, const gchar *set ) -{ - const gchar *cstr; - const gchar *cset; - - for ( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { - for ( cset = set; *cset != '\0'; LDAP_UTF8_INCR(cset) ) { - if ( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { - return cstr - str; - } - } - } - - return cstr - str; -} - -static gsize ldap_utf8_strspn( const gchar *str, const gchar *set ) -{ - const gchar *cstr; - const gchar *cset; - - for ( cstr = str; *cstr != '\0'; LDAP_UTF8_INCR(cstr) ) { - for ( cset = set; ; LDAP_UTF8_INCR(cset) ) { - if ( *cset == '\0' ) { - return cstr - str; - } - - if ( ldap_x_utf8_to_ucs4( cstr ) == ldap_x_utf8_to_ucs4( cset ) ) { - break; - } - } - } - - return cstr - str; -} - -static gchar *ldap_utf8_strtok(gchar *str, const gchar *sep, gchar **last) -{ - gchar *begin; - gchar *end; - - if ( last == NULL ) return NULL; - - begin = str ? str : *last; - - begin += ldap_utf8_strspn( begin, sep ); - - if ( *begin == '\0' ) { - *last = NULL; - return NULL; - } - - end = &begin[ ldap_utf8_strcspn( begin, sep ) ]; - - if ( *end != '\0' ) { - gchar *next = LDAP_UTF8_NEXT( end ); - *end = '\0'; - end = next; - } - - *last = end; - return begin; -} - -/* from ldap.h */ - -#define LDAP_URL_SUCCESS 0x00 /* Success */ -#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */ -#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */ - -#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */ -#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */ -#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */ -#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */ -#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */ -#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */ -#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */ -#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */ - -#define LDAP_URL_PREFIX "ldap://" -#define LDAP_URL_PREFIX_LEN (sizeof(LDAP_URL_PREFIX)-1) -#define LDAPS_URL_PREFIX "ldaps://" -#define LDAPS_URL_PREFIX_LEN (sizeof(LDAPS_URL_PREFIX)-1) -#define LDAPI_URL_PREFIX "ldapi://" -#define LDAPI_URL_PREFIX_LEN (sizeof(LDAPI_URL_PREFIX)-1) - -#define LDAP_URL_URLCOLON "URL:" -#define LDAP_URL_URLCOLON_LEN (sizeof(LDAP_URL_URLCOLON)-1) - -typedef struct ldap_url_desc { - struct ldap_url_desc *lud_next; - gchar *lud_scheme; - gchar *lud_host; - gint lud_port; - gchar *lud_dn; - gchar **lud_attrs; - gint lud_scope; - gchar *lud_filter; - gchar **lud_exts; - gint lud_crit_exts; -} LDAPURLDesc; - -/* from url.c */ - -static const gchar * -skip_url_prefix( - const gchar *url, - gint *enclosedp, - const gchar **scheme ) -{ - /* - * return non-zero if this looks like a LDAP URL; zero if not - * if non-zero returned, *urlp will be moved past "ldap://" part of URL - */ - const gchar *p; - - if ( url == NULL ) { - return( NULL ); - } - - p = url; - - /* skip leading '<' (if any) */ - if ( *p == '<' ) { - *enclosedp = 1; - ++p; - } else { - *enclosedp = 0; - } - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { - p += LDAP_URL_URLCOLON_LEN; - } - - /* check for "ldap://" prefix */ - if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldap://" prefix and return success */ - p += LDAP_URL_PREFIX_LEN; - *scheme = "ldap"; - return( p ); - } - - /* check for "ldaps://" prefix */ - if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldaps://" prefix and return success */ - p += LDAPS_URL_PREFIX_LEN; - *scheme = "ldaps"; - return( p ); - } - - /* check for "ldapi://" prefix */ - if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) { - /* skip over "ldapi://" prefix and return success */ - p += LDAPI_URL_PREFIX_LEN; - *scheme = "ldapi"; - return( p ); - } - -#ifdef LDAP_CONNECTIONLESS - /* check for "cldap://" prefix */ - if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { - /* skip over "cldap://" prefix and return success */ - p += LDAPC_URL_PREFIX_LEN; - *scheme = "cldap"; - return( p ); - } -#endif - - return( NULL ); -} - -static gint str2scope( const gchar *p ) -{ - if ( strcasecmp( p, "one" ) == 0 ) { - return LDAP_SCOPE_ONELEVEL; - - } else if ( strcasecmp( p, "onelevel" ) == 0 ) { - return LDAP_SCOPE_ONELEVEL; - - } else if ( strcasecmp( p, "base" ) == 0 ) { - return LDAP_SCOPE_BASE; - - } else if ( strcasecmp( p, "sub" ) == 0 ) { - return LDAP_SCOPE_SUBTREE; - - } else if ( strcasecmp( p, "subtree" ) == 0 ) { - return LDAP_SCOPE_SUBTREE; - } - - return( -1 ); -} - -static void -ldap_free_urldesc( LDAPURLDesc *ludp ) -{ - if ( ludp == NULL ) { - return; - } - - if ( ludp->lud_scheme != NULL ) { - LDAP_FREE( ludp->lud_scheme ); - } - - if ( ludp->lud_host != NULL ) { - LDAP_FREE( ludp->lud_host ); - } - - if ( ludp->lud_dn != NULL ) { - LDAP_FREE( ludp->lud_dn ); - } - - if ( ludp->lud_filter != NULL ) { - LDAP_FREE( ludp->lud_filter); - } - - if ( ludp->lud_attrs != NULL ) { - LDAP_VFREE( ludp->lud_attrs ); - } - - if ( ludp->lud_exts != NULL ) { - LDAP_VFREE( ludp->lud_exts ); - } - - LDAP_FREE( ludp ); -} - -static gint -ldap_int_unhex( gint c ) -{ - return( c >= '0' && c <= '9' ? c - '0' - : c >= 'A' && c <= 'F' ? c - 'A' + 10 - : c - 'a' + 10 ); -} - -static void -ldap_pvt_hex_unescape( gchar *s ) -{ - /* - * Remove URL hex escapes from s... done in place. The basic concept for - * this routine is borrowed from the WWW library HTUnEscape() routine. - */ - gchar *p; - - for ( p = s; *s != '\0'; ++s ) { - if ( *s == '%' ) { - if ( *++s == '\0' ) { - break; - } - *p = ldap_int_unhex( *s ) << 4; - if ( *++s == '\0' ) { - break; - } - *p++ += ldap_int_unhex( *s ); - } else { - *p++ = *s; - } - } - - *p = '\0'; -} - -static gchar ** -ldap_str2charray( const gchar *str_in, const gchar *brkstr ) -{ - gchar **res; - gchar *str, *s; - gchar *lasts; - gint i; - - /* protect the input string from strtok */ - str = LDAP_STRDUP( str_in ); - if ( str == NULL ) { - return NULL; - } - - i = 1; - for ( s = str; *s; s++ ) { - if ( ldap_utf8_strchr( brkstr, s ) != NULL ) { - i++; - } - } - - res = (gchar **) LDAP_MALLOC( (i + 1) * sizeof(gchar *) ); - - if ( res == NULL ) { - LDAP_FREE( str ); - return NULL; - } - - i = 0; - - for ( s = ldap_utf8_strtok( str, brkstr, &lasts ); - s != NULL; - s = ldap_utf8_strtok( NULL, brkstr, &lasts ) ) - { - res[i] = LDAP_STRDUP( s ); - - if (res[i] == NULL) { - for ( --i; i >= 0; i-- ) { - LDAP_FREE( res[i] ); - } - LDAP_FREE( res ); - LDAP_FREE( str ); - return NULL; - } - - i++; - } - - res[i] = NULL; - - LDAP_FREE( str ); - return( res ); -} - -static gint -ldap_url_parse_ext( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) -{ -/* - * Pick apart the pieces of an LDAP URL. - */ - - LDAPURLDesc *ludp; - gchar *p, *q, *r; - gint i, enclosed; - const gchar *scheme = NULL; - const gchar *url_tmp; - gchar *url; - - if ( url_in == NULL || ludpp == NULL ) { - return LDAP_URL_ERR_PARAM; - } - - *ludpp = NULL; /* pessimistic */ - - url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); - - if ( url_tmp == NULL ) { - return LDAP_URL_ERR_BADSCHEME; - } - - assert( scheme ); - - /* make working copy of the remainder of the URL */ - url = LDAP_STRDUP( url_tmp ); - if ( url == NULL ) { - return LDAP_URL_ERR_MEM; - } - - if ( enclosed ) { - p = &url[strlen(url)-1]; - - if ( *p != '>' ) { - LDAP_FREE( url ); - return LDAP_URL_ERR_BADENCLOSURE; - } - - *p = '\0'; - } - - /* allocate return struct */ - ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc )); - - if ( ludp == NULL ) { - LDAP_FREE( url ); - return LDAP_URL_ERR_MEM; - } - - ludp->lud_next = NULL; - ludp->lud_host = NULL; - ludp->lud_port = 0; - ludp->lud_dn = NULL; - ludp->lud_attrs = NULL; - ludp->lud_filter = NULL; - ludp->lud_scope = LDAP_SCOPE_DEFAULT; - ludp->lud_filter = NULL; - ludp->lud_exts = NULL; - - ludp->lud_scheme = LDAP_STRDUP( scheme ); - - if ( ludp->lud_scheme == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - /* scan forward for '/' that marks end of hostport and begin. of dn */ - p = strchr( url, '/' ); - - if ( p != NULL ) { - /* terminate hostport; point to start of dn */ - *p++ = '\0'; - } - - /* IPv6 syntax with [ip address]:port */ - if ( *url == '[' ) { - r = strchr( url, ']' ); - if ( r == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - *r++ = '\0'; - q = strchr( r, ':' ); - } else { - q = strchr( url, ':' ); - } - - if ( q != NULL ) { - gchar *next; - - *q++ = '\0'; - ldap_pvt_hex_unescape( q ); - - if ( *q == '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - - ludp->lud_port = strtol( q, &next, 10 ); - if ( next == NULL || next[0] != '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - } - - ldap_pvt_hex_unescape( url ); - - /* If [ip address]:port syntax, url is [ip and we skip the [ */ - ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) ); - - if ( ludp->lud_host == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - /* - * Kludge. ldap://111.222.333.444:389??cn=abc,o=company - * - * On early Novell releases, search references/referrals were returned - * in this format, i.e., the dn was kind of in the scope position, - * but the required slash is missing. The whole thing is illegal syntax, - * but we need to account for it. Fortunately it can't be confused with - * anything real. - */ - if ( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { - q++; - /* ? immediately followed by question */ - if ( *q == '?') { - q++; - if ( *q != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( q ); - ludp->lud_dn = LDAP_STRDUP( q ); - } else { - ludp->lud_dn = LDAP_STRDUP( "" ); - } - - if ( ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - } - } - - if ( p == NULL ) { - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of dn */ - q = strchr( p, '?' ); - - if ( q != NULL ) { - /* terminate dn part */ - *q++ = '\0'; - } - - if ( *p != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( p ); - ludp->lud_dn = LDAP_STRDUP( p ); - } else { - ludp->lud_dn = LDAP_STRDUP( "" ); - } - - if ( ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of attributes */ - p = q; - q = strchr( p, '?' ); - - if ( q != NULL ) { - /* terminate attributes part */ - *q++ = '\0'; - } - - if ( *p != '\0' ) { - /* parse attributes */ - ldap_pvt_hex_unescape( p ); - ludp->lud_attrs = ldap_str2charray( p, "," ); - - if ( ludp->lud_attrs == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADATTRS; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of scope */ - p = q; - q = strchr( p, '?' ); - - if ( q != NULL ) { - /* terminate the scope part */ - *q++ = '\0'; - } - - if ( *p != '\0' ) { - /* parse the scope */ - ldap_pvt_hex_unescape( p ); - ludp->lud_scope = str2scope( p ); - - if ( ludp->lud_scope == -1 ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADSCOPE; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of filter */ - p = q; - q = strchr( p, '?' ); - - if ( q != NULL ) { - /* terminate the filter part */ - *q++ = '\0'; - } - - if ( *p != '\0' ) { - /* parse the filter */ - ldap_pvt_hex_unescape( p ); - - if ( ! *p ) { - /* missing filter */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADFILTER; - } - - LDAP_FREE( ludp->lud_filter ); - ludp->lud_filter = LDAP_STRDUP( p ); - - if ( ludp->lud_filter == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } - } - - if ( q == NULL ) { - /* no more */ - LDAP_FREE( url ); - *ludpp = ludp; - return LDAP_URL_SUCCESS; - } - - /* scan forward for '?' that may marks end of extensions */ - p = q; - q = strchr( p, '?' ); - - if ( q != NULL ) { - /* extra '?' */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } - - /* parse the extensions */ - ludp->lud_exts = ldap_str2charray( p, "," ); - - if ( ludp->lud_exts == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADEXTS; - } - - for ( i=0; ludp->lud_exts[i] != NULL; i++ ) { - ldap_pvt_hex_unescape( ludp->lud_exts[i] ); - - if ( *ludp->lud_exts[i] == '!' ) { - /* count the number of critical extensions */ - ludp->lud_crit_exts++; - } - } - - if ( i == 0 ) { - /* must have 1 or more */ - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADEXTS; - } - - /* no more */ - *ludpp = ludp; - LDAP_FREE( url ); - return LDAP_URL_SUCCESS; -} - -static gint -ldap_url_parse( LDAP_CONST gchar *url_in, LDAPURLDesc **ludpp ) -{ - gint rc = ldap_url_parse_ext( url_in, ludpp ); - - if ( rc != LDAP_URL_SUCCESS ) { - return rc; - } - - if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) { - (*ludpp)->lud_scope = LDAP_SCOPE_BASE; - } - - if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') { - LDAP_FREE( (*ludpp)->lud_host ); - (*ludpp)->lud_host = NULL; - } - - if ((*ludpp)->lud_port == 0) { - if ( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) { - (*ludpp)->lud_port = LDAP_PORT; -#ifdef LDAP_CONNECTIONLESS - } else if ( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) { - (*ludpp)->lud_port = LDAP_PORT; -#endif - } else if ( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) { - (*ludpp)->lud_port = LDAPS_PORT; - } - } - - return rc; -} - diff --git a/addressbook/gui/contact-editor/Makefile.am b/addressbook/gui/contact-editor/Makefile.am index 36ba4c90a8..29ddb6ee9c 100644 --- a/addressbook/gui/contact-editor/Makefile.am +++ b/addressbook/gui/contact-editor/Makefile.am @@ -29,10 +29,13 @@ libecontacteditor_la_SOURCES = \ libecontacteditor_la_LDFLAGS = $(NO_UNDEFINED) -libecontacteditor_la_LIBADD = \ - $(WIN32_BOOTSTRAP_LIBS) \ - $(top_builddir)/widgets/misc/libemiscwidgets.la \ - $(top_builddir)/e-util/libeutil.la \ +libecontacteditor_la_LIBADD = \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/addressbook/util/libeabutil.la \ + $(top_builddir)/addressbook/gui/widgets/libeabwidgets.la \ + $(top_builddir)/addressbook/gui/merging/libeabbookmerging.la \ + $(top_builddir)/addressbook/printing/libecontactprint.la \ $(EVOLUTION_ADDRESSBOOK_LIBS) glade_DATA = \ diff --git a/addressbook/gui/contact-editor/e-contact-editor.c b/addressbook/gui/contact-editor/e-contact-editor.c index fc4c8ff8df..007436e7da 100644 --- a/addressbook/gui/contact-editor/e-contact-editor.c +++ b/addressbook/gui/contact-editor/e-contact-editor.c @@ -33,7 +33,6 @@ #include <gdk-pixbuf/gdk-pixbuf.h> #include <libedataserverui/e-categories-dialog.h> -#include <misc/e-gui-utils.h> #include <libebook/e-address-western.h> #include <libedataserverui/e-category-completion.h> @@ -41,7 +40,7 @@ #include <camel/camel.h> -#include "addressbook/gui/component/addressbook.h" +#include "addressbook/util/addressbook.h" #include "addressbook/printing/e-contact-print.h" #include "addressbook/gui/widgets/eab-gui-util.h" #include "e-util/e-util.h" @@ -49,9 +48,9 @@ #include "misc/e-dateedit.h" #include "misc/e-image-chooser.h" #include "misc/e-url-entry.h" -#include "shell/evolution-shell-component-utils.h" #include "e-util/e-icon-factory.h" #include "e-util/e-util-private.h" +#include "shell/e-shell.h" #include "eab-contact-merging.h" @@ -198,6 +197,54 @@ static const gint email_default [] = { 0, 1, 2, 2 }; #define STRING_IS_EMPTY(x) (!(x) || !(*(x))) #define STRING_MAKE_NON_NULL(x) ((x) ? (x) : "") +static void +e_contact_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error adding contact"), status); +} + +static void +e_contact_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error modifying contact"), status); +} + +static void +e_contact_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error removing contact"), status); +} + +static void +e_contact_editor_closed (EABEditor *editor) +{ + g_object_unref (editor); +} + GType e_contact_editor_get_type (void) { @@ -241,6 +288,10 @@ e_contact_editor_class_init (EContactEditorClass *klass) editor_class->save_contact = e_contact_editor_save_contact; editor_class->is_changed = e_contact_editor_is_changed; editor_class->get_window = e_contact_editor_get_window; + editor_class->contact_added = e_contact_editor_contact_added; + editor_class->contact_modified = e_contact_editor_contact_modified; + editor_class->contact_deleted = e_contact_editor_contact_deleted; + editor_class->editor_closed = e_contact_editor_closed; g_object_class_install_property (object_class, PROP_SOURCE_BOOK, g_param_spec_object ("source_book", @@ -3322,6 +3373,7 @@ static void e_contact_editor_init (EContactEditor *e_contact_editor) { GladeXML *gui; + EShell *shell; GtkWidget *widget, *label; GtkEntryCompletion *completion; gchar *gladefile; @@ -3399,6 +3451,10 @@ e_contact_editor_init (EContactEditor *e_contact_editor) /* show window */ gtk_widget_show (e_contact_editor->app); + + /* FIXME Shell should be passed in. */ + shell = e_shell_get_default (); + e_shell_watch_window (shell, GTK_WINDOW (e_contact_editor->app)); } static void @@ -3455,7 +3511,7 @@ static void supported_fields_cb (EBook *book, EBookStatus status, EList *fields, EContactEditor *ce) { - if (!g_slist_find ((GSList*)eab_editor_get_all_editors (), ce)) { + if (!g_slist_find (eab_editor_get_all_editors (), ce)) { g_warning ("supported_fields_cb called for book that's still around, but contact editor that's been destroyed."); return; } @@ -3474,7 +3530,7 @@ required_fields_cb (EBook *book, EBookStatus status, EList *fields, EContactEditor *ce) { - if (!g_slist_find ((GSList*)eab_editor_get_all_editors (), ce)) { + if (!g_slist_find (eab_editor_get_all_editors (), ce)) { g_warning ("supported_fields_cb called for book that's still around, but contact editor that's been destroyed."); return; } @@ -3485,30 +3541,22 @@ required_fields_cb (EBook *book, EBookStatus status, } -static void -contact_editor_destroy_notify (gpointer data, - GObject *where_the_object_was) +EABEditor * +e_contact_editor_new (EShell *shell, + EBook *book, + EContact *contact, + gboolean is_new_contact, + gboolean editable) { - eab_editor_remove (EAB_EDITOR (data)); -} - -EContactEditor * -e_contact_editor_new (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactEditor *ce; + EABEditor *editor; + g_return_val_if_fail (E_IS_SHELL (shell), NULL); g_return_val_if_fail (E_IS_BOOK (book), NULL); g_return_val_if_fail (E_IS_CONTACT (contact), NULL); - ce = g_object_new (E_TYPE_CONTACT_EDITOR, NULL); + editor = g_object_new (E_TYPE_CONTACT_EDITOR, "shell", shell, NULL); - eab_editor_add (EAB_EDITOR (ce)); - g_object_weak_ref (G_OBJECT (ce), contact_editor_destroy_notify, ce); - - g_object_set (ce, + g_object_set (editor, "source_book", book, "contact", contact, "is_new_contact", is_new_contact, @@ -3516,9 +3564,10 @@ e_contact_editor_new (EBook *book, NULL); if (book) - e_book_async_get_supported_fields (book, (EBookEListCallback)supported_fields_cb, ce); + e_book_async_get_supported_fields ( + book, (EBookEListCallback)supported_fields_cb, editor); - return ce; + return editor; } static void diff --git a/addressbook/gui/contact-editor/e-contact-editor.h b/addressbook/gui/contact-editor/e-contact-editor.h index cdd9c2e8da..9a83831eff 100644 --- a/addressbook/gui/contact-editor/e-contact-editor.h +++ b/addressbook/gui/contact-editor/e-contact-editor.h @@ -23,7 +23,6 @@ #ifndef __E_CONTACT_EDITOR_H__ #define __E_CONTACT_EDITOR_H__ -#include <bonobo/bonobo-ui-component.h> #include <glade/glade.h> #include "addressbook/gui/contact-editor/eab-editor.h" @@ -62,9 +61,6 @@ struct _EContactEditor EBook *target_book; EContact *contact; - /* UI handler */ - BonoboUIComponent *uic; - GladeXML *gui; GtkWidget *app; @@ -110,11 +106,12 @@ struct _EContactEditorClass EABEditorClass parent_class; }; -EContactEditor *e_contact_editor_new (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -GType e_contact_editor_get_type (void); +GType e_contact_editor_get_type (void); +EABEditor *e_contact_editor_new (EShell *shell, + EBook *book, + EContact *contact, + gboolean is_new_contact, + gboolean editable); G_END_DECLS diff --git a/addressbook/gui/contact-editor/e-contact-quick-add.c b/addressbook/gui/contact-editor/e-contact-quick-add.c index 0f6552ba18..bb40e9a79d 100644 --- a/addressbook/gui/contact-editor/e-contact-quick-add.c +++ b/addressbook/gui/contact-editor/e-contact-quick-add.c @@ -28,7 +28,7 @@ #include <libebook/e-book.h> #include <libebook/e-contact.h> #include <libedataserverui/e-source-combo-box.h> -#include <addressbook/gui/component/addressbook.h> +#include <addressbook/util/addressbook.h> #include <addressbook/util/eab-book-util.h> #include "e-contact-editor.h" #include "e-contact-quick-add.h" @@ -49,7 +49,7 @@ struct _QuickAdd { GtkWidget *dialog; GtkWidget *name_entry; GtkWidget *email_entry; - GtkWidget *option_menu; + GtkWidget *combo_box; gint refs; @@ -193,7 +193,12 @@ ce_have_book (EBook *book, EBookStatus status, gpointer closure) g_warning ("Couldn't open local address book."); quick_add_unref (qa); } else { - EContactEditor *contact_editor = e_contact_editor_new (book, qa->contact, TRUE, TRUE /* XXX */); + EShell *shell; + EABEditor *contact_editor; + + shell = e_shell_get_default (); + contact_editor = e_contact_editor_new ( + shell, book, qa->contact, TRUE, TRUE /* XXX */); /* mark it as changed so the Save buttons are enabled when we bring up the dialog. */ g_object_set (contact_editor, @@ -284,7 +289,7 @@ sanitize_widgets (QuickAdd *qa) g_return_if_fail (qa->dialog != NULL); /* do not call here e_book_is_writable (qa->book), because it requires opened book, which takes time for remote books */ - enabled = qa->book != NULL && e_source_combo_box_get_active_uid (E_SOURCE_COMBO_BOX (qa->option_menu)); + enabled = qa->book != NULL && e_source_combo_box_get_active_uid (E_SOURCE_COMBO_BOX (qa->combo_box)); gtk_dialog_set_response_sensitive (GTK_DIALOG (qa->dialog), QUICK_ADD_RESPONSE_EDIT_FULL, enabled); gtk_dialog_set_response_sensitive (GTK_DIALOG (qa->dialog), GTK_RESPONSE_OK, enabled); @@ -355,13 +360,13 @@ build_quick_add_dialog (QuickAdd *qa) gconf_client = gconf_client_get_default (); source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/addressbook/sources"); g_object_unref (gconf_client); - qa->option_menu = e_source_combo_box_new (source_list); + qa->combo_box = e_source_combo_box_new (source_list); book = e_book_new_default_addressbook (NULL); e_source_combo_box_set_active ( - E_SOURCE_COMBO_BOX (qa->option_menu), + E_SOURCE_COMBO_BOX (qa->combo_box), e_book_get_source (book)); - if (!e_source_combo_box_get_active_uid (E_SOURCE_COMBO_BOX (qa->option_menu))) { + if (!e_source_combo_box_get_active_uid (E_SOURCE_COMBO_BOX (qa->combo_box))) { /* this means the e_book_new_default_addressbook didn't find any "default" nor "system" source, and created new one for us. That is wrong, choose one from combo instead. */ @@ -371,9 +376,9 @@ build_quick_add_dialog (QuickAdd *qa) } book = e_book_new (e_source_list_peek_source_any (source_list), NULL); - e_source_combo_box_set_active (E_SOURCE_COMBO_BOX (qa->option_menu), e_book_get_source (book)); + e_source_combo_box_set_active (E_SOURCE_COMBO_BOX (qa->combo_box), e_book_get_source (book)); - if (!e_source_combo_box_get_active_uid (E_SOURCE_COMBO_BOX (qa->option_menu))) { + if (!e_source_combo_box_get_active_uid (E_SOURCE_COMBO_BOX (qa->combo_box))) { /* Does it failed again? What is going on? */ if (book) g_object_unref (book); @@ -386,9 +391,9 @@ build_quick_add_dialog (QuickAdd *qa) qa->book = NULL; } qa->book = book; - source_changed (E_SOURCE_COMBO_BOX (qa->option_menu), qa); + source_changed (E_SOURCE_COMBO_BOX (qa->combo_box), qa); g_signal_connect ( - qa->option_menu, "changed", + qa->combo_box, "changed", G_CALLBACK (source_changed), qa); g_object_unref (source_list); @@ -420,13 +425,13 @@ build_quick_add_dialog (QuickAdd *qa) GTK_EXPAND | GTK_FILL, 0, xpad, ypad); label = gtk_label_new_with_mnemonic (_("_Select Address Book")); - gtk_label_set_mnemonic_widget ((GtkLabel *)label, qa->option_menu); + gtk_label_set_mnemonic_widget ((GtkLabel *)label, qa->combo_box); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_table_attach (table, label, 0, 1, 2, 3, GTK_FILL, 0, xpad, ypad); - gtk_table_attach (table, qa->option_menu, + gtk_table_attach (table, qa->combo_box, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, xpad, ypad); diff --git a/addressbook/gui/contact-editor/eab-editor.c b/addressbook/gui/contact-editor/eab-editor.c index 19c3d9c7e3..554db9aa7b 100644 --- a/addressbook/gui/contact-editor/eab-editor.c +++ b/addressbook/gui/contact-editor/eab-editor.c @@ -28,16 +28,22 @@ #include <glib/gi18n.h> #include "eab-editor.h" -#include "addressbook/gui/widgets/eab-gui-util.h" #include "e-util/e-util.h" +#include "addressbook/gui/widgets/eab-gui-util.h" + +#define EAB_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_EDITOR, EABEditorPrivate)) + +struct _EABEditorPrivate { + EShell *shell; +}; -static void eab_editor_default_show (EABEditor *editor); -static void eab_editor_default_raise (EABEditor *editor); -static void eab_editor_default_close (EABEditor *editor); -static void eab_editor_class_init (EABEditorClass *klass); -static void eab_editor_init (EABEditor *editor); +enum { + PROP_0, + PROP_SHELL +}; -/* Signal IDs */ enum { CONTACT_ADDED, CONTACT_MODIFIED, @@ -46,97 +52,125 @@ enum { LAST_SIGNAL }; -static GSList *all_editors = NULL; - -static GtkObjectClass *parent_class = NULL; +static GSList *all_editors; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -static guint editor_signals[LAST_SIGNAL]; - -GType -eab_editor_get_type (void) +static void +eab_editor_quit_requested_cb (EABEditor *editor, + EShell *shell) { - static GType editor_type = 0; - - if (!editor_type) { - static const GTypeInfo editor_info = { - sizeof (EABEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_editor_init, - }; + GtkWindow *window; - editor_type = g_type_register_static (G_TYPE_OBJECT, "EABEditor", &editor_info, 0); - } + window = eab_editor_get_window (editor); - return editor_type; + eab_editor_raise (editor); + if (!eab_editor_prompt_to_save_changes (editor, window)) + e_shell_cancel_quit (shell); } static void -eab_editor_default_show (EABEditor *editor) +eab_editor_set_shell (EABEditor *editor, + EShell *shell) { - g_warning ("abstract eab_editor_show called"); + g_return_if_fail (editor->priv->shell == NULL); + g_return_if_fail (E_IS_SHELL (shell)); + + editor->priv->shell = g_object_ref (shell); + + g_signal_connect_swapped ( + shell, "quit-requested", + G_CALLBACK (eab_editor_quit_requested_cb), editor); } static void -eab_editor_default_close (EABEditor *editor) +eab_editor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - g_warning ("abstract eab_editor_close called"); + switch (property_id) { + case PROP_SHELL: + eab_editor_set_shell ( + EAB_EDITOR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -eab_editor_default_raise (EABEditor *editor) +eab_editor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - g_warning ("abstract eab_editor_raise called"); + switch (property_id) { + case PROP_SHELL: + g_value_set_object ( + value, eab_editor_get_shell ( + EAB_EDITOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -eab_editor_default_save_contact (EABEditor *editor, gboolean should_close) +eab_editor_dispose (GObject *object) { - g_warning ("abstract eab_editor_save_contact called"); -} + EABEditorPrivate *priv; -static gboolean -eab_editor_default_is_valid (EABEditor *editor) -{ - g_warning ("abstract eab_editor_is_valid called"); - return FALSE; -} + priv = EAB_EDITOR_GET_PRIVATE (object); -static gboolean -eab_editor_default_is_changed (EABEditor *editor) -{ - g_warning ("abstract eab_editor_is_changed called"); - return FALSE; -} + if (priv->shell != NULL) { + g_signal_handlers_disconnect_matched ( + priv->shell, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->shell); + priv->shell = NULL; + } -static GtkWindow* -eab_editor_default_get_window (EABEditor *editor) -{ - g_warning ("abstract eab_editor_get_window called"); - return NULL; + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -eab_editor_class_init (EABEditorClass *klass) +eab_editor_finalize (GObject *object) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + all_editors = g_slist_remove (all_editors, object); - parent_class = g_type_class_ref (G_TYPE_OBJECT); - - klass->show = eab_editor_default_show; - klass->close = eab_editor_default_close; - klass->raise = eab_editor_default_raise; - klass->save_contact = eab_editor_default_save_contact; - klass->is_valid = eab_editor_default_is_valid; - klass->is_changed = eab_editor_default_is_changed; - klass->get_window = eab_editor_default_get_window; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} - editor_signals[CONTACT_ADDED] = +static void +eab_editor_class_init (EABEditorClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EABEditorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = eab_editor_set_property; + object_class->get_property = eab_editor_get_property; + object_class->dispose = eab_editor_dispose; + object_class->finalize = eab_editor_finalize; + + 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)); + + signals[CONTACT_ADDED] = g_signal_new ("contact_added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -146,7 +180,7 @@ eab_editor_class_init (EABEditorClass *klass) G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_OBJECT); - editor_signals[CONTACT_MODIFIED] = + signals[CONTACT_MODIFIED] = g_signal_new ("contact_modified", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -156,7 +190,7 @@ eab_editor_class_init (EABEditorClass *klass) G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_OBJECT); - editor_signals[CONTACT_DELETED] = + signals[CONTACT_DELETED] = g_signal_new ("contact_deleted", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -166,7 +200,7 @@ eab_editor_class_init (EABEditorClass *klass) G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_OBJECT); - editor_signals[EDITOR_CLOSED] = + signals[EDITOR_CLOSED] = g_signal_new ("editor_closed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -179,78 +213,143 @@ eab_editor_class_init (EABEditorClass *klass) static void eab_editor_init (EABEditor *editor) { + editor->priv = EAB_EDITOR_GET_PRIVATE (editor); + + all_editors = g_slist_prepend (all_editors, editor); } - +GType +eab_editor_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EABEditorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) eab_editor_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EABEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) eab_editor_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EABEditor", &type_info, + G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +EShell * +eab_editor_get_shell (EABEditor *editor) +{ + g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL); + + return E_SHELL (editor->priv->shell); +} + +GSList * +eab_editor_get_all_editors (void) +{ + return all_editors; +} void eab_editor_show (EABEditor *editor) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->show) - EAB_EDITOR_GET_CLASS(editor)->show (editor); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->show != NULL); + + class->show (editor); } void eab_editor_close (EABEditor *editor) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->close) - EAB_EDITOR_GET_CLASS(editor)->close (editor); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->close != NULL); + + class->close (editor); } void eab_editor_raise (EABEditor *editor) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->raise) - EAB_EDITOR_GET_CLASS(editor)->raise (editor); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->raise != NULL); + + class->raise (editor); } void eab_editor_save_contact (EABEditor *editor, gboolean should_close) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->save_contact) - EAB_EDITOR_GET_CLASS(editor)->save_contact (editor, should_close); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->save_contact != NULL); + + class->save_contact (editor, should_close); } gboolean eab_editor_is_changed (EABEditor *editor) { + EABEditorClass *class; + g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE); - if (EAB_EDITOR_GET_CLASS(editor)->is_changed) - return EAB_EDITOR_GET_CLASS(editor)->is_changed (editor); - else - return FALSE; + class = EAB_EDITOR_GET_CLASS (editor); + g_return_val_if_fail (class->is_changed != NULL, FALSE); + + return class->is_changed (editor); } gboolean eab_editor_is_valid (EABEditor *editor) { + EABEditorClass *class; + g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE); - if (EAB_EDITOR_GET_CLASS(editor)->is_valid) - return EAB_EDITOR_GET_CLASS(editor)->is_valid (editor); - else - return FALSE; + class = EAB_EDITOR_GET_CLASS (editor); + g_return_val_if_fail (class->is_valid != NULL, FALSE); + + return class->is_valid (editor); } GtkWindow* eab_editor_get_window (EABEditor *editor) { + EABEditorClass *class; + g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL); - if (EAB_EDITOR_GET_CLASS(editor)->get_window) - return EAB_EDITOR_GET_CLASS(editor)->get_window (editor); - else - return NULL; + class = EAB_EDITOR_GET_CLASS (editor); + g_return_val_if_fail (class->get_window != NULL, NULL); + + return class->get_window (editor); } + /* This function prompts for saving if editor conents are in changed state and save or discards or cancels(just returns with out doing anything) according to user input. Editor gets destoryed in case of save and discard case. @@ -280,108 +379,37 @@ eab_editor_prompt_to_save_changes (EABEditor *editor, GtkWindow *window) } } -gboolean -eab_editor_request_close_all (void) -{ - GSList *p; - GSList *pnext; - gboolean retval; - - retval = TRUE; - for (p = all_editors; p != NULL; p = pnext) { - EABEditor *editor = EAB_EDITOR (p->data); - GtkWindow *window = eab_editor_get_window (editor); - - pnext = p->next; - - eab_editor_raise (editor); - if (! eab_editor_prompt_to_save_changes (editor, window)) { - retval = FALSE; - break; - } - } - - return retval; -} - -const GSList* -eab_editor_get_all_editors (void) -{ - return all_editors; -} - -gboolean -eab_editor_confirm_delete (GtkWindow *parent, gboolean plural, gboolean is_list, gchar *name) -{ - GtkWidget *dialog; - gint result; - gchar *msg; - - if (is_list) { - /* contact list(s) */ - if (!plural) - msg = g_strdup_printf (_("Are you sure you want\nto delete contact list (%s)?"), - name?name:""); - else - msg = g_strdup (_("Are you sure you want\nto delete these contact lists?")); - } - else { - /* contact(s) */ - if (!plural) - msg = g_strdup_printf (_("Are you sure you want\nto delete contact (%s)?"), - name?name:""); - else - msg = g_strdup (_("Are you sure you want\nto delete these contacts?")); - } - - dialog = gtk_message_dialog_new (parent, - 0, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - "%s", - msg); - g_free (msg); - - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT, - NULL); - - result = gtk_dialog_run(GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); - - return (result == GTK_RESPONSE_ACCEPT); -} - void -eab_editor_contact_added (EABEditor *editor, EBookStatus status, EContact *contact) +eab_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact) { g_return_if_fail (EAB_IS_EDITOR (editor)); g_return_if_fail (E_IS_CONTACT (contact)); - g_signal_emit (editor, editor_signals[CONTACT_ADDED], 0, - status, contact); + g_signal_emit (editor, signals[CONTACT_ADDED], 0, status, contact); } void -eab_editor_contact_modified (EABEditor *editor, EBookStatus status, EContact *contact) +eab_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact) { g_return_if_fail (EAB_IS_EDITOR (editor)); g_return_if_fail (E_IS_CONTACT (contact)); - g_signal_emit (editor, editor_signals[CONTACT_MODIFIED], 0, - status, contact); + g_signal_emit (editor, signals[CONTACT_MODIFIED], 0, status, contact); } void -eab_editor_contact_deleted (EABEditor *editor, EBookStatus status, EContact *contact) +eab_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact) { g_return_if_fail (EAB_IS_EDITOR (editor)); g_return_if_fail (E_IS_CONTACT (contact)); - g_signal_emit (editor, editor_signals[CONTACT_DELETED], 0, - status, contact); + g_signal_emit (editor, signals[CONTACT_DELETED], 0, status, contact); } void @@ -389,21 +417,5 @@ eab_editor_closed (EABEditor *editor) { g_return_if_fail (EAB_IS_EDITOR (editor)); - g_signal_emit (editor, editor_signals[EDITOR_CLOSED], 0); -} - -void -eab_editor_add (EABEditor *editor) -{ - g_return_if_fail (EAB_IS_EDITOR (editor)); - - all_editors = g_slist_prepend (all_editors, editor); -} - -void -eab_editor_remove (EABEditor *editor) -{ - g_return_if_fail (EAB_IS_EDITOR (editor)); - - all_editors = g_slist_remove (all_editors, editor); + g_signal_emit (editor, signals[EDITOR_CLOSED], 0); } diff --git a/addressbook/gui/contact-editor/eab-editor.h b/addressbook/gui/contact-editor/eab-editor.h index 6d70107643..f3803e7341 100644 --- a/addressbook/gui/contact-editor/eab-editor.h +++ b/addressbook/gui/contact-editor/eab-editor.h @@ -24,42 +24,42 @@ #ifndef __EAB_EDITOR_H__ #define __EAB_EDITOR_H__ -#include <bonobo/bonobo-ui-component.h> -#include <glade/glade.h> - +#include <gtk/gtk.h> #include <libebook/e-book.h> #include <libebook/e-contact.h> - -#include <gtk/gtk.h> +#include <shell/e-shell.h> + +/* Standard GObject macros */ +#define EAB_TYPE_EDITOR \ + (eab_editor_get_type ()) +#define EAB_EDITOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EAB_TYPE_EDITOR, EABEditor)) +#define EAB_EDITOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EAB_TYPE_EDITOR, EABEditorClass)) +#define EAB_IS_EDITOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EAB_TYPE_EDITOR)) +#define EAB_IS_EDITOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EAB_TYPE_EDITOR)) +#define EAB_EDITOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), EAB_EDITOR_TYPE, EABEditorClass)) G_BEGIN_DECLS -/* EABEditor - A dialog displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * -------------------------------------------------------------------------------- - * card ECard * RW The card currently being edited - */ - -#define EAB_TYPE_EDITOR (eab_editor_get_type ()) -#define EAB_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EAB_TYPE_EDITOR, EABEditor)) -#define EAB_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EAB_TYPE_EDITOR, EABEditorClass)) -#define EAB_IS_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EAB_TYPE_EDITOR)) -#define EAB_IS_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EAB_TYPE_EDITOR)) -#define EAB_EDITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EAB_EDITOR_TYPE, EABEditorClass)) - -typedef struct _EABEditor EABEditor; -typedef struct _EABEditorClass EABEditorClass; +typedef struct _EABEditor EABEditor; +typedef struct _EABEditorClass EABEditorClass; +typedef struct _EABEditorPrivate EABEditorPrivate; -struct _EABEditor -{ +struct _EABEditor { GObject parent; + EABEditorPrivate *priv; }; -struct _EABEditorClass -{ +struct _EABEditorClass { GObjectClass parent_class; /* virtual functions */ @@ -78,32 +78,35 @@ struct _EABEditorClass void (* editor_closed) (EABEditor *editor); }; -GType eab_editor_get_type (void); +GType eab_editor_get_type (void); +EShell * eab_editor_get_shell (EABEditor *editor); +GSList * eab_editor_get_all_editors (void); /* virtual functions */ -void eab_editor_show (EABEditor *editor); -void eab_editor_close (EABEditor *editor); -void eab_editor_raise (EABEditor *editor); -void eab_editor_save_contact (EABEditor *editor, gboolean should_close); -gboolean eab_editor_is_valid (EABEditor *editor); -gboolean eab_editor_is_changed (EABEditor *editor); -GtkWindow* eab_editor_get_window (EABEditor *editor); - -gboolean eab_editor_prompt_to_save_changes (EABEditor *editor, GtkWindow *window); -gboolean eab_editor_confirm_delete (GtkWindow *parent, gboolean plural, gboolean is_list, gchar *name); +void eab_editor_show (EABEditor *editor); +void eab_editor_close (EABEditor *editor); +void eab_editor_raise (EABEditor *editor); +void eab_editor_save_contact (EABEditor *editor, + gboolean should_close); +gboolean eab_editor_is_valid (EABEditor *editor); +gboolean eab_editor_is_changed (EABEditor *editor); +GtkWindow * eab_editor_get_window (EABEditor *editor); + +gboolean eab_editor_prompt_to_save_changes + (EABEditor *editor, + GtkWindow *window); /* these four generate EABEditor signals */ -void eab_editor_contact_added (EABEditor *editor, EBookStatus status, EContact *contact); -void eab_editor_contact_modified (EABEditor *editor, EBookStatus status, EContact *contact); -void eab_editor_contact_deleted (EABEditor *editor, EBookStatus status, EContact *contact); -void eab_editor_closed (EABEditor *editor); - -/* these maintain the global list of editors so we can prompt the user - if there are unsaved changes when they exit. */ -void eab_editor_add (EABEditor *editor); -void eab_editor_remove (EABEditor *editor); -gboolean eab_editor_request_close_all (void); -const GSList* eab_editor_get_all_editors (void); +void eab_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact); +void eab_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact); +void eab_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact); +void eab_editor_closed (EABEditor *editor); G_END_DECLS diff --git a/addressbook/gui/contact-list-editor/Makefile.am b/addressbook/gui/contact-list-editor/Makefile.am index 81aa679c07..608707395d 100644 --- a/addressbook/gui/contact-list-editor/Makefile.am +++ b/addressbook/gui/contact-list-editor/Makefile.am @@ -25,7 +25,6 @@ libecontactlisteditor_la_SOURCES = \ libecontactlisteditor_la_LDFLAGS = $(NO_UNDEFINED) libecontactlisteditor_la_LIBADD = \ - $(WIN32_BOOTSTRAP_LIBS) \ $(top_builddir)/addressbook/util/libeabutil.la \ $(top_builddir)/addressbook/gui/contact-editor/libecontacteditor.la \ $(top_builddir)/widgets/table/libetable.la \ diff --git a/addressbook/gui/contact-list-editor/e-contact-list-editor.c b/addressbook/gui/contact-list-editor/e-contact-list-editor.c index e62958a72e..77d91357c5 100644 --- a/addressbook/gui/contact-list-editor/e-contact-list-editor.c +++ b/addressbook/gui/contact-list-editor/e-contact-list-editor.c @@ -34,10 +34,8 @@ #include <libedataserverui/e-source-combo-box.h> -#include "shell/evolution-shell-component-utils.h" - -#include "addressbook/gui/component/addressbook.h" #include "addressbook/gui/widgets/eab-gui-util.h" +#include "addressbook/util/addressbook.h" #include "addressbook/util/eab-book-util.h" #include "eab-editor.h" @@ -883,6 +881,36 @@ contact_list_editor_create_name_selector (gchar *name, gint int1, gint int2); +static gpointer +contact_editor_fudge_new (EBook *book, + EContact *contact, + gboolean is_new, + gboolean editable) +{ + EShell *shell = e_shell_get_default (); + + /* XXX Putting this function signature in libedataserverui + * was a terrible idea. Now we're stuck with it. */ + + return e_contact_editor_new ( + shell, book, contact, is_new, editable); +} + +static gpointer +contact_list_editor_fudge_new (EBook *book, + EContact *contact, + gboolean is_new, + gboolean editable) +{ + EShell *shell = e_shell_get_default (); + + /* XXX Putting this function signature in libedataserverui + * was a terrible idea. Now we're stuck with it. */ + + return e_contact_list_editor_new ( + shell, book, contact, is_new, editable); +} + GtkWidget * contact_list_editor_create_name_selector (gchar *name, gchar *string1, @@ -903,9 +931,9 @@ contact_list_editor_create_name_selector (gchar *name, name_selector, "Members"); e_name_selector_entry_set_contact_editor_func ( - name_selector_entry, e_contact_editor_new); + name_selector_entry, contact_editor_fudge_new); e_name_selector_entry_set_contact_list_editor_func ( - name_selector_entry, e_contact_list_editor_new); + name_selector_entry, contact_list_editor_fudge_new); gtk_widget_show (GTK_WIDGET (name_selector_entry)); g_signal_connect ( @@ -924,87 +952,6 @@ contact_list_editor_create_name_selector (gchar *name, return GTK_WIDGET (name_selector_entry); } -/**************************** EABEditor Callbacks ****************************/ - -static void -contact_list_editor_show (EABEditor *editor) -{ - gtk_widget_show (WIDGET (DIALOG)); -} - -static void -contact_list_editor_close (EABEditor *editor) -{ - gtk_widget_destroy (WIDGET (DIALOG)); - eab_editor_closed (editor); -} - -static void -contact_list_editor_raise (EABEditor *editor) -{ - gdk_window_raise (WIDGET (DIALOG)->window); -} - -static void -contact_list_editor_save_contact (EABEditor *eab_editor, - gboolean should_close) -{ - EContactListEditor *editor = E_CONTACT_LIST_EDITOR (eab_editor); - EContactListEditorPrivate *priv = editor->priv; - EditorCloseStruct *ecs; - EContact *contact; - - contact = e_contact_list_editor_get_contact (editor); - - if (priv->book == NULL) - return; - - ecs = g_new (EditorCloseStruct, 1); - ecs->editor = g_object_ref (editor); - ecs->should_close = should_close; - - gtk_widget_set_sensitive (WIDGET (DIALOG), FALSE); - priv->in_async_call = TRUE; - - if (priv->is_new_list) - eab_merging_book_add_contact ( - priv->book, contact, (EBookIdCallback) - contact_list_editor_list_added_cb, ecs); - else - eab_merging_book_commit_contact ( - priv->book, contact, (EBookCallback) - contact_list_editor_list_modified_cb, ecs); - - priv->changed = FALSE; -} - -static gboolean -contact_list_editor_is_valid (EABEditor *editor) -{ - GtkEditable *editable; - gboolean valid; - gchar *chars; - - editable = GTK_EDITABLE (WIDGET (LIST_NAME_ENTRY)); - chars = gtk_editable_get_chars (editable, 0, -1); - valid = (chars != NULL && *chars != '\0'); - g_free (chars); - - return valid; -} - -static gboolean -contact_list_editor_is_changed (EABEditor *editor) -{ - return E_CONTACT_LIST_EDITOR_GET_PRIVATE (editor)->changed; -} - -static GtkWindow* -contact_list_editor_get_window (EABEditor *editor) -{ - return GTK_WINDOW (WIDGET (DIALOG)); -} - /***************************** GObject Callbacks *****************************/ static GObject * @@ -1114,6 +1061,135 @@ contact_list_editor_dispose (GObject *object) G_OBJECT_CLASS (parent_class)->dispose (object); } +/**************************** EABEditor Callbacks ****************************/ + +static void +contact_list_editor_show (EABEditor *editor) +{ + gtk_widget_show (WIDGET (DIALOG)); +} + +static void +contact_list_editor_close (EABEditor *editor) +{ + gtk_widget_destroy (WIDGET (DIALOG)); + eab_editor_closed (editor); +} + +static void +contact_list_editor_raise (EABEditor *editor) +{ + gdk_window_raise (WIDGET (DIALOG)->window); +} + +static void +contact_list_editor_save_contact (EABEditor *eab_editor, + gboolean should_close) +{ + EContactListEditor *editor = E_CONTACT_LIST_EDITOR (eab_editor); + EContactListEditorPrivate *priv = editor->priv; + EditorCloseStruct *ecs; + EContact *contact; + + contact = e_contact_list_editor_get_contact (editor); + + if (priv->book == NULL) + return; + + ecs = g_new (EditorCloseStruct, 1); + ecs->editor = g_object_ref (editor); + ecs->should_close = should_close; + + gtk_widget_set_sensitive (WIDGET (DIALOG), FALSE); + priv->in_async_call = TRUE; + + if (priv->is_new_list) + eab_merging_book_add_contact ( + priv->book, contact, (EBookIdCallback) + contact_list_editor_list_added_cb, ecs); + else + eab_merging_book_commit_contact ( + priv->book, contact, (EBookCallback) + contact_list_editor_list_modified_cb, ecs); + + priv->changed = FALSE; +} + +static gboolean +contact_list_editor_is_valid (EABEditor *editor) +{ + GtkEditable *editable; + gboolean valid; + gchar *chars; + + editable = GTK_EDITABLE (WIDGET (LIST_NAME_ENTRY)); + chars = gtk_editable_get_chars (editable, 0, -1); + valid = (chars != NULL && *chars != '\0'); + g_free (chars); + + return valid; +} + +static gboolean +contact_list_editor_is_changed (EABEditor *editor) +{ + return E_CONTACT_LIST_EDITOR_GET_PRIVATE (editor)->changed; +} + +static GtkWindow * +contact_list_editor_get_window (EABEditor *editor) +{ + return GTK_WINDOW (WIDGET (DIALOG)); +} + +static void +contact_list_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error adding list"), status); +} + +static void +contact_list_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error modifying list"), status); +} + +static void +contact_list_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact) +{ + if (status == E_BOOK_ERROR_OK) + return; + + if (status == E_BOOK_ERROR_CANCELLED) + return; + + eab_error_dialog (_("Error removing list"), status); +} + +static void +contact_list_editor_closed (EABEditor *editor) +{ + g_object_unref (editor); +} + /****************************** GType Callbacks ******************************/ static void @@ -1139,6 +1215,10 @@ contact_list_editor_class_init (EContactListEditorClass *class) editor_class->is_valid = contact_list_editor_is_valid; editor_class->is_changed = contact_list_editor_is_changed; editor_class->get_window = contact_list_editor_get_window; + editor_class->contact_added = contact_list_editor_contact_added; + editor_class->contact_modified = contact_list_editor_contact_modified; + editor_class->contact_deleted = contact_list_editor_contact_deleted; + editor_class->editor_closed = contact_list_editor_closed; g_object_class_install_property ( object_class, @@ -1269,26 +1349,20 @@ e_contact_list_editor_get_type (void) return type; } -static void -contact_list_editor_destroy_notify (gpointer data, - GObject *where_the_object_was) -{ - eab_editor_remove (EAB_EDITOR (data)); -} - -EContactListEditor * -e_contact_list_editor_new (EBook *book, - EContact *list_contact, - gboolean is_new_list, - gboolean editable) +EABEditor * +e_contact_list_editor_new (EShell *shell, + EBook *book, + EContact *list_contact, + gboolean is_new_list, + gboolean editable) { - EContactListEditor *editor; + EABEditor *editor; - editor = g_object_new (E_TYPE_CONTACT_LIST_EDITOR, NULL); + g_return_val_if_fail (E_IS_SHELL (shell), NULL); - eab_editor_add (EAB_EDITOR (editor)); - g_object_weak_ref ( - G_OBJECT (editor), contact_list_editor_destroy_notify, editor); + editor = g_object_new ( + E_TYPE_CONTACT_LIST_EDITOR, + "shell", shell, NULL); g_object_set (editor, "book", book, diff --git a/addressbook/gui/contact-list-editor/e-contact-list-editor.h b/addressbook/gui/contact-list-editor/e-contact-list-editor.h index fcee0b02ef..8e258597aa 100644 --- a/addressbook/gui/contact-list-editor/e-contact-list-editor.h +++ b/addressbook/gui/contact-list-editor/e-contact-list-editor.h @@ -68,7 +68,8 @@ struct _EContactListEditorClass }; GType e_contact_list_editor_get_type (void); -EContactListEditor * e_contact_list_editor_new (EBook *book, +EABEditor * e_contact_list_editor_new (EShell *shell, + EBook *book, EContact *list_contact, gboolean is_new_list, gboolean editable); diff --git a/addressbook/gui/merging/eab-contact-compare.c b/addressbook/gui/merging/eab-contact-compare.c index 236c6acd0c..86ed4e9de6 100644 --- a/addressbook/gui/merging/eab-contact-compare.c +++ b/addressbook/gui/merging/eab-contact-compare.c @@ -24,8 +24,8 @@ #include <config.h> #include <ctype.h> #include <string.h> -#include "util/eab-book-util.h" -#include "../component/addressbook.h" +#include "addressbook/util/addressbook.h" +#include "addressbook/util/eab-book-util.h" #include "eab-contact-compare.h" /* This is an "optimistic" combiner: the best of the two outcomes is diff --git a/addressbook/gui/merging/eab-contact-merging.c b/addressbook/gui/merging/eab-contact-merging.c index aabea67bdb..b927918d22 100644 --- a/addressbook/gui/merging/eab-contact-merging.c +++ b/addressbook/gui/merging/eab-contact-merging.c @@ -471,12 +471,18 @@ match_query_callback (EContact *contact, EContact *match, EABContactMatchType ty } widget = glade_xml_get_widget (ui, "custom-old-contact"); - eab_contact_display_render (EAB_CONTACT_DISPLAY (widget), - match, EAB_CONTACT_DISPLAY_RENDER_COMPACT); + eab_contact_display_set_mode ( + EAB_CONTACT_DISPLAY (widget), + EAB_CONTACT_DISPLAY_RENDER_COMPACT); + eab_contact_display_set_contact ( + EAB_CONTACT_DISPLAY (widget), match); widget = glade_xml_get_widget (ui, "custom-new-contact"); - eab_contact_display_render (EAB_CONTACT_DISPLAY (widget), - contact, EAB_CONTACT_DISPLAY_RENDER_COMPACT); + eab_contact_display_set_mode ( + EAB_CONTACT_DISPLAY (widget), + EAB_CONTACT_DISPLAY_RENDER_COMPACT); + eab_contact_display_set_contact ( + EAB_CONTACT_DISPLAY (widget), contact); widget = glade_xml_get_widget (ui, "dialog-duplicate-contact"); diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index dd4bacf276..58d1e1b1d1 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -7,11 +7,11 @@ AM_CPPFLAGS = \ -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ -DSEARCH_RULE_DIR=\"$(ruledir)\" \ -I$(top_srcdir) \ + -I$(top_srcdir)/filter \ -I$(top_srcdir)/widgets \ -I$(top_srcdir)/addressbook \ - -I$(top_srcdir)/addressbook/gui/contact-editor \ -I$(top_srcdir)/addressbook/gui/merging \ - -I$(top_srcdir)/addressbook/gui/component \ + -I$(top_srcdir)/addressbook/util \ -I$(top_srcdir)/widgets/misc \ -I$(top_builddir)/shell \ $(EVOLUTION_ADDRESSBOOK_CFLAGS) @@ -22,9 +22,7 @@ noinst_LTLIBRARIES = \ eabincludedir = $(privincludedir)/addressbook/gui/widgets eabinclude_HEADERS = \ - eab-config.h \ - eab-menu.h \ - eab-popup.h + eab-config.h libeabwidgets_la_SOURCES = \ eab-config.c \ @@ -32,11 +30,6 @@ libeabwidgets_la_SOURCES = \ eab-contact-display.h \ eab-gui-util.c \ eab-gui-util.h \ - eab-menu.c \ - eab-popup.c \ - eab-popup.h \ - eab-popup-control.c \ - eab-popup-control.h \ e-minicard.c \ e-minicard.h \ e-minicard-label.c \ @@ -51,12 +44,29 @@ libeabwidgets_la_SOURCES = \ e-addressbook-table-adapter.h \ e-addressbook-model.c \ e-addressbook-model.h \ + e-addressbook-selector.c \ + e-addressbook-selector.h \ e-addressbook-view.c \ e-addressbook-view.h \ gal-view-minicard.c \ gal-view-minicard.h \ gal-view-factory-minicard.c \ - gal-view-factory-minicard.h + gal-view-factory-minicard.h \ + ea-minicard.c \ + ea-minicard.h \ + ea-minicard-view.c \ + ea-minicard-view.h \ + ea-addressbook-view.c \ + ea-addressbook-view.h \ + ea-addressbook.c \ + ea-addressbook.h + +libeabwidgets_la_LIBADD = \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/shell/libeshell.la \ + $(top_builddir)/widgets/table/libetable.la \ + $(top_builddir)/widgets/menus/libmenus.la \ + $(top_builddir)/a11y/libevolution-a11y.la dist-hook: cd $(distdir); rm -f $(BUILT_SOURCES) @@ -65,6 +75,6 @@ etspec_DATA= e-addressbook-view.etspec EXTRA_DIST = \ $(etspec_DATA) \ - addresstypes.xml + $(rule_DATA) -include $(top_srcdir)/git.mk diff --git a/addressbook/gui/widgets/e-addressbook-model.c b/addressbook/gui/widgets/e-addressbook-model.c index 786c4d994d..71de495f13 100644 --- a/addressbook/gui/widgets/e-addressbook-model.c +++ b/addressbook/gui/widgets/e-addressbook-model.c @@ -22,31 +22,45 @@ #include <config.h> #include <string.h> -#include <gtk/gtk.h> #include <glib/gi18n.h> -#include "e-util/e-util.h" #include "e-addressbook-model.h" -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/xmlmemory.h> +#include <e-util/e-util.h> #include <misc/e-gui-utils.h> #include "eab-gui-util.h" -#define PARENT_TYPE G_TYPE_OBJECT -static GObjectClass *parent_class; - -/* - * EABModel callbacks - * These are the callbacks that define the behavior of our custom model. - */ -static void eab_model_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static void eab_model_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +#define E_ADDRESSBOOK_MODEL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelPrivate)) + +struct _EAddressbookModelPrivate { + EBook *book; + EBookQuery *query; + EBookView *book_view; + guint book_view_idle_id; + + /* Query Results */ + GPtrArray *contacts; + + /* Signal Handler IDs */ + gulong create_contact_id; + gulong remove_contact_id; + gulong modify_contact_id; + gulong status_message_id; + gulong writable_status_id; + gulong sequence_complete_id; + gulong backend_died_id; + + guint search_in_progress : 1; + guint editable : 1; + guint editable_set : 1; + guint first_get_view : 1; +}; enum { PROP_0, PROP_BOOK, - PROP_QUERY, - PROP_EDITABLE + PROP_EDITABLE, + PROP_QUERY }; enum { @@ -64,672 +78,799 @@ enum { LAST_SIGNAL }; -static guint eab_model_signals [LAST_SIGNAL] = {0, }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static void -free_data (EABModel *model) +free_data (EAddressbookModel *model) { - if (model->data) { - gint i; - - for ( i = 0; i < model->data_count; i++ ) { - g_object_unref (model->data[i]); - } - - g_free(model->data); - model->data = NULL; - model->data_count = 0; - model->allocated_count = 0; - } -} + GPtrArray *array; -static void -remove_book_view(EABModel *model) -{ - if (model->book_view && model->create_contact_id) - g_signal_handler_disconnect (model->book_view, - model->create_contact_id); - if (model->book_view && model->remove_contact_id) - g_signal_handler_disconnect (model->book_view, - model->remove_contact_id); - if (model->book_view && model->modify_contact_id) - g_signal_handler_disconnect (model->book_view, - model->modify_contact_id); - if (model->book_view && model->status_message_id) - g_signal_handler_disconnect (model->book_view, - model->status_message_id); - if (model->book_view && model->sequence_complete_id) - g_signal_handler_disconnect (model->book_view, - model->sequence_complete_id); - - model->create_contact_id = 0; - model->remove_contact_id = 0; - model->modify_contact_id = 0; - model->status_message_id = 0; - model->sequence_complete_id = 0; - - model->search_in_progress = FALSE; - - if (model->book_view) { - e_book_view_stop (model->book_view); - g_object_unref (model->book_view); - model->book_view = NULL; - } + array = model->priv->contacts; + g_ptr_array_foreach (array, (GFunc) g_object_unref, NULL); + g_ptr_array_set_size (array, 0); } static void -addressbook_dispose(GObject *object) +remove_book_view(EAddressbookModel *model) { - EABModel *model = EAB_MODEL(object); - - remove_book_view(model); - free_data (model); - - if (model->book) { - if (model->writable_status_id) - g_signal_handler_disconnect (model->book, - model->writable_status_id); - model->writable_status_id = 0; - - if (model->backend_died_id) - g_signal_handler_disconnect (model->book, - model->backend_died_id); - model->backend_died_id = 0; - - g_object_unref (model->book); - model->book = NULL; - } - - if (model->query) { - e_book_query_unref (model->query); - model->query = NULL; + if (model->priv->book_view && model->priv->create_contact_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->create_contact_id); + if (model->priv->book_view && model->priv->remove_contact_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->remove_contact_id); + if (model->priv->book_view && model->priv->modify_contact_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->modify_contact_id); + if (model->priv->book_view && model->priv->status_message_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->status_message_id); + if (model->priv->book_view && model->priv->sequence_complete_id) + g_signal_handler_disconnect ( + model->priv->book_view, + model->priv->sequence_complete_id); + + model->priv->create_contact_id = 0; + model->priv->remove_contact_id = 0; + model->priv->modify_contact_id = 0; + model->priv->status_message_id = 0; + model->priv->sequence_complete_id = 0; + + model->priv->search_in_progress = FALSE; + + if (model->priv->book_view) { + e_book_view_stop (model->priv->book_view); + g_object_unref (model->priv->book_view); + model->priv->book_view = NULL; } - - if (G_OBJECT_CLASS(parent_class)->dispose) - G_OBJECT_CLASS(parent_class)->dispose(object); } static void -update_folder_bar_message (EABModel *model) +update_folder_bar_message (EAddressbookModel *model) { - gint count; + guint count; gchar *message; - count = model->data_count; + count = model->priv->contacts->len; switch (count) { case 0: message = g_strdup (_("No contacts")); break; default: - message = g_strdup_printf (ngettext("%d contact", "%d contacts", count), count); + message = g_strdup_printf ( + ngettext ("%d contact", "%d contacts", count), count); break; } - g_signal_emit (model, - eab_model_signals [FOLDER_BAR_MESSAGE], 0, - message); + g_signal_emit (model, signals[FOLDER_BAR_MESSAGE], 0, message); g_free (message); } static void -create_contact(EBookView *book_view, - const GList *contacts, - EABModel *model) +create_contact (EBookView *book_view, + const GList *contact_list, + EAddressbookModel *model) { - gint old_count = model->data_count; - gint length = g_list_length ((GList *)contacts); + GPtrArray *array; + guint count; + guint index; - if (model->data_count + length > model->allocated_count) { - while (model->data_count + length > model->allocated_count) - model->allocated_count = model->allocated_count * 2 + 1; - model->data = g_renew(EContact *, model->data, model->allocated_count); - } + array = model->priv->contacts; + index = array->len; + count = g_list_length ((GList *) contact_list); - for (; contacts; contacts = contacts->next) { - model->data[model->data_count++] = contacts->data; - g_object_ref (contacts->data); - } + while (contact_list != NULL) { + EContact *contact = contact_list->data; - g_signal_emit (model, - eab_model_signals [CONTACT_ADDED], 0, - old_count, model->data_count - old_count); + g_ptr_array_add (array, g_object_ref (contact)); + contact_list = contact_list->next; + } + g_signal_emit (model, signals[CONTACT_ADDED], 0, index, count); update_folder_bar_message (model); } static void remove_contact(EBookView *book_view, GList *ids, - EABModel *model) + EAddressbookModel *model) { /* XXX we should keep a hash around instead of this O(n*m) loop */ - gint i = 0; - GList *l; + GList *iter; GArray *indices; + GPtrArray *array; + gint ii; + array = model->priv->contacts; indices = g_array_new (FALSE, FALSE, sizeof (gint)); - for (l = ids; l; l = l->next) { - gchar *id = l->data; - for ( i = 0; i < model->data_count; i++) { - if ( !strcmp(e_contact_get_const (model->data[i], E_CONTACT_UID), id) ) { - g_object_unref (model->data[i]); - memmove(model->data + i, model->data + i + 1, (model->data_count - i - 1) * sizeof (EContact *)); - model->data_count--; - g_array_append_val (indices, i); - break; + + for (iter = ids; iter != NULL; iter = iter->next) { + const gchar *target_uid = iter->data; + + for (ii = 0; ii < array->len; ii++) { + EContact *contact; + const gchar *uid; + + contact = array->pdata[ii]; + uid = e_contact_get_const (contact, E_CONTACT_UID); + if (strcmp (uid, target_uid) == 0) { + g_object_unref (contact); + g_array_append_val (indices, ii); } } } - g_signal_emit (model, - eab_model_signals [CONTACTS_REMOVED], 0, - indices); + + for (ii = 0; ii < indices->len; ii++) { + gint index; + + index = g_array_index (indices, gint, ii); + g_ptr_array_remove_index (array, index); + } + + g_signal_emit (model, signals[CONTACTS_REMOVED], 0, indices); g_array_free (indices, FALSE); + update_folder_bar_message (model); } static void modify_contact(EBookView *book_view, - const GList *contacts, - EABModel *model) -{ - for (; contacts; contacts = contacts->next) { - gint i; - for ( i = 0; i < model->data_count; i++) { - if ( !strcmp(e_contact_get_const(model->data[i], E_CONTACT_UID), - e_contact_get_const(E_CONTACT(contacts->data), E_CONTACT_UID)) ) { - g_object_unref (model->data[i]); - model->data[i] = e_contact_duplicate(E_CONTACT(contacts->data)); - g_signal_emit (model, - eab_model_signals [CONTACT_CHANGED], 0, - i); - break; - } + const GList *contact_list, + EAddressbookModel *model) +{ + GPtrArray *array; + + array = model->priv->contacts; + + while (contact_list != NULL) { + EContact *contact = contact_list->data; + const gchar *target_uid; + gint ii; + + target_uid = e_contact_get_const (contact, E_CONTACT_UID); + + for (ii = 0; ii < array->len; ii++) { + const gchar *uid; + + uid = e_contact_get_const ( + array->pdata[ii], E_CONTACT_UID); + + if (strcmp (uid, target_uid) != 0) + continue; + + g_object_unref (array->pdata[ii]); + contact = e_contact_duplicate (contact); + array->pdata[ii] = contact; + + g_signal_emit ( + model, signals[CONTACT_CHANGED], 0, ii); + break; } + + contact_list = contact_list->next; } } static void status_message (EBookView *book_view, gchar * status, - EABModel *model) + EAddressbookModel *model) { - g_signal_emit (model, - eab_model_signals [STATUS_MESSAGE], 0, - status); + g_signal_emit (model, signals[STATUS_MESSAGE], 0, status); } static void sequence_complete (EBookView *book_view, - EBookViewStatus status, - EABModel *model) + EBookViewStatus status, + EAddressbookModel *model) { - model->search_in_progress = FALSE; + model->priv->search_in_progress = FALSE; status_message (book_view, NULL, model); - g_signal_emit (model, - eab_model_signals [SEARCH_RESULT], 0, - status); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); + g_signal_emit (model, signals[SEARCH_RESULT], 0, status); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); } static void writable_status (EBook *book, gboolean writable, - EABModel *model) + EAddressbookModel *model) { - if (!model->editable_set) { - model->editable = writable; + if (!model->priv->editable_set) { + model->priv->editable = writable; - g_signal_emit (model, - eab_model_signals [WRITABLE_STATUS], 0, - writable); + g_signal_emit (model, signals[WRITABLE_STATUS], 0, writable); } } static void backend_died (EBook *book, - EABModel *model) + EAddressbookModel *model) +{ + g_signal_emit (model, signals[BACKEND_DIED], 0); +} + +static void +book_view_loaded (EBook *book, + EBookStatus status, + EBookView *book_view, + gpointer closure) +{ + EAddressbookModel *model = closure; + + if (status != E_BOOK_ERROR_OK) { + eab_error_dialog (_("Error getting book view"), status); + return; + } + + remove_book_view (model); + free_data (model); + + model->priv->book_view = book_view; + if (model->priv->book_view) + g_object_ref (model->priv->book_view); + + model->priv->create_contact_id = g_signal_connect ( + model->priv->book_view, "contacts-added", + G_CALLBACK (create_contact), model); + model->priv->remove_contact_id = g_signal_connect ( + model->priv->book_view, "contacts-removed", + G_CALLBACK (remove_contact), model); + model->priv->modify_contact_id = g_signal_connect ( + model->priv->book_view, "contacts-changed", + G_CALLBACK (modify_contact), model); + model->priv->status_message_id = g_signal_connect ( + model->priv->book_view, "status-message", + G_CALLBACK (status_message), model); + model->priv->sequence_complete_id = g_signal_connect ( + model->priv->book_view, "sequence-complete", + G_CALLBACK (sequence_complete), model); + + model->priv->search_in_progress = TRUE; + g_signal_emit (model, signals[MODEL_CHANGED], 0); + g_signal_emit (model, signals[SEARCH_STARTED], 0); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); + + e_book_view_start (model->priv->book_view); +} + +static gboolean +addressbook_model_idle_cb (EAddressbookModel *model) +{ + model->priv->book_view_idle_id = 0; + + if (model->priv->book && model->priv->query) { + ESource *source; + const gchar *limit_str; + gint limit = -1; + + source = e_book_get_source (model->priv->book); + + limit_str = e_source_get_property (source, "limit"); + if (limit_str && *limit_str) + limit = atoi (limit_str); + + remove_book_view(model); + + if (model->priv->first_get_view) { + model->priv->first_get_view = FALSE; + + if (e_book_check_static_capability (model->priv->book, "do-initial-query")) { + e_book_async_get_book_view ( + model->priv->book, model->priv->query, + NULL, limit, book_view_loaded, model); + } else { + free_data (model); + + g_signal_emit (model, + signals[MODEL_CHANGED], 0); + g_signal_emit (model, + signals[STOP_STATE_CHANGED], 0); + } + } else + e_book_async_get_book_view ( + model->priv->book, model->priv->query, + NULL, limit, book_view_loaded, model); + + } + + g_object_unref (model); + + return FALSE; +} + +static void +addressbook_model_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BOOK: + e_addressbook_model_set_book ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_object (value)); + return; + + case PROP_EDITABLE: + e_addressbook_model_set_editable ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_boolean (value)); + return; + + case PROP_QUERY: + e_addressbook_model_set_query ( + E_ADDRESSBOOK_MODEL (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + +} + +static void +addressbook_model_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_BOOK: + g_value_set_object ( + value, e_addressbook_model_get_book ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_EDITABLE: + g_value_set_boolean ( + value, e_addressbook_model_get_editable ( + E_ADDRESSBOOK_MODEL (object))); + return; + + case PROP_QUERY: + g_value_take_string ( + value, e_addressbook_model_get_query ( + E_ADDRESSBOOK_MODEL (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_model_dispose (GObject *object) +{ + EAddressbookModel *model = E_ADDRESSBOOK_MODEL(object); + + remove_book_view (model); + free_data (model); + + if (model->priv->book) { + if (model->priv->writable_status_id) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->writable_status_id); + model->priv->writable_status_id = 0; + + if (model->priv->backend_died_id) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->backend_died_id); + model->priv->backend_died_id = 0; + + g_object_unref (model->priv->book); + model->priv->book = NULL; + } + + if (model->priv->query) { + e_book_query_unref (model->priv->query); + model->priv->query = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +addressbook_model_finalize (GObject *object) { - g_signal_emit (model, - eab_model_signals [BACKEND_DIED], 0); + EAddressbookModelPrivate *priv; + + priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (object); + + g_ptr_array_free (priv->contacts, TRUE); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -eab_model_class_init (GObjectClass *object_class) -{ - parent_class = g_type_class_ref (PARENT_TYPE); - - object_class->dispose = addressbook_dispose; - object_class->set_property = eab_model_set_property; - object_class->get_property = eab_model_get_property; - - g_object_class_install_property (object_class, PROP_BOOK, - g_param_spec_object ("book", - _("Book"), - /*_( */"XXX blurb" /*)*/, - E_TYPE_BOOK, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_QUERY, - g_param_spec_string ("query", - _("Query"), - /*_( */"XXX blurb" /*)*/, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_EDITABLE, - g_param_spec_boolean ("editable", - _("Editable"), - /*_( */"XXX blurb" /*)*/, - FALSE, - G_PARAM_READWRITE)); - - eab_model_signals [WRITABLE_STATUS] = +addressbook_model_class_init (EAddressbookModelClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookModelPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_model_set_property; + object_class->get_property = addressbook_model_get_property; + object_class->dispose = addressbook_model_dispose; + object_class->finalize = addressbook_model_finalize; + + g_object_class_install_property ( + object_class, + PROP_BOOK, + g_param_spec_object ( + "book", + _("Book"), + NULL, + E_TYPE_BOOK, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_EDITABLE, + g_param_spec_boolean ( + "editable", + _("Editable"), + NULL, + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_QUERY, + g_param_spec_string ( + "query", + _("Query"), + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[WRITABLE_STATUS] = g_signal_new ("writable_status", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, writable_status), + G_STRUCT_OFFSET (EAddressbookModelClass, writable_status), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - eab_model_signals [STATUS_MESSAGE] = + signals[STATUS_MESSAGE] = g_signal_new ("status_message", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, status_message), + G_STRUCT_OFFSET (EAddressbookModelClass, status_message), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - eab_model_signals [SEARCH_STARTED] = + signals[SEARCH_STARTED] = g_signal_new ("search_started", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, search_started), + G_STRUCT_OFFSET (EAddressbookModelClass, search_started), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - eab_model_signals [SEARCH_RESULT] = + signals[SEARCH_RESULT] = g_signal_new ("search_result", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, search_result), + G_STRUCT_OFFSET (EAddressbookModelClass, search_result), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - eab_model_signals [FOLDER_BAR_MESSAGE] = + signals[FOLDER_BAR_MESSAGE] = g_signal_new ("folder_bar_message", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, folder_bar_message), + G_STRUCT_OFFSET (EAddressbookModelClass, folder_bar_message), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - eab_model_signals [CONTACT_ADDED] = + signals[CONTACT_ADDED] = g_signal_new ("contact_added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, contact_added), + G_STRUCT_OFFSET (EAddressbookModelClass, contact_added), NULL, NULL, e_marshal_NONE__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); - eab_model_signals [CONTACTS_REMOVED] = + signals[CONTACTS_REMOVED] = g_signal_new ("contacts_removed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, contacts_removed), + G_STRUCT_OFFSET (EAddressbookModelClass, contacts_removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); - eab_model_signals [CONTACT_CHANGED] = + signals[CONTACT_CHANGED] = g_signal_new ("contact_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, contact_changed), + G_STRUCT_OFFSET (EAddressbookModelClass, contact_changed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - eab_model_signals [MODEL_CHANGED] = + signals[MODEL_CHANGED] = g_signal_new ("model_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, model_changed), + G_STRUCT_OFFSET (EAddressbookModelClass, model_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - eab_model_signals [STOP_STATE_CHANGED] = + signals[STOP_STATE_CHANGED] = g_signal_new ("stop_state_changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, stop_state_changed), + G_STRUCT_OFFSET (EAddressbookModelClass, stop_state_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - eab_model_signals [BACKEND_DIED] = + signals[BACKEND_DIED] = g_signal_new ("backend_died", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABModelClass, backend_died), + G_STRUCT_OFFSET (EAddressbookModelClass, backend_died), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void -eab_model_init (GObject *object) -{ - EABModel *model = EAB_MODEL(object); - model->book = NULL; - model->query = e_book_query_any_field_contains (""); - model->book_view = NULL; - model->create_contact_id = 0; - model->remove_contact_id = 0; - model->modify_contact_id = 0; - model->status_message_id = 0; - model->writable_status_id = 0; - model->backend_died_id = 0; - model->sequence_complete_id = 0; - model->data = NULL; - model->data_count = 0; - model->allocated_count = 0; - model->search_in_progress = FALSE; - model->editable = FALSE; - model->editable_set = FALSE; - model->first_get_view = TRUE; +addressbook_model_init (EAddressbookModel *model) +{ + model->priv = E_ADDRESSBOOK_MODEL_GET_PRIVATE (model); + + model->priv->contacts = g_ptr_array_new (); + model->priv->first_get_view = TRUE; } -static void -book_view_loaded (EBook *book, EBookStatus status, EBookView *book_view, gpointer closure) +GType +e_addressbook_model_get_type (void) { - EABModel *model = closure; + static GType type = 0; - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (_("Error getting book view"), status); - return; + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAddressbookModelClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_model_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookModel), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_model_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EAddressbookModel", &type_info, 0); } - remove_book_view (model); - free_data (model); + return type; +} - model->book_view = book_view; - if (model->book_view) - g_object_ref (model->book_view); - model->create_contact_id = g_signal_connect(model->book_view, - "contacts_added", - G_CALLBACK (create_contact), - model); - model->remove_contact_id = g_signal_connect(model->book_view, - "contacts_removed", - G_CALLBACK (remove_contact), - model); - model->modify_contact_id = g_signal_connect(model->book_view, - "contacts_changed", - G_CALLBACK(modify_contact), - model); - model->status_message_id = g_signal_connect(model->book_view, - "status_message", - G_CALLBACK(status_message), - model); - model->sequence_complete_id = g_signal_connect(model->book_view, - "sequence_complete", - G_CALLBACK(sequence_complete), - model); - - model->search_in_progress = TRUE; - g_signal_emit (model, - eab_model_signals [MODEL_CHANGED], 0); - g_signal_emit (model, - eab_model_signals [SEARCH_STARTED], 0); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); - - e_book_view_start (model->book_view); +EAddressbookModel* +e_addressbook_model_new (void) +{ + return g_object_new (E_TYPE_ADDRESSBOOK_MODEL, NULL); } -static void -get_view (EABModel *model) +EContact * +e_addressbook_model_get_contact (EAddressbookModel *model, + gint row) { - /* Should this be checked somehow? */ - gboolean success; + GPtrArray *array; - if (model->book && model->query) { - ESource *source; - const gchar *limit_str; - gint limit = -1; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); - source = e_book_get_source (model->book); + array = model->priv->contacts; - limit_str = e_source_get_property (source, "limit"); - if (limit_str && *limit_str) - limit = atoi (limit_str); + if (0 <= row && row < array->len) + return e_contact_duplicate (array->pdata[row]); - remove_book_view(model); + return NULL; +} - if (model->first_get_view) { - model->first_get_view = FALSE; +void +e_addressbook_model_stop (EAddressbookModel *model) +{ + const gchar *message; - if (e_book_check_static_capability (model->book, "do-initial-query")) { - success = e_book_async_get_book_view (model->book, model->query, NULL, limit, book_view_loaded, model); - } else { - free_data (model); + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); - g_signal_emit (model, - eab_model_signals [MODEL_CHANGED], 0); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); - return; - } - } - else - success = e_book_async_get_book_view (model->book, model->query, NULL, limit, book_view_loaded, model); + remove_book_view (model); - } + message = _("Search Interrupted"); + g_signal_emit (model, signals[STOP_STATE_CHANGED], 0); + g_signal_emit (model, signals[STATUS_MESSAGE], 0, message); } -static gboolean -get_view_idle (EABModel *model) +gboolean +e_addressbook_model_can_stop (EAddressbookModel *model) { - model->book_view_idle_id = 0; - get_view (model); - g_object_unref (model); - return FALSE; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + + return model->priv->search_in_progress; } -EContact * -eab_model_get_contact(EABModel *model, - gint row) +void +e_addressbook_model_force_folder_bar_message (EAddressbookModel *model) { - if (model->data && 0 <= row && row < model->data_count) { - return e_contact_duplicate (model->data[row]); - } - return NULL; + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + update_folder_bar_message (model); } -static void -eab_model_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +gint +e_addressbook_model_contact_count (EAddressbookModel *model) { - EABModel *model; - gboolean need_get_book_view = FALSE; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), 0); - model = EAB_MODEL (object); + return model->priv->contacts->len; +} - switch (prop_id) { - case PROP_BOOK: - if (model->book) { - if (model->writable_status_id) - g_signal_handler_disconnect (model->book, - model->writable_status_id); - model->writable_status_id = 0; +EContact * +e_addressbook_model_contact_at (EAddressbookModel *model, + gint index) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); - if (model->backend_died_id) - g_signal_handler_disconnect (model->book, - model->backend_died_id); - model->backend_died_id = 0; + return model->priv->contacts->pdata[index]; +} - g_object_unref (model->book); - } - model->book = E_BOOK(g_value_get_object (value)); - if (model->book) { - model->writable_status_id = - g_signal_connect (model->book, - "writable_status", - G_CALLBACK (writable_status), model); - model->backend_died_id = - g_signal_connect (model->book, - "backend_died", - G_CALLBACK (backend_died), model); - - if (!model->editable_set) { - model->editable = e_book_is_writable (model->book); +gint +e_addressbook_model_find (EAddressbookModel *model, + EContact *contact) +{ + GPtrArray *array; + gint ii; - g_signal_emit (model, - eab_model_signals [WRITABLE_STATUS], 0, - model->editable); - } + /* XXX This searches for a particular EContact instance, + * as opposed to an equivalent but possibly different + * EContact instance. Might have to revise this in + * the future. */ - model->first_get_view = TRUE; - g_object_ref (model->book); - need_get_book_view = TRUE; - } - break; - case PROP_QUERY: - if (model->query) - e_book_query_unref (model->query); - model->query = e_book_query_from_string (g_value_get_string (value)); - need_get_book_view = TRUE; - break; - case PROP_EDITABLE: - model->editable = g_value_get_boolean (value); - model->editable_set = TRUE; - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), -1); + g_return_val_if_fail (E_IS_CONTACT (contact), -1); - if (need_get_book_view) { - if (!model->book_view_idle_id) { - g_object_ref (model); - model->book_view_idle_id = g_idle_add ((GSourceFunc)get_view_idle, model); - } + array = model->priv->contacts; + for (ii = 0; ii < array->len; ii++) { + EContact *candidate = array->pdata[ii]; + + if (contact == candidate) + return ii; } + return -1; } -static void -eab_model_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +EBook * +e_addressbook_model_get_book (EAddressbookModel *model) { - EABModel *eab_model; - - eab_model = EAB_MODEL (object); + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); - switch (prop_id) { - case PROP_BOOK: - g_value_set_object (value, eab_model->book); - break; - case PROP_QUERY: { - gchar *query_string = e_book_query_to_string (eab_model->query); - g_value_set_string (value, query_string); - break; - } - case PROP_EDITABLE: - g_value_set_boolean (value, eab_model->editable); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return model->priv->book; } -GType -eab_model_get_type (void) +void +e_addressbook_model_set_book (EAddressbookModel *model, + EBook *book) { - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EABModelClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_model_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABModel), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_model_init, - }; - - type = g_type_register_static (PARENT_TYPE, "EABModel", &info, 0); + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + g_return_if_fail (E_IS_BOOK (book)); + + if (model->priv->book != NULL) { + if (model->priv->writable_status_id != 0) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->writable_status_id); + model->priv->writable_status_id = 0; + + if (model->priv->backend_died_id != 0) + g_signal_handler_disconnect ( + model->priv->book, + model->priv->backend_died_id); + model->priv->backend_died_id = 0; + + g_object_unref (model->priv->book); } - return type; -} + model->priv->book = g_object_ref (book); + model->priv->first_get_view = TRUE; -EABModel* -eab_model_new (void) -{ - EABModel *et; + model->priv->writable_status_id = g_signal_connect ( + book, "writable-status", + G_CALLBACK (writable_status), model); - et = g_object_new (EAB_TYPE_MODEL, NULL); + model->priv->backend_died_id = g_signal_connect ( + book, "backend-died", + G_CALLBACK (backend_died), model); - return et; -} + if (!model->priv->editable_set) { + model->priv->editable = e_book_is_writable (book); + g_signal_emit ( + model, signals[WRITABLE_STATUS], 0, + model->priv->editable); + } -void eab_model_stop (EABModel *model) -{ - remove_book_view(model); - g_signal_emit (model, - eab_model_signals [STOP_STATE_CHANGED], 0); - g_signal_emit (model, - eab_model_signals [STATUS_MESSAGE], 0, - "Search Interrupted."); + if (model->priv->book_view_idle_id == 0) + model->priv->book_view_idle_id = g_idle_add ( + (GSourceFunc) addressbook_model_idle_cb, + g_object_ref (model)); + + g_object_notify (G_OBJECT (model), "book"); } gboolean -eab_model_can_stop (EABModel *model) +e_addressbook_model_get_editable (EAddressbookModel *model) { - return model->search_in_progress; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), FALSE); + + return model->priv->editable; } void -eab_model_force_folder_bar_message (EABModel *model) +e_addressbook_model_set_editable (EAddressbookModel *model, + gboolean editable) { - update_folder_bar_message (model); -} + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); -gint -eab_model_contact_count (EABModel *model) -{ - return model->data_count; -} + model->priv->editable = editable; + model->priv->editable_set = TRUE; -const EContact * -eab_model_contact_at (EABModel *model, gint index) -{ - return model->data[index]; + g_object_notify (G_OBJECT (model), "editable"); } -gboolean -eab_model_editable (EABModel *model) +gchar * +e_addressbook_model_get_query (EAddressbookModel *model) { - return model->editable; + g_return_val_if_fail (E_IS_ADDRESSBOOK_MODEL (model), NULL); + + return e_book_query_to_string (model->priv->query); } -EBook * -eab_model_get_ebook (EABModel *model) +void +e_addressbook_model_set_query (EAddressbookModel *model, + const gchar *query) { - return model->book; + g_return_if_fail (E_IS_ADDRESSBOOK_MODEL (model)); + + if (model->priv->query != NULL) + e_book_query_unref (model->priv->query); + + if (query == NULL) + model->priv->query = e_book_query_any_field_contains (""); + else + model->priv->query = e_book_query_from_string (query); + + if (model->priv->book_view_idle_id == 0) + model->priv->book_view_idle_id = g_idle_add ( + (GSourceFunc) addressbook_model_idle_cb, + g_object_ref (model)); + + g_object_notify (G_OBJECT (model), "query"); } diff --git a/addressbook/gui/widgets/e-addressbook-model.h b/addressbook/gui/widgets/e-addressbook-model.h index 1383da4b19..b42de48dbc 100644 --- a/addressbook/gui/widgets/e-addressbook-model.h +++ b/addressbook/gui/widgets/e-addressbook-model.h @@ -18,82 +18,98 @@ * */ -#ifndef _EAB_MODEL_H_ -#define _EAB_MODEL_H_ +#ifndef E_ADDRESSBOOK_MODEL_H +#define E_ADDRESSBOOK_MODEL_H -#include <glib.h> -#include <glib-object.h> #include <libebook/e-book.h> +#include <libebook/e-book-query.h> #include <libebook/e-book-view.h> -#define EAB_TYPE_MODEL (eab_model_get_type ()) -#define EAB_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EAB_TYPE_MODEL, EABModel)) -#define EAB_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EAB_TYPE_MODEL, EABModelClass)) -#define E_IS_ADDRESSBOOK_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EAB_TYPE_MODEL)) -#define E_IS_ADDRESSBOOK_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EAB_TYPE_MODEL)) - -typedef struct _EABModel EABModel; -typedef struct _EABModelClass EABModelClass; - -struct _EABModel { +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_MODEL \ + (e_addressbook_model_get_type ()) +#define E_ADDRESSBOOK_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModel)) +#define E_ADDRESSBOOK_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_MODEL, EAddressbookModelClass)) +#define E_IS_ADDRESSBOOK_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL)) +#define E_IS_ADDRESSBOOK_MODEL_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_MODEL)) +#define E_ADDRESSBOOK_MODEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_MODEL)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookModel EAddressbookModel; +typedef struct _EAddressbookModelClass EAddressbookModelClass; +typedef struct _EAddressbookModelPrivate EAddressbookModelPrivate; + +struct _EAddressbookModel { GObject parent; - - /* item specific fields */ - EBook *book; - EBookQuery *query; - EBookView *book_view; - - gint book_view_idle_id; - - EContact **data; - gint data_count; - gint allocated_count; - - gint create_contact_id, remove_contact_id, modify_contact_id; - gint status_message_id, writable_status_id, sequence_complete_id; - gint backend_died_id; - - guint search_in_progress : 1; - guint editable : 1; - guint editable_set : 1; - guint first_get_view : 1; + EAddressbookModelPrivate *priv; }; -struct _EABModelClass { +struct _EAddressbookModelClass { GObjectClass parent_class; - /* - * Signals - */ - void (*writable_status) (EABModel *model, gboolean writable); - void (*search_started) (EABModel *model); - void (*search_result) (EABModel *model, EBookViewStatus status); - void (*status_message) (EABModel *model, const gchar *message); - void (*folder_bar_message) (EABModel *model, const gchar *message); - void (*contact_added) (EABModel *model, gint index, gint count); - void (*contacts_removed) (EABModel *model, gpointer id_list); - void (*contact_changed) (EABModel *model, gint index); - void (*model_changed) (EABModel *model); - void (*stop_state_changed) (EABModel *model); - void (*backend_died) (EABModel *model); + /* Signals */ + void (*writable_status) (EAddressbookModel *model, + gboolean writable); + void (*search_started) (EAddressbookModel *model); + void (*search_result) (EAddressbookModel *model, + EBookViewStatus status); + void (*status_message) (EAddressbookModel *model, + const gchar *message); + void (*folder_bar_message) (EAddressbookModel *model, + const gchar *message); + void (*contact_added) (EAddressbookModel *model, + gint index, + gint count); + void (*contacts_removed) (EAddressbookModel *model, + gpointer id_list); + void (*contact_changed) (EAddressbookModel *model, + gint index); + void (*model_changed) (EAddressbookModel *model); + void (*stop_state_changed) (EAddressbookModel *model); + void (*backend_died) (EAddressbookModel *model); }; -GType eab_model_get_type (void); -EABModel *eab_model_new (void); +GType e_addressbook_model_get_type (void); +EAddressbookModel * + e_addressbook_model_new (void); /* Returns object with ref count of 1. */ -EContact *eab_model_get_contact (EABModel *model, - gint row); -EBook *eab_model_get_ebook (EABModel *model); - -void eab_model_stop (EABModel *model); -gboolean eab_model_can_stop (EABModel *model); - -void eab_model_force_folder_bar_message (EABModel *model); - -gint eab_model_contact_count (EABModel *model); -const EContact *eab_model_contact_at (EABModel *model, - gint index); -gboolean eab_model_editable (EABModel *model); - -#endif /* _EAB_MODEL_H_ */ +EContact * e_addressbook_model_get_contact (EAddressbookModel *model, + gint row); + +void e_addressbook_model_stop (EAddressbookModel *model); +gboolean e_addressbook_model_can_stop (EAddressbookModel *model); + +void e_addressbook_model_force_folder_bar_message + (EAddressbookModel *model); + +gint e_addressbook_model_contact_count + (EAddressbookModel *model); +EContact * e_addressbook_model_contact_at (EAddressbookModel *model, + gint index); +gint e_addressbook_model_find (EAddressbookModel *model, + EContact *contact); +EBook * e_addressbook_model_get_book (EAddressbookModel *model); +void e_addressbook_model_set_book (EAddressbookModel *model, + EBook *book); +gboolean e_addressbook_model_get_editable(EAddressbookModel *model); +void e_addressbook_model_set_editable(EAddressbookModel *model, + gboolean editable); +gchar * e_addressbook_model_get_query (EAddressbookModel *model); +void e_addressbook_model_set_query (EAddressbookModel *model, + const gchar *query); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_MODEL_H */ diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c index 536d065c10..500b045077 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c @@ -20,18 +20,17 @@ #include <string.h> #include <glib/gi18n.h> -#include "e-util/e-util.h" #include "e-addressbook-reflow-adapter.h" #include "e-addressbook-model.h" -#include "e-addressbook-view.h" #include "eab-gui-util.h" #include "e-minicard.h" +#include <e-util/e-util.h> #include <misc/e-gui-utils.h> #include "addressbook/printing/e-contact-print.h" struct _EAddressbookReflowAdapterPrivate { - EABModel *model; + EAddressbookModel *model; gboolean loading; @@ -54,10 +53,11 @@ enum { enum { DRAG_BEGIN, + OPEN_CONTACT, LAST_SIGNAL }; -static guint e_addressbook_reflow_adapter_signals [LAST_SIGNAL] = {0, }; +static guint signals [LAST_SIGNAL] = {0, }; static void unlink_model(EAddressbookReflowAdapter *adapter) @@ -128,7 +128,7 @@ addressbook_count (EReflowModel *erm) EAddressbookReflowAdapter *adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(erm); EAddressbookReflowAdapterPrivate *priv = adapter->priv; - return eab_model_contact_count (priv->model); + return e_addressbook_model_contact_count (priv->model); } /* This function returns the height of the minicontact in question */ @@ -140,7 +140,7 @@ addressbook_height (EReflowModel *erm, gint i, GnomeCanvasGroup *parent) EContactField field; gint count = 0; gchar *string; - EContact *contact = (EContact*)eab_model_contact_at (priv->model, i); + EContact *contact = (EContact*)e_addressbook_model_contact_at (priv->model, i); PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET (GNOME_CANVAS_ITEM (parent)->canvas), ""); gint height; @@ -189,8 +189,8 @@ addressbook_compare (EReflowModel *erm, gint n1, gint n2) return n1-n2; } else { - contact1 = (EContact*)eab_model_contact_at (priv->model, n1); - contact2 = (EContact*)eab_model_contact_at (priv->model, n2); + contact1 = (EContact*)e_addressbook_model_contact_at (priv->model, n1); + contact2 = (EContact*)e_addressbook_model_contact_at (priv->model, n2); if (contact1 && contact2) { const gchar *file_as1, *file_as2; @@ -226,12 +226,20 @@ adapter_drag_begin (EMinicard *card, GdkEvent *event, EAddressbookReflowAdapter gint ret_val = 0; g_signal_emit (adapter, - e_addressbook_reflow_adapter_signals[DRAG_BEGIN], 0, + signals[DRAG_BEGIN], 0, event, &ret_val); return ret_val; } +static void +adapter_open_contact (EMinicard *card, + EContact *contact, + EAddressbookReflowAdapter *adapter) +{ + g_signal_emit (adapter, signals[OPEN_CONTACT], 0, contact); +} + static GnomeCanvasItem * addressbook_incarnate (EReflowModel *erm, gint i, GnomeCanvasGroup *parent) { @@ -241,8 +249,8 @@ addressbook_incarnate (EReflowModel *erm, gint i, GnomeCanvasGroup *parent) item = gnome_canvas_item_new(parent, e_minicard_get_type(), - "contact", eab_model_contact_at (priv->model, i), - "editable", eab_model_editable (priv->model), + "contact", e_addressbook_model_contact_at (priv->model, i), + "editable", e_addressbook_model_get_editable (priv->model), NULL); #if 0 @@ -251,7 +259,10 @@ addressbook_incarnate (EReflowModel *erm, gint i, GnomeCanvasGroup *parent) #endif g_signal_connect (item, "drag_begin", - G_CALLBACK(adapter_drag_begin), adapter); + G_CALLBACK (adapter_drag_begin), adapter); + + g_signal_connect (item, "open-contact", + G_CALLBACK (adapter_open_contact), adapter); return item; } @@ -263,12 +274,12 @@ addressbook_reincarnate (EReflowModel *erm, gint i, GnomeCanvasItem *item) EAddressbookReflowAdapterPrivate *priv = adapter->priv; gnome_canvas_item_set(item, - "contact", eab_model_contact_at (priv->model, i), + "contact", e_addressbook_model_contact_at (priv->model, i), NULL); } static void -create_contact (EABModel *model, +create_contact (EAddressbookModel *model, gint index, gint count, EAddressbookReflowAdapter *adapter) { @@ -278,7 +289,7 @@ create_contact (EABModel *model, } static void -remove_contacts (EABModel *model, +remove_contacts (EAddressbookModel *model, gpointer data, EAddressbookReflowAdapter *adapter) { @@ -293,7 +304,7 @@ remove_contacts (EABModel *model, } static void -modify_contact (EABModel *model, +modify_contact (EAddressbookModel *model, gint index, EAddressbookReflowAdapter *adapter) { @@ -301,14 +312,14 @@ modify_contact (EABModel *model, } static void -model_changed (EABModel *model, +model_changed (EAddressbookModel *model, EAddressbookReflowAdapter *adapter) { e_reflow_model_changed (E_REFLOW_MODEL (adapter)); } static void -search_started (EABModel *model, +search_started (EAddressbookModel *model, EAddressbookReflowAdapter *adapter) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; @@ -317,7 +328,7 @@ search_started (EABModel *model, } static void -search_result (EABModel *model, +search_result (EAddressbookModel *model, EBookViewStatus status, EAddressbookReflowAdapter *adapter) { @@ -423,10 +434,10 @@ e_addressbook_reflow_adapter_class_init (GObjectClass *object_class) g_param_spec_object ("model", _("Model"), /*_( */"XXX blurb" /*)*/, - EAB_TYPE_MODEL, + E_TYPE_ADDRESSBOOK_MODEL, G_PARAM_READABLE)); - e_addressbook_reflow_adapter_signals [DRAG_BEGIN] = + signals [DRAG_BEGIN] = g_signal_new ("drag_begin", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, @@ -435,6 +446,16 @@ e_addressbook_reflow_adapter_class_init (GObjectClass *object_class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); + signals [OPEN_CONTACT] = + g_signal_new ("open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookReflowAdapterClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + model_class->set_width = addressbook_set_width; model_class->count = addressbook_count; model_class->height = addressbook_height; @@ -486,7 +507,7 @@ e_addressbook_reflow_adapter_get_type (void) void e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, - EABModel *model) + EAddressbookModel *model) { EAddressbookReflowAdapterPrivate *priv = adapter->priv; @@ -520,7 +541,7 @@ e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, } EReflowModel * -e_addressbook_reflow_adapter_new (EABModel *model) +e_addressbook_reflow_adapter_new (EAddressbookModel *model) { EAddressbookReflowAdapter *et; @@ -538,5 +559,5 @@ e_addressbook_reflow_adapter_get_contact (EAddressbookReflowAdapter *adapter, { EAddressbookReflowAdapterPrivate *priv = adapter->priv; - return eab_model_get_contact (priv->model, index); + return e_addressbook_model_get_contact (priv->model, index); } diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h index 0f8eb4102c..bc428ba30c 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.h @@ -21,7 +21,7 @@ #ifndef _E_ADDRESSBOOK_REFLOW_ADAPTER_H_ #define _E_ADDRESSBOOK_REFLOW_ADAPTER_H_ -#include <misc/e-reflow-model.h> +#include <text/e-reflow-model.h> #include <libebook/e-contact.h> #include "e-addressbook-model.h" @@ -47,13 +47,16 @@ struct _EAddressbookReflowAdapterClass { /* * Signals */ - gint (* drag_begin) (EAddressbookReflowAdapter *adapter, GdkEvent *event); + gint (*drag_begin) (EAddressbookReflowAdapter *adapter, + GdkEvent *event); + void (*open_contact) (EAddressbookReflowAdapter *adapter, + EContact *contact); }; GType e_addressbook_reflow_adapter_get_type (void); void e_addressbook_reflow_adapter_construct (EAddressbookReflowAdapter *adapter, - EABModel *model); -EReflowModel *e_addressbook_reflow_adapter_new (EABModel *model); + EAddressbookModel *model); +EReflowModel *e_addressbook_reflow_adapter_new (EAddressbookModel *model); /* Returns object with ref count of 1. */ EContact *e_addressbook_reflow_adapter_get_contact (EAddressbookReflowAdapter *adapter, diff --git a/addressbook/gui/widgets/e-addressbook-selector.c b/addressbook/gui/widgets/e-addressbook-selector.c new file mode 100644 index 0000000000..21347e2529 --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.c @@ -0,0 +1,443 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-addressbook-selector.h" + +#include <eab-book-util.h> +#include <eab-contact-merging.h> + +#define E_ADDRESSBOOK_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorPrivate)) + +#define PRIMARY_ADDRESSBOOK_KEY \ + "/apps/evolution/addressbook/display/primary_addressbook" + +typedef struct _MergeContext MergeContext; + +struct _EAddressbookSelectorPrivate { + EAddressbookView *current_view; +}; + +struct _MergeContext { + EBook *source_book; + EBook *target_book; + + EContact *current_contact; + GList *remaining_contacts; + guint pending_removals; + + gint remove_from_source : 1; + gint copy_done : 1; +}; + +enum { + PROP_0, + PROP_CURRENT_VIEW +}; + +enum { + DND_TARGET_TYPE_VCARD, + DND_TARGET_TYPE_SOURCE_VCARD +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/x-vcard", 0, DND_TARGET_TYPE_VCARD }, + { (gchar *) "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD } +}; + +static gpointer parent_class; + +static void +merge_context_next (MergeContext *merge_context) +{ + GList *list; + + list = merge_context->remaining_contacts; + merge_context->current_contact = list->data; + list = g_list_delete_link (list, list); + merge_context->remaining_contacts = list; +} + +static MergeContext * +merge_context_new (EBook *source_book, + EBook *target_book, + GList *contact_list) +{ + MergeContext *merge_context; + + merge_context = g_slice_new0 (MergeContext); + merge_context->source_book = source_book; + merge_context->target_book = target_book; + merge_context->remaining_contacts = contact_list; + merge_context_next (merge_context); + + return merge_context; +} + +static void +merge_context_free (MergeContext *merge_context) +{ + if (merge_context->source_book != NULL) + g_object_unref (merge_context->source_book); + + if (merge_context->target_book != NULL) + g_object_unref (merge_context->target_book); + + g_slice_free (MergeContext, merge_context); +} + +static void +addressbook_selector_removed_cb (EBook *book, + EBookStatus status, + MergeContext *merge_context) +{ + merge_context->pending_removals--; + + if (merge_context->remaining_contacts != NULL) + return; + + if (merge_context->pending_removals > 0) + return; + + merge_context_free (merge_context); +} + +static void +addressbook_selector_merge_next_cb (EBook *book, + EBookStatus status, + const gchar *id, + MergeContext *merge_context) +{ + if (merge_context->remove_from_source && status == E_BOOK_ERROR_OK) { + /* Remove previous contact from source. */ + e_book_async_remove_contact ( + merge_context->source_book, + merge_context->current_contact, + (EBookCallback) addressbook_selector_removed_cb, + merge_context); + merge_context->pending_removals++; + } + + g_object_unref (merge_context->current_contact); + + if (merge_context->remaining_contacts != NULL) { + merge_context_next (merge_context); + eab_merging_book_add_contact ( + merge_context->target_book, + merge_context->current_contact, + (EBookIdCallback) addressbook_selector_merge_next_cb, + merge_context); + + } else if (merge_context->pending_removals == 0) + merge_context_free (merge_context); +} + +static void +addressbook_selector_load_primary_source (ESourceSelector *selector) +{ + GConfClient *client; + ESourceList *source_list; + ESource *source = NULL; + const gchar *key; + gchar *uid; + + /* XXX If ESourceSelector had a "primary-uid" property, + * we could just bind the GConf key to it. */ + + source_list = e_source_selector_get_source_list (selector); + + client = gconf_client_get_default (); + key = PRIMARY_ADDRESSBOOK_KEY; + uid = gconf_client_get_string (client, key, NULL); + g_object_unref (client); + + if (uid != NULL) { + source = e_source_list_peek_source_by_uid (source_list, uid); + g_free (uid); + } else { + GSList *groups; + + /* Dig up the first source in the source list. + * XXX libedataserver should provide API for this. */ + groups = e_source_list_peek_groups (source_list); + while (groups != NULL) { + ESourceGroup *source_group = groups->data; + GSList *sources; + + sources = e_source_group_peek_sources (source_group); + if (sources != NULL) { + source = sources->data; + break; + } + + groups = g_slist_next (groups); + } + } + + if (source != NULL) + e_source_selector_set_primary_selection (selector, source); +} + +static void +addressbook_selector_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + e_addressbook_selector_set_current_view ( + E_ADDRESSBOOK_SELECTOR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_selector_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CURRENT_VIEW: + g_value_set_object ( + value, + e_addressbook_selector_get_current_view ( + E_ADDRESSBOOK_SELECTOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +addressbook_selector_dispose (GObject *object) +{ + EAddressbookSelectorPrivate *priv; + + priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (object); + + if (priv->current_view != NULL) { + g_object_unref (priv->current_view); + priv->current_view = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +addressbook_selector_constructed (GObject *object) +{ + ESourceSelector *selector; + + selector = E_SOURCE_SELECTOR (object); + addressbook_selector_load_primary_source (selector); +} + +static void +addressbook_selector_primary_selection_changed (ESourceSelector *selector) +{ + ESource *source; + GConfClient *client; + const gchar *key; + const gchar *string; + + /* XXX If ESourceSelector had a "primary-uid" property, + * we could just bind the GConf key to it. */ + + source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; + + client = gconf_client_get_default (); + key = PRIMARY_ADDRESSBOOK_KEY; + string = e_source_peek_uid (source); + gconf_client_set_string (client, key, string, NULL); + g_object_unref (client); +} + +static gboolean +addressbook_selector_data_dropped (ESourceSelector *selector, + GtkSelectionData *selection_data, + ESource *destination, + GdkDragAction action, + guint info) +{ + EAddressbookSelectorPrivate *priv; + MergeContext *merge_context; + EAddressbookModel *model; + EBook *source_book; + EBook *target_book; + GList *list; + const gchar *string; + gboolean remove_from_source; + + priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + g_return_val_if_fail (priv->current_view != NULL, FALSE); + + string = (const gchar *) selection_data->data; + remove_from_source = (action == GDK_ACTION_MOVE); + + target_book = e_book_new (destination, NULL); + if (target_book == NULL) + return FALSE; + + e_book_open (target_book, FALSE, NULL); + + /* XXX Function assumes both out arguments are provided. All we + * care about is the contact list; source_book will be NULL. */ + eab_book_and_contact_list_from_string (string, &source_book, &list); + if (list == NULL) + return FALSE; + + model = e_addressbook_view_get_model (priv->current_view); + source_book = e_addressbook_model_get_book (model); + g_return_val_if_fail (E_IS_BOOK (source_book), FALSE); + + merge_context = merge_context_new (source_book, target_book, list); + merge_context->remove_from_source = remove_from_source; + + eab_merging_book_add_contact ( + target_book, merge_context->current_contact, + (EBookIdCallback) addressbook_selector_merge_next_cb, + merge_context); + + return TRUE; +} + +static void +addressbook_selector_class_init (EAddressbookSelectorClass *class) +{ + GObjectClass *object_class; + ESourceSelectorClass *selector_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookSelectorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = addressbook_selector_set_property; + object_class->get_property = addressbook_selector_get_property; + object_class->dispose = addressbook_selector_dispose; + object_class->constructed = addressbook_selector_constructed; + + selector_class = E_SOURCE_SELECTOR_CLASS (class); + selector_class->primary_selection_changed = + addressbook_selector_primary_selection_changed; + selector_class->data_dropped = addressbook_selector_data_dropped; + + g_object_class_install_property ( + object_class, + PROP_CURRENT_VIEW, + g_param_spec_object ( + "current-view", + NULL, + NULL, + E_TYPE_ADDRESSBOOK_VIEW, + G_PARAM_READWRITE)); +} + +static void +addressbook_selector_init (EAddressbookSelector *selector) +{ + selector->priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + + gtk_drag_dest_set ( + GTK_WIDGET (selector), GTK_DEST_DEFAULT_ALL, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_COPY | GDK_ACTION_MOVE); +} + +GType +e_addressbook_selector_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EAddressbookSelectorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_selector_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookSelector), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_selector_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_SOURCE_SELECTOR, "EAddressbookSelector", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_addressbook_selector_new (ESourceList *source_list) +{ + g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL); + + return g_object_new ( + E_TYPE_ADDRESSBOOK_SELECTOR, + "source-list", source_list, NULL); +} + +EAddressbookView * +e_addressbook_selector_get_current_view (EAddressbookSelector *selector) +{ + g_return_val_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector), NULL); + + return selector->priv->current_view; +} + +void +e_addressbook_selector_set_current_view (EAddressbookSelector *selector, + EAddressbookView *current_view) +{ + /* XXX This is only needed for moving contacts via drag-and-drop. + * The selection data doesn't include the source of the data + * (the model for the currently selected address book view), + * so we have to rely on it being provided to us. I would + * be happy to see this function go away. */ + + g_return_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector)); + + if (current_view != NULL) + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (current_view)); + + if (selector->priv->current_view != NULL) { + g_object_unref (selector->priv->current_view); + selector->priv->current_view = NULL; + } + + if (current_view != NULL) + g_object_ref (current_view); + + selector->priv->current_view = current_view; + + g_object_notify (G_OBJECT (selector), "current-view"); +} diff --git a/addressbook/gui/widgets/e-addressbook-selector.h b/addressbook/gui/widgets/e-addressbook-selector.h new file mode 100644 index 0000000000..c0102cb3b8 --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_ADDRESSBOOK_SELECTOR_H +#define E_ADDRESSBOOK_SELECTOR_H + +#include <libedataserver/e-source-list.h> +#include <libedataserverui/e-source-selector.h> +#include "e-addressbook-view.h" + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_SELECTOR \ + (e_addressbook_selector_get_type ()) +#define E_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelector)) +#define E_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) +#define E_IS_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_IS_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_ADDRESSBOOK_SELECTOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookSelector EAddressbookSelector; +typedef struct _EAddressbookSelectorClass EAddressbookSelectorClass; +typedef struct _EAddressbookSelectorPrivate EAddressbookSelectorPrivate; + +struct _EAddressbookSelector { + ESourceSelector parent; + EAddressbookSelectorPrivate *priv; +}; + +struct _EAddressbookSelectorClass { + ESourceSelectorClass parent_class; +}; + +GType e_addressbook_selector_get_type (void); +GtkWidget * e_addressbook_selector_new (ESourceList *source_list); +EAddressbookView * + e_addressbook_selector_get_current_view + (EAddressbookSelector *selector); +void e_addressbook_selector_set_current_view + (EAddressbookSelector *selector, + EAddressbookView *current_view); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_SELECTOR_H */ diff --git a/addressbook/gui/widgets/e-addressbook-table-adapter.c b/addressbook/gui/widgets/e-addressbook-table-adapter.c index a081ebb34d..396c382d32 100644 --- a/addressbook/gui/widgets/e-addressbook-table-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-table-adapter.c @@ -31,7 +31,7 @@ #include <libxml/xmlmemory.h> struct _EAddressbookTableAdapterPrivate { - EABModel *model; + EAddressbookModel *model; gint create_contact_id, remove_contact_id, modify_contact_id, model_changed_id; @@ -100,7 +100,7 @@ addressbook_row_count (ETableModel *etc) EAddressbookTableAdapter *adapter = EAB_TABLE_ADAPTER(etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - return eab_model_contact_count (priv->model); + return e_addressbook_model_contact_count (priv->model); } /* This function returns the value at a particular point in our ETableModel. */ @@ -111,10 +111,10 @@ addressbook_value_at (ETableModel *etc, gint col, gint row) EAddressbookTableAdapterPrivate *priv = adapter->priv; const gchar *value; - if ( col >= COLS || row >= eab_model_contact_count (priv->model) ) + if ( col >= COLS || row >= e_addressbook_model_contact_count (priv->model) ) return NULL; - value = e_contact_get_const((EContact*)eab_model_contact_at (priv->model, row), col); + value = e_contact_get_const((EContact*)e_addressbook_model_contact_at (priv->model, row), col); if (value && *value && (col == E_CONTACT_EMAIL_1 || col == E_CONTACT_EMAIL_2 || col == E_CONTACT_EMAIL_3)) { gchar *val = g_hash_table_lookup (priv->emails, value); @@ -156,13 +156,13 @@ addressbook_set_value_at (ETableModel *etc, gint col, gint row, gconstpointer va EAddressbookTableAdapter *adapter = EAB_TABLE_ADAPTER(etc); EAddressbookTableAdapterPrivate *priv = adapter->priv; - if (eab_model_editable (priv->model)) { + if (e_addressbook_model_get_editable (priv->model)) { EContact *contact; - if (col >= COLS || row >= eab_model_contact_count (priv->model)) + if (col >= COLS || row >= e_addressbook_model_contact_count (priv->model)) return; - contact = eab_model_get_contact (priv->model, row); + contact = e_addressbook_model_get_contact (priv->model, row); if (!contact) return; @@ -177,7 +177,7 @@ addressbook_set_value_at (ETableModel *etc, gint col, gint row, gconstpointer va } e_contact_set(contact, col, (gpointer) val); - eab_merging_book_commit_contact (eab_model_get_ebook (priv->model), + eab_merging_book_commit_contact (e_addressbook_model_get_book (priv->model), contact, contact_modified_cb, etc); g_object_unref (contact); @@ -196,12 +196,12 @@ addressbook_is_cell_editable (ETableModel *etc, gint col, gint row) EAddressbookTableAdapterPrivate *priv = adapter->priv; const EContact *contact; - if (row >= 0 && row < eab_model_contact_count (priv->model)) - contact = eab_model_contact_at (priv->model, row); + if (row >= 0 && row < e_addressbook_model_contact_count (priv->model)) + contact = e_addressbook_model_contact_at (priv->model, row); else contact = NULL; - if (!eab_model_editable(priv->model)) + if (!e_addressbook_model_editable(priv->model)) return FALSE; else if (contact && e_contact_get ((EContact *) contact, E_CONTACT_IS_LIST)) /* we only allow editing of the name and file as for @@ -229,7 +229,7 @@ addressbook_append_row (ETableModel *etm, ETableModel *source, gint row) e_contact_set (contact, col, (gpointer) val); } - eab_merging_book_add_contact (eab_model_get_ebook (priv->model), contact, NULL, NULL); + eab_merging_book_add_contact (e_addressbook_model_get_book (priv->model), contact, NULL, NULL); g_object_unref (contact); } @@ -303,7 +303,7 @@ eab_table_adapter_init (GObject *object) } static void -create_contact (EABModel *model, +create_contact (EAddressbookModel *model, gint index, gint count, EAddressbookTableAdapter *adapter) { @@ -312,7 +312,7 @@ create_contact (EABModel *model, } static void -remove_contacts (EABModel *model, +remove_contacts (EAddressbookModel *model, gpointer data, EAddressbookTableAdapter *adapter) { @@ -330,7 +330,7 @@ remove_contacts (EABModel *model, } static void -modify_contact (EABModel *model, +modify_contact (EAddressbookModel *model, gint index, EAddressbookTableAdapter *adapter) { @@ -342,7 +342,7 @@ modify_contact (EABModel *model, } static void -model_changed (EABModel *model, +model_changed (EAddressbookModel *model, EAddressbookTableAdapter *adapter) { /* clear whole cache */ @@ -378,7 +378,7 @@ eab_table_adapter_get_type (void) void eab_table_adapter_construct (EAddressbookTableAdapter *adapter, - EABModel *model) + EAddressbookModel *model) { EAddressbookTableAdapterPrivate *priv = adapter->priv; @@ -406,7 +406,7 @@ eab_table_adapter_construct (EAddressbookTableAdapter *adapter, } ETableModel * -eab_table_adapter_new (EABModel *model) +eab_table_adapter_new (EAddressbookModel *model) { EAddressbookTableAdapter *et; diff --git a/addressbook/gui/widgets/e-addressbook-table-adapter.h b/addressbook/gui/widgets/e-addressbook-table-adapter.h index 27bfe0e3f4..71999bd4d1 100644 --- a/addressbook/gui/widgets/e-addressbook-table-adapter.h +++ b/addressbook/gui/widgets/e-addressbook-table-adapter.h @@ -47,7 +47,7 @@ struct _EAddressbookTableAdapterClass { GType eab_table_adapter_get_type (void); void eab_table_adapter_construct (EAddressbookTableAdapter *adapter, - EABModel *model); -ETableModel *eab_table_adapter_new (EABModel *model); + EAddressbookModel *model); +ETableModel *eab_table_adapter_new (EAddressbookModel *model); #endif /* _EAB_TABLE_ADAPTER_H_ */ diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index 283b25f89f..c606530594 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -31,12 +31,10 @@ #include <widgets/menus/gal-view-factory-etable.h> #include <filter/rule-editor.h> #include <widgets/menus/gal-view-etable.h> -#include <e-util/e-xml-utils.h> +#include <shell/e-shell-sidebar.h> #include "addressbook/printing/e-contact-print.h" -#include "addressbook/gui/widgets/eab-popup.h" -#include "addressbook/gui/widgets/eab-menu.h" -#include "a11y/addressbook/ea-addressbook.h" +#include "ea-addressbook.h" #include "e-util/e-print.h" #include "e-util/e-util.h" @@ -56,1538 +54,954 @@ #include "e-util/e-error.h" #include "e-util/e-util-private.h" -#include "e-contact-editor.h" #include <gdk/gdkkeysyms.h> #include <ctype.h> #include <string.h> -#include <libxml/tree.h> -#include <libxml/parser.h> - -#define SHOW_ALL_SEARCH "(contains \"x-evolution-any-field\" \"\")" +#define E_ADDRESSBOOK_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewPrivate)) #define d(x) -static void eab_view_init (EABView *card); -static void eab_view_class_init (EABViewClass *class); - -static void eab_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static void eab_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); - -static void eab_view_dispose (GObject *object); -static void change_view_type (EABView *view, EABViewType view_type); - -static void status_message (GtkObject *object, const gchar *status, EABView *eav); -static void search_result (GtkObject *object, EBookViewStatus status, EABView *eav); -static void folder_bar_message (GtkObject *object, const gchar *status, EABView *eav); -static void stop_state_changed (GtkObject *object, EABView *eav); -static void writable_status (GtkObject *object, gboolean writable, EABView *eav); -static void backend_died (GtkObject *object, EABView *eav); -static void contact_changed (EABModel *model, gint index, EABView *eav); -static void contacts_removed (EABModel *model, gpointer data, EABView *eav); -static GList *get_selected_contacts (EABView *view); - -static void command_state_change (EABView *eav); - -static void selection_clear_event (GtkWidget *invisible, GdkEventSelection *event, - EABView *view); -static void selection_received (GtkWidget *invisible, GtkSelectionData *selection_data, - guint time, EABView *view); -static void selection_get (GtkWidget *invisible, GtkSelectionData *selection_data, - guint info, guint time_stamp, EABView *view); -static void invisible_destroyed (gpointer data, GObject *where_object_was); - -static void categories_changed_cb (gpointer object, gpointer user_data); -static void make_suboptions (EABView *view); -static void query_changed (ESearchBar *esb, EABView *view); -static void search_activated (ESearchBar *esb, EABView *view); -static void search_menu_activated (ESearchBar *esb, gint id, EABView *view); -static GList *get_master_list (gboolean force_rebuild); +static void status_message (EAddressbookView *view, const gchar *status); +static void search_result (EAddressbookView *view, EBookViewStatus status); +static void folder_bar_message (EAddressbookView *view, const gchar *status); +static void stop_state_changed (GtkObject *object, EAddressbookView *view); +static void backend_died (EAddressbookView *view); -static gpointer parent_class; +static void command_state_change (EAddressbookView *view); + +struct _EAddressbookViewPrivate { + gpointer shell_view; /* weak pointer */ + + EAddressbookModel *model; + EActivity *activity; + + GList *clipboard_contacts; + ESource *source; + + GObject *object; + GtkWidget *widget; + + GalViewInstance *view_instance; + + GtkWidget *invisible; +}; -/* The arguments we take */ enum { PROP_0, - PROP_BOOK, - PROP_SOURCE, - PROP_QUERY, - PROP_TYPE + PROP_MODEL, + PROP_SHELL_VIEW, + PROP_SOURCE }; enum { - STATUS_MESSAGE, - SEARCH_RESULT, - FOLDER_BAR_MESSAGE, + OPEN_CONTACT, + POPUP_EVENT, COMMAND_STATE_CHANGE, + SELECTION_CHANGE, LAST_SIGNAL }; -enum DndTargetType { +enum { DND_TARGET_TYPE_SOURCE_VCARD, DND_TARGET_TYPE_VCARD }; -#define VCARD_TYPE "text/x-vcard" -#define SOURCE_VCARD_TYPE "text/x-source-vcard" - -typedef struct EABSearchBarItem { - ESearchBarItem search; - gchar *image; -}EABSearchBarItem; static GtkTargetEntry drag_types[] = { - { (gchar *) SOURCE_VCARD_TYPE, 0, DND_TARGET_TYPE_SOURCE_VCARD }, - { (gchar *) VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD } + { (gchar *) "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD }, + { (gchar *) "text/x-vcard", 0, DND_TARGET_TYPE_VCARD } }; -static const gint num_drag_types = sizeof (drag_types) / sizeof (drag_types[0]); - -static guint eab_view_signals [LAST_SIGNAL] = {0, }; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static GdkAtom clipboard_atom = GDK_NONE; -static GalViewCollection *collection = NULL; - -enum { - ESB_FULL_NAME, - ESB_EMAIL, - ESB_ANY -}; - -#if 0 -static ESearchBarItem addressbook_search_option_items[] = { - { N_("Name begins with"), ESB_FULL_NAME, ESB_ITEMTYPE_RADIO }, - { N_("Email begins with"), ESB_EMAIL, ESB_ITEMTYPE_RADIO }, - { N_("Any field contains"), ESB_ANY, ESB_ITEMTYPE_RADIO }, - { NULL, -1, 0 } -}; -#endif - -static ESearchBarItem addressbook_search_items[] = { - E_FILTERBAR_ADVANCED, - {NULL, 0, 0}, - E_FILTERBAR_SAVE, - E_FILTERBAR_EDIT, - {NULL, -1, 0} -}; - -GType -eab_view_get_type (void) +static void +addressbook_view_emit_open_contact (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact) { - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EABViewClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_view_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABView), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_view_init, - }; - - type = g_type_register_static (GTK_TYPE_VBOX, "EABView", &info, 0); - } - - return type; + g_signal_emit (view, signals[OPEN_CONTACT], 0, contact, is_new_contact); } static void -eab_view_class_init (EABViewClass *class) +addressbook_view_emit_popup_event (EAddressbookView *view, + GdkEvent *event) { - GObjectClass *object_class; - - parent_class = g_type_class_peek_parent (class); - - object_class = G_OBJECT_CLASS(class); - object_class->set_property = eab_view_set_property; - object_class->get_property = eab_view_get_property; - object_class->dispose = eab_view_dispose; - - g_object_class_install_property (object_class, PROP_BOOK, - g_param_spec_object ("book", - _("Book"), - /*_( */"XXX blurb" /*)*/, - E_TYPE_BOOK, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_SOURCE, - g_param_spec_object ("source", - _("Source"), - /*_( */"XXX blurb" /*)*/, - E_TYPE_SOURCE, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_QUERY, - g_param_spec_string ("query", - _("Query"), - /*_( */"XXX blurb" /*)*/, - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, PROP_TYPE, - g_param_spec_int ("type", - _("Type"), - /*_( */"XXX blurb" /*)*/, - EAB_VIEW_NONE, - EAB_VIEW_TABLE, - EAB_VIEW_NONE, - G_PARAM_READWRITE)); - - eab_view_signals [STATUS_MESSAGE] = - g_signal_new ("status_message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, status_message), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - eab_view_signals [SEARCH_RESULT] = - g_signal_new ("search_result", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, search_result), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); - - eab_view_signals [FOLDER_BAR_MESSAGE] = - g_signal_new ("folder_bar_message", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, folder_bar_message), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - eab_view_signals [COMMAND_STATE_CHANGE] = - g_signal_new ("command_state_change", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EABViewClass, command_state_change), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - if (!clipboard_atom) - clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); - - /* init the accessibility support for e_addressbook_view */ - eab_view_a11y_init(); + g_signal_emit (view, signals[POPUP_EVENT], 0, event); } static void -eab_view_init (EABView *eav) +addressbook_view_emit_selection_change (EAddressbookView *view) { - eav->view_type = EAB_VIEW_NONE; - - eav->model = NULL; - eav->object = NULL; - eav->widget = NULL; - eav->contact_display_window = NULL; - eav->contact_display = NULL; - eav->displayed_contact = -1; - - eav->view_instance = NULL; - eav->view_menus = NULL; - eav->current_view = NULL; - eav->uic = NULL; - - eav->book = NULL; - eav->source = NULL; - eav->query = NULL; - - eav->invisible = NULL; - eav->clipboard_contacts = NULL; + g_signal_emit (view, signals[SELECTION_CHANGE], 0); } static void -eab_view_dispose (GObject *object) +addressbook_view_open_contact (EAddressbookView *view, + EContact *contact) { - EABView *eav = EAB_VIEW(object); - - e_categories_unregister_change_listener (G_CALLBACK (categories_changed_cb), eav); - - if (eav->model) { - g_signal_handlers_disconnect_matched (eav->model, - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - object); - g_object_unref (eav->model); - eav->model = NULL; - } - - if (eav->book) { - g_object_unref (eav->book); - eav->book = NULL; - } - - if (eav->source) { - g_object_unref (eav->source); - eav->source = NULL; - } - - if (eav->query) { - g_free(eav->query); - eav->query = NULL; - } - - eav->uic = NULL; - - if (eav->view_instance) { - g_object_unref (eav->view_instance); - eav->view_instance = NULL; - } - - if (eav->view_menus) { - g_object_unref (eav->view_menus); - eav->view_menus = NULL; - } - - if (eav->clipboard_contacts) { - g_list_foreach (eav->clipboard_contacts, (GFunc)g_object_unref, NULL); - g_list_free (eav->clipboard_contacts); - eav->clipboard_contacts = NULL; - } - - if (eav->invisible) { - gtk_widget_destroy (eav->invisible); - eav->invisible = NULL; - } - - /* - if (eav->search_context) { - g_object_unref (eav->search_context); - eav->search_context = NULL; - } - */ - - if (eav->search_rule) { - g_object_unref (eav->search_rule); - eav->search_rule = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); + addressbook_view_emit_open_contact (view, contact, FALSE); } static void -set_paned_position (EABView *eav) +addressbook_view_create_contact (EAddressbookView *view) { - GConfClient *gconf_client; - gint pos; - - /* XXX this should use the addressbook's global gconf client */ - gconf_client = gconf_client_get_default (); - pos = gconf_client_get_int (gconf_client, "/apps/evolution/addressbook/display/vpane_position", NULL); - if (pos < 1) - pos = 144; - - gtk_paned_set_position (GTK_PANED (eav->paned), pos); + EContact *contact; - g_object_unref (gconf_client); + contact = e_contact_new (); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); } -static gboolean -get_paned_position (EABView *eav) +static void +addressbook_view_create_contact_list (EAddressbookView *view) { - GConfClient *gconf_client; - gint pos; - - /* XXX this should use the addressbook's global gconf client */ - gconf_client = gconf_client_get_default (); - - pos = gtk_paned_get_position (GTK_PANED (eav->paned)); - gconf_client_set_int (gconf_client, "/apps/evolution/addressbook/display/vpane_position", pos, NULL); - - g_object_unref (gconf_client); + EContact *contact; - return FALSE; + contact = e_contact_new (); + e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE)); + addressbook_view_emit_open_contact (view, contact, TRUE); + g_object_unref (contact); } -GtkWidget* -eab_view_new (void) +static void +table_double_click (ETableScrolled *table, + gint row, + gint col, + GdkEvent *event, + EAddressbookView *view) { - GtkWidget *widget = GTK_WIDGET (g_object_new (E_TYPE_AB_VIEW, NULL)); - EABView *eav = EAB_VIEW (widget); - FilterPart *part; - gchar *xmlfile; - gchar *userfile; - - /* create our model */ - eav->model = eab_model_new (); - - g_signal_connect (eav->model, "status_message", - G_CALLBACK (status_message), eav); - g_signal_connect (eav->model, "search_result", - G_CALLBACK (search_result), eav); - g_signal_connect (eav->model, "folder_bar_message", - G_CALLBACK (folder_bar_message), eav); - g_signal_connect (eav->model, "stop_state_changed", - G_CALLBACK (stop_state_changed), eav); - g_signal_connect (eav->model, "writable_status", - G_CALLBACK (writable_status), eav); - g_signal_connect (eav->model, "backend_died", - G_CALLBACK (backend_died), eav); - g_signal_connect (eav->model, "contact_changed", - G_CALLBACK (contact_changed), eav); - g_signal_connect (eav->model, "contacts_removed", - G_CALLBACK (contacts_removed), eav); - - eav->editable = FALSE; - eav->query = g_strdup (SHOW_ALL_SEARCH); - - /* create the search context */ - eav->search_context = rule_context_new (); - rule_context_add_part_set (eav->search_context, "partset", filter_part_get_type (), - rule_context_add_part, rule_context_next_part); - rule_context_add_rule_set (eav->search_context, "ruleset", filter_rule_get_type (), - rule_context_add_rule, rule_context_next_rule); - - userfile = g_build_filename ( g_get_home_dir (), ".evolution/addressbook/searches.xml", NULL); - xmlfile = g_build_filename (SEARCH_RULE_DIR, "addresstypes.xml", NULL); - - g_object_set_data_full (G_OBJECT (eav->search_context), "user", userfile, g_free); - g_object_set_data_full (G_OBJECT (eav->search_context), "system", xmlfile, g_free); - - rule_context_load (eav->search_context, xmlfile, userfile); - - eav->search_rule = filter_rule_new (); - part = rule_context_next_part (eav->search_context, NULL); - - if (part == NULL) - g_warning ("Could not load addressbook search; no parts."); - else - filter_rule_add_part (eav->search_rule, filter_part_clone (part)); - - eav->search = e_filter_bar_new (eav->search_context, xmlfile, userfile, NULL, eav); - - g_free (xmlfile); - g_free (userfile); - - e_search_bar_set_menu ( (ESearchBar *) eav->search, addressbook_search_items); - gtk_widget_show (GTK_WIDGET (eav->search)); - make_suboptions (eav); - - e_categories_register_change_listener (G_CALLBACK (categories_changed_cb), eav); - - g_signal_connect (eav->search, "query_changed", - G_CALLBACK (query_changed), eav); - g_signal_connect (eav->search, "search_activated", - G_CALLBACK (search_activated), eav); - g_signal_connect (eav->search, "menu_activated", - G_CALLBACK (search_menu_activated), eav); - - gtk_box_pack_start (GTK_BOX (eav), GTK_WIDGET (eav->search), FALSE, FALSE, 0); - - /* create the paned window and contact display */ - eav->paned = gtk_vpaned_new (); - gtk_box_pack_start (GTK_BOX (eav), eav->paned, TRUE, TRUE, 0); - g_signal_connect_swapped (eav->paned, "button_release_event", - G_CALLBACK (get_paned_position), eav); - - eav->contact_display = eab_contact_display_new (); - eav->contact_display_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (eav->contact_display_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (eav->contact_display_window), GTK_SHADOW_IN); - gtk_container_add (GTK_CONTAINER (eav->contact_display_window), eav->contact_display); - gtk_paned_add2 (GTK_PANED (eav->paned), eav->contact_display_window); - gtk_widget_show (eav->contact_display); - gtk_widget_show (eav->contact_display_window); - gtk_widget_show (eav->paned); - - /* gtk selection crap */ - eav->invisible = gtk_invisible_new (); - - gtk_selection_add_target (eav->invisible, - clipboard_atom, - GDK_SELECTION_TYPE_STRING, - 0); - - g_signal_connect (eav->invisible, "selection_get", - G_CALLBACK (selection_get), - eav); - g_signal_connect (eav->invisible, "selection_clear_event", - G_CALLBACK (selection_clear_event), - eav); - g_signal_connect (eav->invisible, "selection_received", - G_CALLBACK (selection_received), - eav); - g_object_weak_ref (G_OBJECT (eav->invisible), invisible_destroyed, eav); + EAddressbookModel *model; + EContact *contact; - return widget; -} + if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) + return; -RuleContext * -eab_view_peek_search_context (EABView *view) -{ - return view->search_context; + model = e_addressbook_view_get_model (view); + contact = e_addressbook_model_get_contact (model, row); + addressbook_view_emit_open_contact (view, contact, FALSE); + g_object_unref (contact); } -FilterRule * -eab_view_peek_search_rule (EABView *view) +static gint +table_right_click (ETableScrolled *table, + gint row, + gint col, + GdkEvent *event, + EAddressbookView *view) { - return view->search_rule; -} + addressbook_view_emit_popup_event (view, event); -static void -writable_status (GtkObject *object, gboolean writable, EABView *eav) -{ - eav->editable = writable; - command_state_change (eav); + return TRUE; } -static void -init_collection (void) +static gint +table_white_space_event (ETableScrolled *table, + GdkEvent *event, + EAddressbookView *view) { - GalViewFactory *factory; - ETableSpecification *spec; - gchar *galview; - gchar *addressbookdir; - gchar *etspecfile; + gint button = ((GdkEventButton *) event)->button; - if (collection == NULL) { - collection = gal_view_collection_new(); - - gal_view_collection_set_title (collection, _("Address Book")); - - galview = g_build_filename ( - e_get_user_data_dir (), "addressbook", "views", NULL); - addressbookdir = g_build_filename (EVOLUTION_GALVIEWSDIR, - "addressbook", - NULL); - gal_view_collection_set_storage_directories - (collection, - addressbookdir, - galview); - g_free(addressbookdir); - g_free(galview); - - spec = e_table_specification_new(); - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "e-addressbook-view.etspec", - NULL); - if (!e_table_specification_load_from_file (spec, etspecfile)) - g_error ("Unable to load ETable specification file " - "for address book"); - g_free (etspecfile); - - factory = gal_view_factory_etable_new (spec); - g_object_unref (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = gal_view_factory_minicard_new(); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - gal_view_collection_load(collection); + if (event->type == GDK_BUTTON_PRESS && button == 3) { + addressbook_view_emit_popup_event (view, event); + return TRUE; } + + return FALSE; } static void -set_view_preview (EABView *view) -{ - /* XXX this should use the addressbook's global gconf client */ - GConfClient *gconf_client; - gboolean state; +table_drag_data_get (ETable *table, + gint row, + gint col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer user_data) +{ + EAddressbookView *view = user_data; + EAddressbookModel *model; + EBook *book; + GList *contact_list; + gchar *value; - gconf_client = gconf_client_get_default(); - state = gconf_client_get_bool(gconf_client, "/apps/evolution/addressbook/display/show_preview", NULL); - bonobo_ui_component_set_prop (view->uic, - "/commands/ContactsViewPreview", - "state", - state ? "1" : "0", NULL); + if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object)) + return; - eab_view_show_contact_preview (view, state); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); - g_object_unref (gconf_client); -} + contact_list = e_addressbook_view_get_selected (view); -static void -display_view(GalViewInstance *instance, - GalView *view, - gpointer data) -{ - EABView *address_view = data; - if (GAL_IS_VIEW_ETABLE(view)) { - change_view_type (address_view, EAB_VIEW_TABLE); - gal_view_etable_attach_table (GAL_VIEW_ETABLE(view), e_table_scrolled_get_table(E_TABLE_SCROLLED(address_view->widget))); - } - else if (GAL_IS_VIEW_MINICARD(view)) { - change_view_type (address_view, EAB_VIEW_MINICARD); - gal_view_minicard_attach (GAL_VIEW_MINICARD (view), address_view); - } - address_view->current_view = view; + switch (info) { + case DND_TARGET_TYPE_VCARD: + value = eab_contact_list_to_string (contact_list); - set_paned_position (address_view); - set_view_preview (address_view); -} + gtk_selection_data_set ( + selection_data, selection_data->target, + 8, (guchar *)value, strlen (value)); -static void -view_preview(BonoboUIComponent *uic, const gchar *path, Bonobo_UIComponent_EventType type, const gchar *state, gpointer data) -{ - /* XXX this should use the addressbook's global gconf client */ - GConfClient *gconf_client; - EABView *view = EAB_VIEW (data); + g_free (value); + break; - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; + case DND_TARGET_TYPE_SOURCE_VCARD: + value = eab_book_and_contact_list_to_string ( + book, contact_list); - gconf_client = gconf_client_get_default(); - gconf_client_set_bool(gconf_client, "/apps/evolution/addressbook/display/show_preview", state[0] != '0', NULL); + gtk_selection_data_set ( + selection_data, selection_data->target, + 8, (guchar *)value, strlen (value)); - eab_view_show_contact_preview(view, state[0] != '0'); + g_free (value); + break; + } - g_object_unref (gconf_client); + g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); + g_list_free (contact_list); } static void -setup_menus (EABView *view) +addressbook_view_create_table_view (EAddressbookView *view) { - if (view->book && view->view_instance == NULL) { - init_collection (); - view->view_instance = gal_view_instance_new (collection, e_book_get_uri (view->book)); - } - - if (view->view_instance && view->uic) { - view->view_menus = gal_view_menus_new(view->view_instance); - gal_view_menus_apply(view->view_menus, view->uic, NULL); + ETableModel *adapter; + ETableExtras *extras; + ECell *cell; + ETable *table; + GtkWidget *widget; + gchar *etspecfile; - display_view (view->view_instance, gal_view_instance_get_current_view (view->view_instance), view); + adapter = eab_table_adapter_new (view->priv->model); - g_signal_connect(view->view_instance, "display_view", - G_CALLBACK (display_view), view); - } + extras = e_table_extras_new (); - bonobo_ui_component_add_listener(view->uic, "ContactsViewPreview", view_preview, view); + /* Set proper format component for a default 'date' cell renderer. */ + cell = e_table_extras_get_cell (extras, "date"); + e_cell_date_set_format_component (E_CELL_DATE (cell), "addressbook"); - set_view_preview (view); -} + /* Here we create the table. We give it the three pieces of + the table we've created, the header, the model, and the + initial layout. It does the rest. */ + etspecfile = g_build_filename ( + EVOLUTION_ETSPECDIR, "e-addressbook-view.etspec", NULL); + widget = e_table_scrolled_new_from_spec_file ( + adapter, extras, etspecfile, NULL); + table = E_TABLE (E_TABLE_SCROLLED (widget)->table); + g_free (etspecfile); -static void -eab_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - EABView *eav = EAB_VIEW(object); + view->priv->object = G_OBJECT (adapter); + view->priv->widget = widget; - switch (prop_id) { - case PROP_BOOK: - if (eav->book) { - g_object_unref (eav->book); - } - if (g_value_get_object (value)) { - eav->book = E_BOOK(g_value_get_object (value)); - g_object_ref (eav->book); - gtk_widget_set_sensitive (GTK_WIDGET (eav->search), TRUE); - } - else { - eav->book = NULL; - gtk_widget_set_sensitive (GTK_WIDGET (eav->search), FALSE); - } + g_signal_connect ( + table, "double_click", + G_CALLBACK(table_double_click), view); + g_signal_connect ( + table, "right_click", + G_CALLBACK(table_right_click), view); + g_signal_connect ( + table, "white_space_event", + G_CALLBACK(table_white_space_event), view); + g_signal_connect_swapped ( + table, "selection_change", + G_CALLBACK (addressbook_view_emit_selection_change), view); - if (eav->view_instance) { - g_object_unref (eav->view_instance); - eav->view_instance = NULL; - } + e_table_drag_source_set ( + table, GDK_BUTTON1_MASK, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); - g_object_set(eav->model, - "book", eav->book, - NULL); + g_signal_connect ( + table, "table_drag_data_get", + G_CALLBACK (table_drag_data_get), view); - setup_menus (eav); + gtk_box_pack_start (GTK_BOX (view), widget, TRUE, TRUE, 0); - break; - case PROP_SOURCE: - if (eav->source) { - g_warning ("EABView at present does not support multiple writes on the \"source\" property."); - break; - } - else { - if (g_value_get_object (value)) { - eav->source = E_SOURCE(g_value_get_object (value)); - g_object_ref (eav->source); - } - else { - eav->source = NULL; - } - } - break; - case PROP_QUERY: -#if 0 /* This code will mess up ldap a bit. We need to think about the ramifications of this more. */ - if ((g_value_get_string (value) == NULL && !strcmp (eav->query, SHOW_ALL_SEARCH)) || - (g_value_get_string (value) != NULL && !strcmp (eav->query, g_value_get_string (value)))) - break; -#endif - g_free(eav->query); - eav->query = g_strdup(g_value_get_string (value)); - if (!eav->query) - eav->query = g_strdup (SHOW_ALL_SEARCH); - g_object_set(eav->model, - "query", eav->query, - NULL); - break; - case PROP_TYPE: - change_view_type(eav, g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + gtk_widget_show (widget); } static void -eab_view_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +addressbook_view_create_minicard_view (EAddressbookView *view) { - EABView *eav = EAB_VIEW(object); + GtkWidget *scrolled_window; + GtkWidget *minicard_view; + EAddressbookReflowAdapter *adapter; - switch (prop_id) { - case PROP_BOOK: - if (eav->book) - g_value_set_object (value, eav->book); - else - g_value_set_object (value, NULL); - break; - case PROP_SOURCE: - if (eav->source) - g_value_set_object (value, eav->source); - else - g_value_set_object (value, NULL); - break; - - case PROP_QUERY: - g_value_set_string (value, eav->query); - break; - case PROP_TYPE: - g_value_set_int (value, eav->view_type); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} + adapter = E_ADDRESSBOOK_REFLOW_ADAPTER ( + e_addressbook_reflow_adapter_new (view->priv->model)); + minicard_view = e_minicard_view_widget_new (adapter); -static ESelectionModel* -get_selection_model (EABView *view) -{ - if (view->view_type == EAB_VIEW_TABLE) - return e_table_get_selection_model (e_table_scrolled_get_table (E_TABLE_SCROLLED(view->widget))); - else if (view->view_type == EAB_VIEW_MINICARD) - return e_minicard_view_widget_get_selection_model (E_MINICARD_VIEW_WIDGET(view->object)); - g_return_val_if_reached (NULL); -} + g_signal_connect_swapped ( + adapter, "open-contact", + G_CALLBACK (addressbook_view_open_contact), view); -/* Popup menu stuff */ -typedef struct { - EABView *view; - gpointer closure; -} ContactAndBook; + g_signal_connect_swapped ( + minicard_view, "create-contact", + G_CALLBACK (addressbook_view_create_contact), view); -static ESelectionModel* -contact_and_book_get_selection_model (ContactAndBook *contact_and_book) -{ - return get_selection_model (contact_and_book->view); -} + g_signal_connect_swapped ( + minicard_view, "create-contact-list", + G_CALLBACK (addressbook_view_create_contact_list), view); -static GList * -get_contact_list (EABPopupTargetSelect *t) -{ - GList *list = NULL; - gint i; + g_signal_connect_swapped ( + minicard_view, "selection_change", + G_CALLBACK (addressbook_view_emit_selection_change), view); - for (i=0;i<t->cards->len;i++) - list = g_list_prepend(list, t->cards->pdata[i]); + g_signal_connect_swapped ( + minicard_view, "right_click", + G_CALLBACK (addressbook_view_emit_popup_event), view); - return list; -} + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); -static void -save_as (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - /*ContactAndBook *contact_and_book = data;*/ - GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); + view->priv->object = G_OBJECT (minicard_view); + view->priv->widget = scrolled_window; - if (contacts) { - eab_contact_list_save(_("Save as vCard..."), contacts, NULL); - g_list_free(contacts); - } -} + gtk_container_add (GTK_CONTAINER (scrolled_window), minicard_view); + gtk_widget_show (minicard_view); -static void -send_as (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - /*ContactAndBook *contact_and_book = data;*/ - GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); + gtk_widget_show_all (scrolled_window); - if (contacts) { - eab_send_contact_list(contacts, EAB_DISPOSITION_AS_ATTACHMENT); - g_list_free(contacts); - } + gtk_box_pack_start (GTK_BOX (view), scrolled_window, TRUE, TRUE, 0); + + e_reflow_model_changed (E_REFLOW_MODEL (adapter)); } static void -send_to (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - /*ContactAndBook *contact_and_book = data;*/ - GList *contacts = get_contact_list ((EABPopupTargetSelect *)ep->target); - - if (contacts) { - eab_send_contact_list(contacts, EAB_DISPOSITION_AS_TO); - g_list_free(contacts); +addressbook_view_display_view_cb (EAddressbookView *view, + GalView *gal_view) +{ + if (view->priv->widget != NULL) { + gtk_container_remove ( + GTK_CONTAINER (view), + view->priv->widget); + view->priv->widget = NULL; } + view->priv->object = NULL; + + if (GAL_IS_VIEW_ETABLE (gal_view)) { + addressbook_view_create_table_view (view); + gal_view_etable_attach_table ( + GAL_VIEW_ETABLE (gal_view), + e_table_scrolled_get_table ( + E_TABLE_SCROLLED (view->priv->widget))); + } + else if (GAL_IS_VIEW_MINICARD (gal_view)) { + addressbook_view_create_minicard_view (view); + gal_view_minicard_attach ( + GAL_VIEW_MINICARD (gal_view), view); + } + + command_state_change (view); } static void -print (EPopup *ep, EPopupItem *pitem, gpointer data) +addressbook_view_selection_get_cb (EAddressbookView *view, + GtkSelectionData *selection_data, + guint info, + guint time_stamp) { - /*ContactAndBook *contact_and_book = data;*/ - EABPopupTargetSelect *t = (EABPopupTargetSelect *)ep->target; - GList *contact_list; + gchar *string; - contact_list = get_contact_list (t); - e_contact_print ( - NULL, NULL, contact_list, - GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); - g_list_free (contact_list); -} + string = eab_contact_list_to_string (view->priv->clipboard_contacts); -static void -copy (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - ContactAndBook *contact_and_book = data; + gtk_selection_data_set ( + selection_data, GDK_SELECTION_TYPE_STRING, + 8, (guchar *) string, strlen (string)); - eab_view_copy (contact_and_book->view); + g_free (string); } static void -paste (EPopup *ep, EPopupItem *pitem, gpointer data) +addressbook_view_selection_clear_event_cb (EAddressbookView *view, + GdkEventSelection *event) { - ContactAndBook *contact_and_book = data; + GList *list; - eab_view_paste (contact_and_book->view); + list = view->priv->clipboard_contacts; + view->priv->clipboard_contacts = NULL; + + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } static void -cut (EPopup *ep, EPopupItem *pitem, gpointer data) +addressbook_view_selection_received_cb (EAddressbookView *view, + GtkSelectionData *selection_data, + guint time) { - ContactAndBook *contact_and_book = data; + EAddressbookModel *model; + GList *list, *iter; + EBook *book; - eab_view_cut (contact_and_book->view); -} + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); -static void -delete (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - ContactAndBook *contact_and_book = data; + if (selection_data->length <= 0) + return; - eab_view_delete_selection(contact_and_book->view, TRUE); -} + if (selection_data->type != GDK_SELECTION_TYPE_STRING) + return; -static void -copy_to_folder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - ContactAndBook *contact_and_book = data; + if (selection_data->data[selection_data->length - 1] != 0) { + gchar *string; - eab_view_copy_to_folder (contact_and_book->view, FALSE); -} + string = g_malloc0 (selection_data->length + 1); + memcpy (string, selection_data->data, selection_data->length); + list = eab_contact_list_from_string (string); + g_free (string); + } else + list = eab_contact_list_from_string ( + (gchar *) selection_data->data); -static void -move_to_folder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - ContactAndBook *contact_and_book = data; + for (iter = list; iter != NULL; iter = iter->next) { + EContact *contact = iter->data; - eab_view_move_to_folder (contact_and_book->view, FALSE); + /* XXX NULL for a callback /sigh */ + eab_merging_book_add_contact ( + book, contact, NULL /* XXX */, NULL); + } + + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } static void -open_contact (EPopup *ep, EPopupItem *pitem, gpointer data) +addressbook_view_set_shell_view (EAddressbookView *view, + EShellView *shell_view) { - ContactAndBook *contact_and_book = data; + g_return_if_fail (view->priv->shell_view == NULL); - eab_view_view (contact_and_book->view); + view->priv->shell_view = shell_view; + + g_object_add_weak_pointer ( + G_OBJECT (shell_view), + &view->priv->shell_view); } static void -new_card (EPopup *ep, EPopupItem *pitem, gpointer data) +addressbook_view_set_source (EAddressbookView *view, + ESource *source) { - /*ContactAndBook *contact_and_book = data;*/ - EContact *contact = e_contact_new(); + g_return_if_fail (view->priv->source == NULL); - eab_show_contact_editor (((EABPopupTargetSelect *)ep->target)->book, contact, TRUE, TRUE); - g_object_unref (contact); + view->priv->source = g_object_ref (source); } static void -new_list (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - /*ContactAndBook *contact_and_book = data;*/ - EContact *contact = e_contact_new (); +addressbook_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SHELL_VIEW: + addressbook_view_set_shell_view ( + E_ADDRESSBOOK_VIEW (object), + g_value_get_object (value)); + return; + + case PROP_SOURCE: + addressbook_view_set_source ( + E_ADDRESSBOOK_VIEW (object), + g_value_get_object (value)); + return; + } - eab_show_contact_list_editor (((EABPopupTargetSelect *)ep->target)->book, contact, TRUE, TRUE); - g_object_unref(contact); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static EPopupItem eabv_popup_items[] = { - { E_POPUP_ITEM, (gchar *) "05.open", (gchar *) N_("_Open"), open_contact, NULL, NULL, EAB_POPUP_SELECT_ANY|EAB_POPUP_SELECT_EDITABLE }, - { E_POPUP_BAR, (gchar *) "10.bar" }, - { E_POPUP_ITEM, (gchar *) "10.new", (gchar *) N_("_New Contact..."), new_card, NULL, (gchar *) "contact-new", 0, EAB_POPUP_SELECT_EDITABLE}, - { E_POPUP_ITEM, (gchar *) "15.newlist", (gchar *) N_("New Contact _List..."), new_list, NULL, (gchar *) "stock_contact-list", 0, EAB_POPUP_SELECT_EDITABLE }, - - { E_POPUP_BAR, (gchar *) "20.bar" }, - { E_POPUP_ITEM, (gchar *) "30.saveas", (gchar *) N_("_Save as vCard..."), save_as, NULL, (gchar *) "document-save-as", 0, EAB_POPUP_SELECT_ANY }, - { E_POPUP_ITEM, (gchar *) "40.forward", (gchar *) N_("_Forward Contact"), send_as, NULL, (gchar *) "mail-forward", EAB_POPUP_SELECT_ONE }, - { E_POPUP_ITEM, (gchar *) "40.forward", (gchar *) N_("_Forward Contacts"), send_as, NULL, (gchar *) "mail-forward", EAB_POPUP_SELECT_MANY }, - { E_POPUP_ITEM, (gchar *) "50.mailto", (gchar *) N_("Send _Message to Contact"), send_to, NULL, (gchar *) "mail-message-new", EAB_POPUP_SELECT_ONE|EAB_POPUP_SELECT_EMAIL|EAB_POPUP_CONTACT }, - { E_POPUP_ITEM, (gchar *) "50.mailto", (gchar *) N_("Send _Message to List"), send_to, NULL, (gchar *) "mail-message-new", EAB_POPUP_SELECT_ONE|EAB_POPUP_SELECT_EMAIL|EAB_POPUP_LIST }, - { E_POPUP_ITEM, (gchar *) "50.mailto", (gchar *) N_("Send _Message to Contacts"), send_to, NULL, (gchar *) "mail-message-new", EAB_POPUP_SELECT_MANY|EAB_POPUP_SELECT_EMAIL }, - { E_POPUP_ITEM, (gchar *) "60.print", (gchar *) N_("_Print"), print, NULL, (gchar *) "document-print", 0, EAB_POPUP_SELECT_ANY }, - - { E_POPUP_BAR, (gchar *) "70.bar" }, - { E_POPUP_ITEM, (gchar *) "80.copyto", (gchar *) N_("Cop_y to Address Book..."), copy_to_folder, NULL, NULL, 0, EAB_POPUP_SELECT_ANY }, - { E_POPUP_ITEM, (gchar *) "90.moveto", (gchar *) N_("Mo_ve to Address Book..."), move_to_folder, NULL, NULL, 0, EAB_POPUP_SELECT_ANY|EAB_POPUP_SELECT_EDITABLE }, - - { E_POPUP_BAR, (gchar *) "a0.bar" }, - { E_POPUP_ITEM, (gchar *) "b0.cut", (gchar *) N_("Cu_t"), cut, NULL, (gchar *) "edit-cut", 0, EAB_POPUP_SELECT_ANY|EAB_POPUP_SELECT_EDITABLE }, - { E_POPUP_ITEM, (gchar *) "c0.copy", (gchar *) N_("_Copy"), copy, NULL, (gchar *) "edit-copy", 0, EAB_POPUP_SELECT_ANY }, - { E_POPUP_ITEM, (gchar *) "d0.paste", (gchar *) N_("P_aste"), paste, NULL, (gchar *) "edit-paste", 0, EAB_POPUP_SELECT_EDITABLE }, - { E_POPUP_ITEM, (gchar *) "e0.delete", (gchar *) N_("_Delete"), delete, NULL, (gchar *) "edit-delete", 0, EAB_POPUP_SELECT_EDITABLE|EAB_POPUP_SELECT_ANY }, -}; - static void -get_card_1(gint model_row, gpointer data) -{ - ContactAndBook *contact_and_book = data; - EContact *contact; +addressbook_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_MODEL: + g_value_set_object ( + value, e_addressbook_view_get_model ( + E_ADDRESSBOOK_VIEW (object))); + return; + + case PROP_SHELL_VIEW: + g_value_set_object ( + value, e_addressbook_view_get_shell_view ( + E_ADDRESSBOOK_VIEW (object))); + return; + + case PROP_SOURCE: + g_value_set_object ( + value, e_addressbook_view_get_source ( + E_ADDRESSBOOK_VIEW (object))); + return; + } - contact = eab_model_get_contact(contact_and_book->view->model, model_row); - if (contact) - g_ptr_array_add((GPtrArray *)contact_and_book->closure, contact); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -eabv_popup_free(EPopup *ep, GSList *list, gpointer data) +addressbook_view_dispose (GObject *object) { - ContactAndBook *cab = data; - ESelectionModel *selection; + EAddressbookViewPrivate *priv; - /* NB: this looks strange to me */ - selection = contact_and_book_get_selection_model(cab); - if (selection) - e_selection_model_right_click_up(selection); + priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (object); - g_slist_free(list); - g_object_unref(cab->view); - g_free(cab); -} + if (priv->shell_view != NULL) { + g_object_remove_weak_pointer ( + G_OBJECT (priv->shell_view), + &priv->shell_view); + priv->shell_view = NULL; + } -static void -do_popup_menu(EABView *view, GdkEvent *event) -{ - EABPopup *ep; - EABPopupTargetSelect *t; - GSList *menus = NULL; - gint i; - GtkMenu *menu; - GPtrArray *cards = g_ptr_array_new(); - ContactAndBook *contact_and_book; - ESelectionModel *selection_model; - - contact_and_book = g_new(ContactAndBook, 1); - contact_and_book->view = view; - g_object_ref(contact_and_book->view); - - selection_model = contact_and_book_get_selection_model(contact_and_book); - if (selection_model) { - contact_and_book->closure = cards; - e_selection_model_foreach(selection_model, get_card_1, contact_and_book); + if (priv->model != NULL) { + g_signal_handlers_disconnect_matched ( + priv->model, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->model); + priv->model = NULL; + } + + if (priv->activity != NULL) { + /* XXX Activity is not cancellable. */ + e_activity_complete (priv->activity); + g_object_unref (priv->activity); + priv->activity = NULL; } - /** @HookPoint-EABPopup:Addressbook view Context Menu - * @Id: org.gnome.evolution.addressbook.view.popup - * @Class: org.gnome.evolution.addresbook.popup:1.0 - * @Target: EABPopupTargetSelect - * - * The context menu on the contacts view. - */ + if (priv->invisible != NULL) { + gtk_widget_destroy (priv->invisible); + priv->invisible = NULL; + } - ep = eab_popup_new("org.gnome.evolution.addressbook.view.popup"); - t = eab_popup_target_new_select(ep, view->book, !eab_model_editable(view->model), cards); - t->target.widget = (GtkWidget *)view; + if (priv->source != NULL) { + g_object_unref (priv->source); + priv->source = NULL; + } - for (i=0;i<sizeof(eabv_popup_items)/sizeof(eabv_popup_items[0]);i++) - menus = g_slist_prepend(menus, &eabv_popup_items[i]); + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } - e_popup_add_items((EPopup *)ep, menus, NULL, eabv_popup_free, contact_and_book); + g_list_foreach ( + priv->clipboard_contacts, + (GFunc) g_object_unref, NULL); + g_list_free (priv->clipboard_contacts); + priv->clipboard_contacts = NULL; - menu = e_popup_create_menu_once((EPopup *)ep, (EPopupTarget *)t, 0); - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event?event->button.button:0, event?event->button.time:gtk_get_current_event_time()); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -render_contact (gint row, EABView *view) +addressbook_view_constructed (GObject *object) { - EContact *contact = eab_model_get_contact (view->model, row); + EAddressbookView *view = E_ADDRESSBOOK_VIEW (object); + GalViewInstance *view_instance; + EShellView *shell_view; + ESource *source; + gchar *uri; - view->displayed_contact = row; + shell_view = e_addressbook_view_get_shell_view (view); + source = e_addressbook_view_get_source (view); + uri = e_source_get_uri (source); - eab_contact_display_render (EAB_CONTACT_DISPLAY (view->contact_display), contact, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); + view_instance = e_shell_view_new_view_instance (shell_view, uri); + g_signal_connect_swapped ( + view_instance, "display-view", + G_CALLBACK (addressbook_view_display_view_cb), view); + gal_view_instance_load (view_instance); + view->priv->view_instance = view_instance; + + g_free (uri); } static void -selection_changed (GObject *o, EABView *view) +addressbook_view_class_init (EAddressbookViewClass *class) { - ESelectionModel *selection_model; - - command_state_change (view); + GObjectClass *object_class; - selection_model = get_selection_model (view); + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookViewPrivate)); - if (e_selection_model_selected_count (selection_model) == 1) - e_selection_model_foreach (selection_model, - (EForeachFunc)render_contact, view); - else { - view->displayed_contact = -1; - eab_contact_display_render (EAB_CONTACT_DISPLAY (view->contact_display), NULL, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); - } + object_class = G_OBJECT_CLASS(class); + object_class->set_property = addressbook_view_set_property; + object_class->get_property = addressbook_view_get_property; + object_class->dispose = addressbook_view_dispose; + object_class->constructed = addressbook_view_constructed; + + g_object_class_install_property ( + object_class, + PROP_MODEL, + g_param_spec_object ( + "model", + _("Model"), + NULL, + E_TYPE_ADDRESSBOOK_MODEL, + G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, + PROP_SHELL_VIEW, + g_param_spec_object ( + "shell-view", + _("Shell View"), + NULL, + E_TYPE_SHELL_VIEW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_SOURCE, + g_param_spec_object ( + "source", + _("Source"), + NULL, + E_TYPE_SOURCE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[OPEN_CONTACT] = g_signal_new ( + "open-contact", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, open_contact), + NULL, NULL, + e_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + E_TYPE_CONTACT, + G_TYPE_BOOLEAN); + + signals[POPUP_EVENT] = g_signal_new ( + "popup-event", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, popup_event), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + signals[COMMAND_STATE_CHANGE] = g_signal_new ( + "command-state-change", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, command_state_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SELECTION_CHANGE] = g_signal_new ( + "selection-change", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EAddressbookViewClass, selection_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + if (clipboard_atom == NULL) + clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE); + /* init the accessibility support for e_addressbook_view */ + eab_view_a11y_init (); } static void -table_double_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EABView *view) +addressbook_view_init (EAddressbookView *view) { - if (E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) { - EABModel *model = view->model; - EContact *contact = eab_model_get_contact (model, row); - EBook *book; + view->priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (view); - g_object_get(model, - "book", &book, - NULL); + view->priv->model = e_addressbook_model_new (); - g_return_if_fail (E_IS_BOOK (book)); + view->priv->invisible = gtk_invisible_new (); - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - eab_show_contact_list_editor (book, contact, FALSE, view->editable); - else - eab_show_contact_editor (book, contact, FALSE, view->editable); + gtk_selection_add_target ( + view->priv->invisible, clipboard_atom, + GDK_SELECTION_TYPE_STRING, 0); - g_object_unref (book); - g_object_unref (contact); - } + g_signal_connect_swapped ( + view->priv->invisible, "selection-get", + G_CALLBACK (addressbook_view_selection_get_cb), view); + g_signal_connect_swapped ( + view->priv->invisible, "selection-clear-event", + G_CALLBACK (addressbook_view_selection_clear_event_cb), view); + g_signal_connect_swapped ( + view->priv->invisible, "selection-received", + G_CALLBACK (addressbook_view_selection_received_cb), view); } -static gint -table_right_click(ETableScrolled *table, gint row, gint col, GdkEvent *event, EABView *view) +GType +e_addressbook_view_get_type (void) { - do_popup_menu(view, event); - return TRUE; -} + static GType type = 0; -static gint -table_white_space_event(ETableScrolled *table, GdkEvent *event, EABView *view) -{ - if (event->type == GDK_BUTTON_PRESS && ((GdkEventButton *)event)->button == 3) { - do_popup_menu(view, event); - return TRUE; - } else { - return FALSE; + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EAddressbookViewClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_view_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookView), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_view_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_VBOX, "EAddressbookView", &type_info, 0); } + + return type; } -static void -table_drag_data_get (ETable *table, - gint row, - gint col, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time, - gpointer user_data) +GtkWidget * +e_addressbook_view_new (EShellView *shell_view, + ESource *source) { - EABView *view = user_data; - GList *contact_list; - - if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER(view->object)) - return; - - contact_list = get_selected_contacts (view); - - switch (info) { - case DND_TARGET_TYPE_VCARD: { - gchar *value; + GtkWidget *widget; + EAddressbookView *view; - value = eab_contact_list_to_string (contact_list); + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - gtk_selection_data_set (selection_data, - selection_data->target, - 8, - (guchar *)value, strlen (value)); - g_free (value); - break; - } - case DND_TARGET_TYPE_SOURCE_VCARD: { - gchar *value; + widget = g_object_new ( + E_TYPE_ADDRESSBOOK_VIEW, "shell-view", + shell_view, "source", source, NULL); - value = eab_book_and_contact_list_to_string (view->book, contact_list); + view = E_ADDRESSBOOK_VIEW (widget); - gtk_selection_data_set (selection_data, - selection_data->target, - 8, - (guchar *)value, strlen (value)); - g_free (value); - break; - } - } + g_signal_connect_swapped ( + view->priv->model, "status_message", + G_CALLBACK (status_message), view); + g_signal_connect_swapped ( + view->priv->model, "search_result", + G_CALLBACK (search_result), view); + g_signal_connect_swapped ( + view->priv->model, "folder_bar_message", + G_CALLBACK (folder_bar_message), view); + g_signal_connect (view->priv->model, "stop_state_changed", + G_CALLBACK (stop_state_changed), view); + g_signal_connect_swapped ( + view->priv->model, "writable-status", + G_CALLBACK (command_state_change), view); + g_signal_connect_swapped ( + view->priv->model, "backend_died", + G_CALLBACK (backend_died), view); - g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); - g_list_free (contact_list); + return widget; } -static void -emit_status_message (EABView *eav, const gchar *status) +EAddressbookModel * +e_addressbook_view_get_model (EAddressbookView *view) { - g_signal_emit (eav, - eab_view_signals [STATUS_MESSAGE], 0, - status); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -emit_search_result (EABView *eav, EBookViewStatus status) -{ - g_signal_emit (eav, - eab_view_signals [SEARCH_RESULT], 0, - status); + return view->priv->model; } -static void -emit_folder_bar_message (EABView *eav, const gchar *message) +GalViewInstance * +e_addressbook_view_get_view_instance (EAddressbookView *view) { - g_signal_emit (eav, - eab_view_signals [FOLDER_BAR_MESSAGE], 0, - message); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -status_message (GtkObject *object, const gchar *status, EABView *eav) -{ - emit_status_message (eav, status); + return view->priv->view_instance; } -static void -search_result (GtkObject *object, EBookViewStatus status, EABView *eav) +GObject * +e_addressbook_view_get_view_object (EAddressbookView *view) { - emit_search_result (eav, status); -} + /* XXX Find a more descriptive name for this. */ -static void -folder_bar_message (GtkObject *object, const gchar *status, EABView *eav) -{ - emit_folder_bar_message (eav, status); -} + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); -static void -stop_state_changed (GtkObject *object, EABView *eav) -{ - command_state_change (eav); + return view->priv->object; } -static void -command_state_change (EABView *eav) +GtkWidget * +e_addressbook_view_get_view_widget (EAddressbookView *view) { - /* Reffing during emission is unnecessary. Gtk automatically refs during an emission. */ - g_signal_emit (eav, eab_view_signals [COMMAND_STATE_CHANGE], 0); -} + /* XXX Find a more descriptive name for this. */ -static void -backend_died (GtkObject *object, EABView *eav) -{ - e_error_run (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (eav))), - "addressbook:backend-died", e_book_get_uri (eav->book), NULL); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); + + return view->priv->widget; } +/* Helper for e_addressbook_view_get_selected() */ static void -contact_changed (EABModel *model, gint index, EABView *eav) +add_to_list (gint model_row, gpointer closure) { - if (eav->displayed_contact == index) { - /* if the contact that's presently displayed is changed, re-render it */ - render_contact (index, eav); - } + GList **list = closure; + *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); } -static void -contacts_removed (EABModel *model, gpointer data, EABView *eav) +GList * +e_addressbook_view_get_selected (EAddressbookView *view) { - GArray *indices = (GArray *) data; - gint count = indices->len; - gint i; + GList *list, *iter; + ESelectionModel *selection; - for (i = 0; i < count; i ++) { + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - if (eav->displayed_contact == g_array_index (indices, gint, i)) { + list = NULL; + selection = e_addressbook_view_get_selection_model (view); + e_selection_model_foreach (selection, add_to_list, &list); - /* if the contact that's presently displayed is changed, clear the display */ - eab_contact_display_render (EAB_CONTACT_DISPLAY (eav->contact_display), NULL, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); - eav->displayed_contact = -1; - break; - } - } -} + for (iter = list; iter != NULL; iter = iter->next) + iter->data = e_addressbook_model_get_contact ( + view->priv->model, GPOINTER_TO_INT (iter->data)); + list = g_list_reverse (list); -static void -minicard_right_click (EMinicardView *minicard_view_item, GdkEvent *event, EABView *view) -{ - do_popup_menu(view, event); + return list; } -static void -create_minicard_view (EABView *view) +ESelectionModel * +e_addressbook_view_get_selection_model (EAddressbookView *view) { - GtkWidget *scrolled_window; - GtkWidget *minicard_view; - EAddressbookReflowAdapter *adapter; + GalView *gal_view; + GalViewInstance *view_instance; + ESelectionModel *model = NULL; - adapter = E_ADDRESSBOOK_REFLOW_ADAPTER(e_addressbook_reflow_adapter_new (view->model)); - minicard_view = e_minicard_view_widget_new(adapter); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - g_signal_connect(minicard_view, "selection_change", - G_CALLBACK(selection_changed), view); + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); - g_signal_connect(minicard_view, "right_click", - G_CALLBACK(minicard_right_click), view); + if (GAL_IS_VIEW_ETABLE (gal_view)) { + ETableScrolled *scrolled_table; + ETable *table; - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); + scrolled_table = E_TABLE_SCROLLED (view->priv->widget); + table = e_table_scrolled_get_table (scrolled_table); - view->object = G_OBJECT(minicard_view); - view->widget = scrolled_window; + model = e_table_get_selection_model (table); - gtk_container_add (GTK_CONTAINER (scrolled_window), minicard_view); - gtk_widget_show (minicard_view); + } else if (GAL_IS_VIEW_MINICARD (gal_view)) { + EMinicardViewWidget *widget; - gtk_widget_show_all( GTK_WIDGET(scrolled_window) ); + widget = E_MINICARD_VIEW_WIDGET (view->priv->object); - gtk_paned_add1 (GTK_PANED (view->paned), scrolled_window); + model = e_minicard_view_widget_get_selection_model (widget); + } - e_reflow_model_changed (E_REFLOW_MODEL (adapter)); + return model; } -static void -create_table_view (EABView *view) +EShellView * +e_addressbook_view_get_shell_view (EAddressbookView *view) { - ETableModel *adapter; - ETableExtras *extras; - ECell *cell; - GtkWidget *table; - gchar *etspecfile; + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - adapter = eab_table_adapter_new(view->model); - - extras = e_table_extras_new (); - - /* set proper format component for a default 'date' cell renderer */ - cell = e_table_extras_get_cell (extras, "date"); - e_cell_date_set_format_component (E_CELL_DATE (cell), "addressbook"); - - /* Here we create the table. We give it the three pieces of - the table we've created, the header, the model, and the - initial layout. It does the rest. */ - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "e-addressbook-view.etspec", - NULL); - table = e_table_scrolled_new_from_spec_file (adapter, extras, etspecfile, NULL); - g_free (etspecfile); - - view->object = G_OBJECT(adapter); - view->widget = table; - - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "double_click", - G_CALLBACK(table_double_click), view); - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "right_click", - G_CALLBACK(table_right_click), view); - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "white_space_event", - G_CALLBACK(table_white_space_event), view); - g_signal_connect(e_table_scrolled_get_table(E_TABLE_SCROLLED(table)), "selection_change", - G_CALLBACK(selection_changed), view); - - /* drag & drop signals */ - e_table_drag_source_set (E_TABLE(E_TABLE_SCROLLED(table)->table), GDK_BUTTON1_MASK, - drag_types, num_drag_types, GDK_ACTION_MOVE | GDK_ACTION_COPY); - - g_signal_connect (E_TABLE_SCROLLED(table)->table, - "table_drag_data_get", - G_CALLBACK (table_drag_data_get), - view); - - gtk_paned_add1 (GTK_PANED (view->paned), table); - - gtk_widget_show( GTK_WIDGET(table) ); + return view->priv->shell_view; } -static void -change_view_type (EABView *view, EABViewType view_type) +ESource * +e_addressbook_view_get_source (EAddressbookView *view) { - if (view_type == view->view_type) - return; - - if (view->widget) { - gtk_container_remove (GTK_CONTAINER (view->paned), view->widget); - view->widget = NULL; - } - view->object = NULL; - - switch (view_type) { - case EAB_VIEW_TABLE: - create_table_view (view); - break; - case EAB_VIEW_MINICARD: - create_minicard_view (view); - break; - default: - g_warning ("view_type not recognized."); - return; - } + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL); - view->view_type = view_type; - - command_state_change (view); + return view->priv->source; } - - static void -search_activated (ESearchBar *esb, EABView *v) -{ - GList *master_list; - gchar *search_word, *search_query, *view_sexp; - const gchar *category_name; - gint search_type, subid; - - g_object_get(esb, - "text", &search_word, - "item_id", &search_type, - NULL); - - if (search_type == E_FILTERBAR_ADVANCED_ID) { - /* rebuild view immediately */ - query_changed (esb, v); - } - else { - if ((search_word && strlen (search_word))) { - GString *s = g_string_new (""); - e_sexp_encode_string (s, search_word); - switch (search_type) { - case ESB_ANY: - search_query = g_strdup_printf ("(contains \"x-evolution-any-field\" %s)", - s->str); - break; - case ESB_FULL_NAME: - search_query = g_strdup_printf ("(contains \"full_name\" %s)", - s->str); - break; - case ESB_EMAIL: - search_query = g_strdup_printf ("(beginswith \"email\" %s)", - s->str); - break; - default: - search_query = g_strdup ("(contains \"x-evolution-any-field\" \"\")"); - break; - } - g_string_free (s, TRUE); - - } else - search_query = g_strdup ("(contains \"x-evolution-any-field\" \"\")"); - - /* Merge view and sexp */ - subid = e_search_bar_get_viewitem_id (esb); - - if (subid) { - master_list = get_master_list (FALSE); - if (subid < 3) { - view_sexp = g_strdup ("(not (and (exists \"CATEGORIES\") (not (is \"CATEGORIES\" \"\"))))"); - } else { - category_name = g_list_nth_data (master_list, subid-3); - view_sexp = g_strdup_printf ("(is \"category_list\" \"%s\")", category_name); - } - search_query = g_strconcat ("(and ", view_sexp, search_query, ")", NULL); - g_free (view_sexp); +status_message (EAddressbookView *view, + const gchar *status) +{ + EActivity *activity; + EShellView *shell_view; + EShellBackend *shell_backend; + + activity = view->priv->activity; + shell_view = e_addressbook_view_get_shell_view (view); + shell_backend = e_shell_view_get_shell_backend (shell_view); + + if (status == NULL || *status == '\0') { + if (activity != NULL) { + e_activity_complete (activity); + g_object_unref (activity); + view->priv->activity = NULL; } - if (search_query) - g_object_set (v, - "query", search_query, - NULL); - - g_free (search_query); - } + } else if (activity == NULL) { + activity = e_activity_new (status); + view->priv->activity = activity; + e_shell_backend_add_activity (shell_backend, activity); - g_free (search_word); - v->displayed_contact = -1; - eab_contact_display_render (EAB_CONTACT_DISPLAY (v->contact_display), NULL, - EAB_CONTACT_DISPLAY_RENDER_NORMAL); + } else + e_activity_set_primary_text (activity, status); } static void -search_menu_activated (ESearchBar *esb, gint id, EABView *view) +search_result (EAddressbookView *view, + EBookViewStatus status) { - if (id == E_FILTERBAR_ADVANCED_ID) - e_search_bar_set_item_id (esb, id); -} + EShellView *shell_view; + EShellWindow *shell_window; -static void -query_changed (ESearchBar *esb, EABView *view) -{ - gint search_type; - gchar *query; - - search_type = e_search_bar_get_item_id(esb); - if (search_type == E_FILTERBAR_ADVANCED_ID) { - g_object_get (esb, "query", &query, NULL); - g_object_set (view, "query", query, NULL); - g_free (query); - } + shell_view = e_addressbook_view_get_shell_view (view); + shell_window = e_shell_view_get_shell_window (shell_view); + eab_search_result_dialog (GTK_WIDGET (shell_window), status); } -static gint -compare_subitems (gconstpointer a, gconstpointer b) -{ - const ESearchBarItem *subitem_a = a; - const ESearchBarItem *subitem_b = b; - gchar *collate_a, *collate_b; - gint ret; - - collate_a = g_utf8_collate_key (subitem_a->text, -1); - collate_b = g_utf8_collate_key (subitem_b->text, -1); - - ret = strcmp (collate_a, collate_b); - - g_free (collate_a); - g_free (collate_b); - - return ret; -} - -static GtkWidget * -generate_viewoption_menu (EABSearchBarItem *subitems) +static void +folder_bar_message (EAddressbookView *view, + const gchar *message) { - GtkWidget *menu, *menu_item; - gint i = 0; - - menu = gtk_menu_new (); - - for (i = 0; subitems[i].search.id != -1; ++i) { - if (subitems[i].search.text) { - gchar *str = NULL; - str = e_str_without_underscores (subitems[i].search.text); - menu_item = gtk_image_menu_item_new_with_label (str); - if (subitems[i].image) { - GtkWidget *image; - - image = gtk_image_new_from_file ( - subitems[i].image); - gtk_image_menu_item_set_image ( - GTK_IMAGE_MENU_ITEM (menu_item), - image); - } - g_free (str); - } else { - menu_item = gtk_menu_item_new (); - gtk_widget_set_sensitive (menu_item, FALSE); - } + EShellView *shell_view; + EShellSidebar *shell_sidebar; + const gchar *name; - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (subitems[i].search.id)); + shell_view = e_addressbook_view_get_shell_view (view); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } + if (view->priv->source == NULL) + return; - return menu; + name = e_source_peek_name (view->priv->source); + e_shell_sidebar_set_primary_text (shell_sidebar, name); + e_shell_sidebar_set_secondary_text (shell_sidebar, message); } static void -categories_changed_cb (gpointer object, gpointer user_data) +stop_state_changed (GtkObject *object, EAddressbookView *view) { - get_master_list (TRUE); - make_suboptions (user_data); + command_state_change (view); } static void -make_suboptions (EABView *view) +command_state_change (EAddressbookView *view) { - EABSearchBarItem *subitems, *s; - GList *master_list; - gint i, N; - GtkWidget *menu; - - master_list = get_master_list (FALSE); - N = g_list_length (master_list); - subitems = g_new (EABSearchBarItem, N+4); - - subitems[0].search.id = 0; - subitems[0].search.text = g_strdup (_("Any Category")); - subitems[0].image = NULL; - - subitems[1].search.text = g_strdup (_("Unmatched")); - subitems[1].search.id = 1; - subitems[1].image = NULL; - - subitems[2].search.text = NULL; - subitems[2].search.id = 0; - subitems[2].image = NULL; - - for (i=0; i<N; ++i) { - const gchar *category = g_list_nth_data (master_list, i); - subitems[i+3].search.id = i+3; - subitems[i+3].search.text = g_strdup (category); - subitems[i+3].image = (gchar *)e_categories_get_icon_file_for (category); - } - - subitems[N+3].search.id = -1; - subitems[N+3].search.text = NULL; - subitems[N+3].image = NULL; - - qsort (subitems + 3, N, sizeof (subitems[0]), compare_subitems); - menu = generate_viewoption_menu (subitems); - e_search_bar_set_viewoption_menu ((ESearchBar *)view->search, menu); - - for (s = subitems; ((ESearchBarItem *)s)->id != -1; s++) { - if (((ESearchBarItem *)s)->text) - g_free (((ESearchBarItem *)s)->text); - } - g_free (subitems); + g_signal_emit (view, signals[COMMAND_STATE_CHANGE], 0); } -static GList * -get_master_list (gboolean force_rebuild) +static void +backend_died (EAddressbookView *view) { - static GList *category_list = NULL; - - if (force_rebuild) { - g_list_free (category_list); - category_list = NULL; - } - - if (category_list == NULL) { - GList *l, *p = e_categories_get_list (); + EShellView *shell_view; + EShellWindow *shell_window; + EAddressbookModel *model; + EBook *book; - for (l = p; l; l = l->next) { - if (e_categories_is_searchable ((const gchar *) l->data)) - category_list = g_list_prepend (category_list, l->data); - } + shell_view = e_addressbook_view_get_shell_view (view); + shell_window = e_shell_view_get_shell_window (shell_view); - category_list = g_list_reverse (category_list); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); - g_list_free (p); - } - - return category_list; + e_error_run ( + GTK_WINDOW (shell_window), + "addressbook:backend-died", + e_book_get_uri (book), NULL); } static void @@ -1633,78 +1047,27 @@ e_contact_print_button (EPrintable *printable, GtkPrintOperationAction action) } void -eab_view_show_contact_preview (EABView *view, gboolean show) +e_addressbook_view_print (EAddressbookView *view, + GtkPrintOperationAction action) { - g_return_if_fail (view && E_IS_ADDRESSBOOK_VIEW (view)); - - if (show) - gtk_widget_show (view->contact_display_window); - else - gtk_widget_hide (view->contact_display_window); -} - -void -eab_view_setup_menus (EABView *view, - BonoboUIComponent *uic) -{ - - g_return_if_fail (view != NULL); - g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - g_return_if_fail (uic != NULL); - g_return_if_fail (BONOBO_IS_UI_COMPONENT (uic)); - - init_collection (); - - view->uic = uic; - - setup_menus (view); - - /* XXX toshok - yeah this really doesn't belong here, but it - needs to happen at the same time and takes the uic */ - e_search_bar_set_ui_component ( (ESearchBar *)view->search, uic); -} + GalView *gal_view; + GalViewInstance *view_instance; -/** - * eab_view_discard_menus: - * @view: An addressbook view. - * - * Makes an addressbook view discard its GAL view menus and its views instance - * objects. This should be called when the corresponding Bonobo component is - * deactivated. - **/ -void -eab_view_discard_menus (EABView *view) -{ - g_return_if_fail (view != NULL); g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (view->view_menus) { - gal_view_menus_unmerge (view->view_menus, NULL); - - g_object_unref (view->view_menus); - view->view_menus = NULL; - } - - if (view->view_instance) { - g_object_unref (view->view_instance); - view->view_instance = NULL; - } - - view->uic = NULL; -} + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); -void -eab_view_print (EABView *view, GtkPrintOperationAction action) -{ - if (view->view_type == EAB_VIEW_MINICARD) { + if (GAL_IS_VIEW_MINICARD (gal_view)) { + EAddressbookModel *model; EBook *book; EBookQuery *query; gchar *query_string; GList *contact_list; - g_object_get ( - view->model, "query", &query_string, - "book", &book, NULL); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + query_string = e_addressbook_model_get_query (model); if (query_string != NULL) query = e_book_query_from_string (query_string); @@ -1712,7 +1075,7 @@ eab_view_print (EABView *view, GtkPrintOperationAction action) query = NULL; g_free (query_string); - contact_list = get_selected_contacts (view); + contact_list = e_addressbook_view_get_selected (view); e_contact_print (book, query, contact_list, action); g_list_foreach (contact_list, (GFunc) g_object_unref, NULL); g_list_free (contact_list); @@ -1720,11 +1083,11 @@ eab_view_print (EABView *view, GtkPrintOperationAction action) if (query != NULL) e_book_query_unref (query); - } else if (view->view_type == EAB_VIEW_TABLE) { + } else if (GAL_IS_VIEW_ETABLE (gal_view)) { EPrintable *printable; ETable *table; - g_object_get (view->widget, "table", &table, NULL); + g_object_get (view->priv->widget, "table", &table, NULL); printable = e_table_get_printable (table); g_object_ref_sink (printable); g_object_unref (table); @@ -1738,7 +1101,8 @@ eab_view_print (EABView *view, GtkPrintOperationAction action) /* callback function to handle removal of contacts for * which a user doesnt have write permission */ -static void delete_contacts_cb (EBook *book, EBookStatus status, gpointer closure) +static void +delete_contacts_cb (EBook *book, EBookStatus status, gpointer closure) { switch (status) { case E_BOOK_ERROR_OK : @@ -1754,19 +1118,85 @@ static void delete_contacts_cb (EBook *book, EBookStatus status, gpointer clos } } +static gboolean +addressbook_view_confirm_delete (GtkWindow *parent, + gboolean plural, + gboolean is_list, + const gchar *name) +{ + GtkWidget *dialog; + gchar *message; + gint response; + + if (is_list) { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contact lists?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact list?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact list (%s)?"), name); + } + } else { + if (plural) { + message = g_strdup ( + _("Are you sure you want to " + "delete these contacts?")); + } else if (name == NULL) { + message = g_strdup ( + _("Are you sure you want to " + "delete this contact?")); + } else { + message = g_strdup_printf ( + _("Are you sure you want to delete " + "this contact (%s)?"), name); + } + } + + dialog = gtk_message_dialog_new ( + parent, 0, GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, "%s", message); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + g_free (message); + + return (response == GTK_RESPONSE_ACCEPT); +} + void -eab_view_delete_selection(EABView *view, gboolean is_delete) +e_addressbook_view_delete_selection(EAddressbookView *view, gboolean is_delete) { GList *list, *l; gboolean plural = FALSE, is_list = FALSE; EContact *contact; ETable *etable = NULL; + EAddressbookModel *model; + EBook *book; EMinicardView *card_view; ESelectionModel *selection_model = NULL; + GalViewInstance *view_instance; + GalView *gal_view; gchar *name = NULL; gint row = 0, select; - list = get_selected_contacts (view); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + + view_instance = e_addressbook_view_get_view_instance (view); + gal_view = gal_view_instance_get_current_view (view_instance); + + list = e_addressbook_view_get_selected (view); contact = list->data; if (g_list_next(list)) @@ -1777,28 +1207,29 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) if (e_contact_get (contact, E_CONTACT_IS_LIST)) is_list = TRUE; - if (view->view_type == EAB_VIEW_MINICARD) { - card_view = e_minicard_view_widget_get_view (E_MINICARD_VIEW_WIDGET(view->object)); - selection_model = get_selection_model (view); + if (GAL_IS_VIEW_MINICARD (gal_view)) { + card_view = e_minicard_view_widget_get_view (E_MINICARD_VIEW_WIDGET(view->priv->object)); + selection_model = e_addressbook_view_get_selection_model (view); row = e_selection_model_cursor_row (selection_model); } - else if (view->view_type == EAB_VIEW_TABLE) { - etable = e_table_scrolled_get_table(E_TABLE_SCROLLED(view->widget)); + else if (GAL_IS_VIEW_ETABLE (gal_view)) { + etable = e_table_scrolled_get_table ( + E_TABLE_SCROLLED(view->priv->widget)); row = e_table_get_cursor_row (E_TABLE (etable)); } /* confirm delete */ - if (is_delete && - !eab_editor_confirm_delete(GTK_WINDOW(gtk_widget_get_toplevel(view->widget)), - plural, is_list, name)) { + if (is_delete && !addressbook_view_confirm_delete ( + GTK_WINDOW (gtk_widget_get_toplevel ( + view->priv->widget)), plural, is_list, name)) { g_free (name); g_list_foreach (list, (GFunc) g_object_unref, NULL); g_list_free (list); return; } - if (e_book_check_static_capability (view->book, "bulk-remove")) { + if (e_book_check_static_capability (book, "bulk-remove")) { GList *ids = NULL; for (l=list;l;l=g_list_next(l)) { @@ -1808,7 +1239,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) } /* Remove the cards all at once. */ - e_book_async_remove_contacts (view->book, + e_book_async_remove_contacts (book, ids, delete_contacts_cb, NULL); @@ -1819,7 +1250,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) for (l=list;l;l=g_list_next(l)) { contact = l->data; /* Remove the card. */ - e_book_async_remove_contact (view->book, + e_book_async_remove_contact (book, contact, delete_contacts_cb, NULL); @@ -1827,7 +1258,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) } /* Sets the cursor, at the row after the deleted row */ - if (view->view_type == EAB_VIEW_MINICARD && row!=0) { + if (GAL_IS_VIEW_MINICARD (gal_view) && row != 0) { select = e_sorter_model_to_sorted (selection_model->sorter, row); /* Sets the cursor, before the deleted row if its the last row */ @@ -1841,7 +1272,7 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) } /* Sets the cursor, at the row after the deleted row */ - else if (view->view_type == EAB_VIEW_TABLE && row!=0) { + else if (GAL_IS_VIEW_ETABLE (gal_view) && row != 0) { select = e_table_model_to_view_row (E_TABLE (etable), row); /* Sets the cursor, before the deleted row if its the last row */ @@ -1857,234 +1288,149 @@ eab_view_delete_selection(EABView *view, gboolean is_delete) g_list_free (list); } -static void -invisible_destroyed (gpointer data, GObject *where_object_was) -{ - EABView *view = data; - view->invisible = NULL; -} - -static void -selection_get (GtkWidget *invisible, - GtkSelectionData *selection_data, - guint info, - guint time_stamp, - EABView *view) -{ - gchar *value; - - value = eab_contact_list_to_string (view->clipboard_contacts); - - gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING, - 8, (guchar *)value, strlen (value)); - g_free (value); -} - -static void -selection_clear_event (GtkWidget *invisible, - GdkEventSelection *event, - EABView *view) -{ - if (view->clipboard_contacts) { - g_list_foreach (view->clipboard_contacts, (GFunc)g_object_unref, NULL); - g_list_free (view->clipboard_contacts); - view->clipboard_contacts = NULL; - } -} - -static void -selection_received (GtkWidget *invisible, - GtkSelectionData *selection_data, - guint time, - EABView *view) +void +e_addressbook_view_save_as (EAddressbookView *view, + gboolean all) { - if (selection_data->length <= 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { - return; - } else { - GList *contact_list; - GList *l; - gchar *str = NULL; - - if (selection_data->data [selection_data->length - 1] != 0) { - str = g_malloc0 (selection_data->length + 1); - memcpy (str, selection_data->data, selection_data->length); - contact_list = eab_contact_list_from_string (str); - } else - contact_list = eab_contact_list_from_string ((gchar *)selection_data->data); - - for (l = contact_list; l; l = l->next) { - EContact *contact = l->data; - - /* XXX NULL for a callback /sigh */ - eab_merging_book_add_contact (view->book, contact, NULL /* XXX */, NULL); - } + GList *list = NULL; + EBook *book; - g_list_foreach (contact_list, (GFunc)g_object_unref, NULL); - g_list_free (contact_list); - g_free (str); - } -} + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); -static void -add_to_list (gint model_row, gpointer closure) -{ - GList **list = closure; - *list = g_list_prepend (*list, GINT_TO_POINTER (model_row)); -} + book = e_addressbook_model_get_book (view->priv->model); -static GList * -get_selected_contacts (EABView *view) -{ - GList *list; - GList *iterator; - ESelectionModel *selection = get_selection_model (view); + if (all) { + EBookQuery *query; - list = NULL; - e_selection_model_foreach (selection, add_to_list, &list); + query = e_book_query_any_field_contains (""); + e_book_get_contacts (book, query, &list, NULL); + e_book_query_unref (query); + } else + list = e_addressbook_view_get_selected (view); - for (iterator = list; iterator; iterator = iterator->next) { - iterator->data = eab_model_get_contact (view->model, GPOINTER_TO_INT (iterator->data)); + if (list != NULL) { + eab_contact_list_save (_("Save as vCard..."), list, NULL); + g_list_foreach (list, (GFunc) g_object_unref, NULL); + g_list_free (list); } - list = g_list_reverse (list); - return list; } void -eab_view_save_as (EABView *view, gboolean all) +e_addressbook_view_view (EAddressbookView *view) { - GList *list = NULL; + EAddressbookModel *model; EBook *book; + GList *list, *iter; + gboolean editable; + gint response; + guint length; - g_object_get(view->model, - "book", &book, - NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (all) { - EBookQuery *query = e_book_query_any_field_contains(""); - e_book_get_contacts(book, query, &list, NULL); - e_book_query_unref(query); + model = e_addressbook_view_get_model (view); + book = e_addressbook_model_get_book (model); + editable = e_addressbook_model_get_editable (model); + + list = e_addressbook_view_get_selected (view); + length = g_list_length (list); + response = GTK_RESPONSE_YES; + + if (length > 5) { + GtkWidget *dialog; + + /* XXX Use e_error_new(). */ + /* XXX Provide a parent window. */ + dialog = gtk_message_dialog_new ( + NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, + _("Opening %d contacts will open %d new windows as " + "well.\nDo you really want to display all of these " + "contacts?"), length, length); + gtk_dialog_add_buttons ( + GTK_DIALOG (dialog), + _("_Don't Display"), GTK_RESPONSE_NO, + _("Display _All Contacts"), GTK_RESPONSE_YES, + NULL); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); } - else { - list = get_selected_contacts(view); - } - if (list) - eab_contact_list_save (_("Save as vCard..."), list, NULL); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} -void -eab_view_view (EABView *view) -{ - GList *list = get_selected_contacts (view); - eab_show_multiple_contacts (view->book, list, view->editable); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} + if (response == GTK_RESPONSE_YES) + for (iter = list; iter != NULL; iter = iter->next) + addressbook_view_emit_open_contact ( + view, iter->data, FALSE); -void -eab_view_send (EABView *view) -{ - GList *list = get_selected_contacts (view); - if (list) - eab_send_contact_list (list, EAB_DISPOSITION_AS_ATTACHMENT); g_list_foreach (list, (GFunc) g_object_unref, NULL); g_list_free (list); } void -eab_view_send_to (EABView *view) +e_addressbook_view_cut (EAddressbookView *view) { - GList *list = get_selected_contacts (view); - if (list) - eab_send_contact_list (list, EAB_DISPOSITION_AS_TO); - g_list_foreach (list, (GFunc) g_object_unref, NULL); - g_list_free (list); -} + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); -void -eab_view_cut (EABView *view) -{ - eab_view_copy (view); - eab_view_delete_selection (view, FALSE); + e_addressbook_view_copy (view); + e_addressbook_view_delete_selection (view, FALSE); } -static gboolean -contact_display_has_selection (EABContactDisplay *display) +void +e_addressbook_view_copy (EAddressbookView *view) { - gchar *string; - gint selection_length; - gboolean has_selection; - - string = gtk_html_get_selection_html (GTK_HTML (display), &selection_length); - - has_selection = string ? TRUE : FALSE; + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (string) - g_free (string); + view->priv->clipboard_contacts = e_addressbook_view_get_selected (view); - return has_selection; + gtk_selection_owner_set ( + view->priv->invisible, + clipboard_atom, GDK_CURRENT_TIME); } void -eab_view_copy (EABView *view) +e_addressbook_view_paste (EAddressbookView *view) { - if (GTK_WIDGET_HAS_FOCUS (view->contact_display) && - contact_display_has_selection (EAB_CONTACT_DISPLAY (view->contact_display))) - { - gtk_html_copy (GTK_HTML (view->contact_display)); - } - else - { - view->clipboard_contacts = get_selected_contacts (view); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - gtk_selection_owner_set (view->invisible, clipboard_atom, GDK_CURRENT_TIME); - } + gtk_selection_convert ( + view->priv->invisible, clipboard_atom, + GDK_SELECTION_TYPE_STRING, GDK_CURRENT_TIME); } void -eab_view_paste (EABView *view) +e_addressbook_view_select_all (EAddressbookView *view) { - gtk_selection_convert (view->invisible, clipboard_atom, - GDK_SELECTION_TYPE_STRING, - GDK_CURRENT_TIME); -} + ESelectionModel *model; -void -eab_view_select_all (EABView *view) -{ - ESelectionModel *model = get_selection_model (view); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + model = e_addressbook_view_get_selection_model (view); g_return_if_fail (model); e_selection_model_select_all (model); } void -eab_view_show_all(EABView *view) +e_addressbook_view_show_all (EAddressbookView *view) { - g_object_set(view, - "query", NULL, - NULL); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + + e_addressbook_model_set_query (view->priv->model, ""); } void -eab_view_stop(EABView *view) +e_addressbook_view_stop (EAddressbookView *view) { - if (view) - eab_model_stop (view->model); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); + + e_addressbook_model_stop (view->priv->model); } static void -view_transfer_contacts (EABView *view, gboolean delete_from_source, gboolean all) +view_transfer_contacts (EAddressbookView *view, gboolean delete_from_source, gboolean all) { EBook *book; GList *contacts = NULL; GtkWindow *parent_window; - g_object_get(view->model, - "book", &book, - NULL); + book = e_addressbook_model_get_book (view->priv->model); if (all) { EBookQuery *query = e_book_query_any_field_contains(""); @@ -2092,7 +1438,7 @@ view_transfer_contacts (EABView *view, gboolean delete_from_source, gboolean all e_book_query_unref(query); } else { - contacts = get_selected_contacts (view); + contacts = e_addressbook_view_get_selected (view); } parent_window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))); @@ -2101,131 +1447,13 @@ view_transfer_contacts (EABView *view, gboolean delete_from_source, gboolean all } void -eab_view_copy_to_folder (EABView *view, gboolean all) +e_addressbook_view_copy_to_folder (EAddressbookView *view, gboolean all) { view_transfer_contacts (view, FALSE, all); } void -eab_view_move_to_folder (EABView *view, gboolean all) +e_addressbook_view_move_to_folder (EAddressbookView *view, gboolean all) { view_transfer_contacts (view, TRUE, all); } - -static gboolean -eab_view_selection_nonempty (EABView *view) -{ - ESelectionModel *selection_model; - - selection_model = get_selection_model (view); - if (selection_model == NULL) - return FALSE; - - return e_selection_model_selected_count (selection_model) != 0; -} - -gboolean -eab_view_can_create (EABView *view) -{ - return view ? eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_print (EABView *view) -{ - return view && view->model ? eab_model_contact_count (view->model) : FALSE; -} - -gboolean -eab_view_can_save_as (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_view (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_send (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_send_to (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_delete (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) && eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_cut (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) && eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_copy (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_paste (EABView *view) -{ - return view ? eab_model_editable (view->model) : FALSE; -} - -gboolean -eab_view_can_select_all (EABView *view) -{ - return view ? eab_model_contact_count (view->model) != 0 : FALSE; -} - -gboolean -eab_view_can_stop (EABView *view) -{ - return view ? eab_model_can_stop (view->model) : FALSE; -} - -gboolean -eab_view_can_copy_to_folder (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) : FALSE; -} - -gboolean -eab_view_can_move_to_folder (EABView *view) -{ - return view ? eab_view_selection_nonempty (view) && eab_model_editable (view->model) : FALSE; -} - -EABMenuTargetSelect * -eab_view_get_menu_target (EABView *view, EABMenu *menu) -{ - GPtrArray *cards = g_ptr_array_new(); - ESelectionModel *selection_model; - EABMenuTargetSelect *t; - - selection_model = get_selection_model (view); - if (selection_model) { - ContactAndBook cab; - - cab.view = view; - cab.closure = cards; - e_selection_model_foreach(selection_model, get_card_1, &cab); - } - - t = eab_menu_target_new_select(menu, view->book, !eab_model_editable(view->model), cards); - t->target.widget = (GtkWidget *)view; - - return t; -} diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index 03bdcb5a1a..4e0f82eeb0 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -20,142 +20,106 @@ * */ -#ifndef __EAB_VIEW_H__ -#define __EAB_VIEW_H__ +#ifndef E_ADDRESSBOOK_VIEW_H +#define E_ADDRESSBOOK_VIEW_H -#include <gtk/gtk.h> -#include <bonobo/bonobo-ui-component.h> -#include <widgets/menus/gal-view-instance.h> #include <libebook/e-book.h> -#include "e-addressbook-model.h" -#include "eab-contact-display.h" -#include "eab-menu.h" -#include "widgets/menus/gal-view-menus.h" -#include "misc/e-search-bar.h" -#include "misc/e-filter-bar.h" +#include <libebook/e-contact.h> -G_BEGIN_DECLS +#include <menus/gal-view-instance.h> +#include <misc/e-selection-model.h> +#include <shell/e-shell-view.h> -/* EABView - A card displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * -------------------------------------------------------------------------------- - */ +#include "e-addressbook-model.h" +#include "eab-contact-display.h" -#define E_TYPE_AB_VIEW (eab_view_get_type ()) -#define EAB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_AB_VIEW, EABView)) -#define EAB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_AB_VIEW, EABViewClass)) -#define E_IS_ADDRESSBOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_AB_VIEW)) -#define E_IS_ADDRESSBOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_AB_VIEW)) +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_VIEW \ + (e_addressbook_view_get_type ()) +#define E_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookView)) +#define E_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewClass)) +#define E_IS_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW)) +#define E_IS_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW)) +#define E_ADDRESSBOOK_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewClass)) -typedef enum { - EAB_VIEW_NONE, /* initialized to this */ - EAB_VIEW_MINICARD, - EAB_VIEW_TABLE -} EABViewType; +G_BEGIN_DECLS -typedef struct _EABView EABView; -typedef struct _EABViewClass EABViewClass; +typedef struct _EAddressbookView EAddressbookView; +typedef struct _EAddressbookViewClass EAddressbookViewClass; +typedef struct _EAddressbookViewPrivate EAddressbookViewPrivate; -struct _EABView -{ +struct _EAddressbookView { GtkVBox parent; - - /* item specific fields */ - EABViewType view_type; - - EABModel *model; - - GtkWidget *invisible; - GList *clipboard_contacts; - - EBook *book; - ESource *source; - gchar *query; - guint editable : 1; - - gint displayed_contact; - - GObject *object; - GtkWidget *widget; - - GtkWidget *contact_display_window; - GtkWidget *contact_display; - GtkWidget *paned; - - /* Menus handler and the view instance */ - GalViewInstance *view_instance; - GalViewMenus *view_menus; - GalView *current_view; - BonoboUIComponent *uic; - - /* the search bar and related machinery */ - EFilterBar *search; - gint ecml_changed_id; - RuleContext *search_context; - FilterRule *search_rule; + EAddressbookViewPrivate *priv; }; -struct _EABViewClass -{ +struct _EAddressbookViewClass { GtkVBoxClass parent_class; - /* - * Signals - */ - void (*status_message) (EABView *view, const gchar *message); - void (*search_result) (EABView *view, EBookViewStatus status); - void (*folder_bar_message) (EABView *view, const gchar *message); - void (*command_state_change) (EABView *view); + /* Signals */ + void (*open_contact) (EAddressbookView *view, + EContact *contact, + gboolean is_new_contact); + void (*popup_event) (EAddressbookView *view, + GdkEvent *event); + void (*status_message) (EAddressbookView *view, + const gchar *message); + void (*command_state_change) (EAddressbookView *view); + void (*selection_change) (EAddressbookView *view); }; -GtkWidget *eab_view_new (void); -GType eab_view_get_type (void); - -void eab_view_show_contact_preview (EABView *view, gboolean show); - -void eab_view_setup_menus (EABView *view, - BonoboUIComponent *uic); -void eab_view_discard_menus (EABView *view); - -RuleContext *eab_view_peek_search_context (EABView *view); -FilterRule *eab_view_peek_search_rule (EABView *view); - -void eab_view_save_as (EABView *view, gboolean all); -void eab_view_view (EABView *view); -void eab_view_send (EABView *view); -void eab_view_send_to (EABView *view); -void eab_view_print (EABView *view, - GtkPrintOperationAction action); -void eab_view_delete_selection (EABView *view, gboolean is_delete); -void eab_view_cut (EABView *view); -void eab_view_copy (EABView *view); -void eab_view_paste (EABView *view); -void eab_view_select_all (EABView *view); -void eab_view_show_all (EABView *view); -void eab_view_stop (EABView *view); -void eab_view_copy_to_folder (EABView *view, gboolean all); -void eab_view_move_to_folder (EABView *view, gboolean all); - -gboolean eab_view_can_create (EABView *view); -gboolean eab_view_can_print (EABView *view); -gboolean eab_view_can_save_as (EABView *view); -gboolean eab_view_can_view (EABView *view); -gboolean eab_view_can_send (EABView *view); -gboolean eab_view_can_send_to (EABView *view); -gboolean eab_view_can_delete (EABView *view); -gboolean eab_view_can_cut (EABView *view); -gboolean eab_view_can_copy (EABView *view); -gboolean eab_view_can_paste (EABView *view); -gboolean eab_view_can_select_all (EABView *view); -gboolean eab_view_can_stop (EABView *view); -gboolean eab_view_can_copy_to_folder (EABView *view); -gboolean eab_view_can_move_to_folder (EABView *view); - -EABMenuTargetSelect *eab_view_get_menu_target (EABView *view, EABMenu *menu); +GType e_addressbook_view_get_type (void); +GtkWidget * e_addressbook_view_new (EShellView *shell_view, + ESource *source); +EAddressbookModel * + e_addressbook_view_get_model (EAddressbookView *view); +GalViewInstance * + e_addressbook_view_get_view_instance + (EAddressbookView *view); +GObject * e_addressbook_view_get_view_object + (EAddressbookView *view); +GtkWidget * e_addressbook_view_get_view_widget + (EAddressbookView *view); +GList * e_addressbook_view_get_selected (EAddressbookView *view); +ESelectionModel * + e_addressbook_view_get_selection_model + (EAddressbookView *view); +EShellView * e_addressbook_view_get_shell_view + (EAddressbookView *view); +ESource * e_addressbook_view_get_source (EAddressbookView *view); +void e_addressbook_view_save_as (EAddressbookView *view, + gboolean all); +void e_addressbook_view_view (EAddressbookView *view); +void e_addressbook_view_print (EAddressbookView *view, + GtkPrintOperationAction action); +void e_addressbook_view_delete_selection + (EAddressbookView *view, + gboolean is_delete); +void e_addressbook_view_cut (EAddressbookView *view); +void e_addressbook_view_copy (EAddressbookView *view); +void e_addressbook_view_paste (EAddressbookView *view); +void e_addressbook_view_select_all (EAddressbookView *view); +void e_addressbook_view_show_all (EAddressbookView *view); +void e_addressbook_view_stop (EAddressbookView *view); +void e_addressbook_view_copy_to_folder + (EAddressbookView *view, + gboolean all); +void e_addressbook_view_move_to_folder + (EAddressbookView *view, + gboolean all); + +gboolean e_addressbook_view_can_create (EAddressbookView *view); G_END_DECLS -#endif /* __EAB_VIEW_H__ */ +#endif /* E_ADDRESSBOOK_VIEW_H */ diff --git a/addressbook/gui/widgets/e-minicard-view-widget.c b/addressbook/gui/widgets/e-minicard-view-widget.c index 62778b4bf3..cb3904728e 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.c +++ b/addressbook/gui/widgets/e-minicard-view-widget.c @@ -53,6 +53,8 @@ enum { }; enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, SELECTION_CHANGE, COLUMN_WIDTH_CHANGED, RIGHT_CLICK, @@ -140,6 +142,24 @@ e_minicard_view_widget_class_init (EMinicardViewWidgetClass *class) 0.0, G_MAXDOUBLE, 150.0, G_PARAM_READWRITE)); + signals [CREATE_CONTACT] = + g_signal_new ("create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals [CREATE_CONTACT_LIST] = + g_signal_new ("create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardViewWidgetClass, create_contact_list), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [SELECTION_CHANGE] = g_signal_new ("selection_change", G_OBJECT_CLASS_TYPE (object_class), @@ -315,6 +335,18 @@ column_width_changed (ESelectionModel *esm, double width, EMinicardViewWidget *w signals [COLUMN_WIDTH_CHANGED], 0, width); } +static void +create_contact (EMinicardView *view, EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT], 0); +} + +static void +create_contact_list (EMinicardView *view, EMinicardViewWidget *widget) +{ + g_signal_emit (widget, signals[CREATE_CONTACT_LIST], 0); +} + static guint right_click (EMinicardView *view, GdkEvent *event, EMinicardViewWidget *widget) { @@ -369,6 +401,12 @@ e_minicard_view_widget_realize (GtkWidget *widget) "column_width_changed", G_CALLBACK (column_width_changed), view); g_signal_connect (view->emv, + "create-contact", + G_CALLBACK (create_contact), view); + g_signal_connect (view->emv, + "create-contact-list", + G_CALLBACK (create_contact_list), view); + g_signal_connect (view->emv, "right_click", G_CALLBACK (right_click), view); diff --git a/addressbook/gui/widgets/e-minicard-view-widget.h b/addressbook/gui/widgets/e-minicard-view-widget.h index 2b01dce65e..bf9fe8dd4e 100644 --- a/addressbook/gui/widgets/e-minicard-view-widget.h +++ b/addressbook/gui/widgets/e-minicard-view-widget.h @@ -57,6 +57,8 @@ struct _EMinicardViewWidget struct _EMinicardViewWidgetClass { ECanvasClass parent_class; + void (*create_contact) (EMinicardViewWidget *emvw); + void (*create_contact_list) (EMinicardViewWidget *emvw); void (*selection_change) (EMinicardViewWidget *emvw); void (*column_width_changed) (EMinicardViewWidget *emvw, double width); guint (*right_click) (EMinicardViewWidget *emvw); diff --git a/addressbook/gui/widgets/e-minicard-view.c b/addressbook/gui/widgets/e-minicard-view.c index c33b1f3045..80d7291113 100644 --- a/addressbook/gui/widgets/e-minicard-view.c +++ b/addressbook/gui/widgets/e-minicard-view.c @@ -33,7 +33,8 @@ #include <misc/e-canvas.h> #include <glib/gi18n.h> #include <string.h> -#include "a11y/addressbook/ea-addressbook.h" +#include "e-util/e-util.h" +#include "ea-addressbook.h" static void e_minicard_view_drag_data_get(GtkWidget *widget, GdkDragContext *context, @@ -55,6 +56,8 @@ enum { }; enum { + CREATE_CONTACT, + CREATE_CONTACT_LIST, RIGHT_CLICK, LAST_SIGNAL }; @@ -159,7 +162,7 @@ set_empty_message (EMinicardView *view) EBook *book; if (view->adapter) { - EABModel *model = NULL; + EAddressbookModel *model = NULL; g_object_get (view->adapter, "editable", &editable, @@ -170,7 +173,7 @@ set_empty_message (EMinicardView *view) if (!e_book_check_static_capability (book, "do-initial-query")) perform_initial_query = TRUE; - searching = model && eab_model_can_stop (model); + searching = model && e_addressbook_model_can_stop (model); } if (searching) { @@ -195,13 +198,13 @@ set_empty_message (EMinicardView *view) } static void -writable_status_change (EABModel *model, gboolean writable, EMinicardView *view) +writable_status_change (EAddressbookModel *model, gboolean writable, EMinicardView *view) { set_empty_message (view); } static void -stop_state_changed (EABModel *model, EMinicardView *view) +stop_state_changed (EAddressbookModel *model, EMinicardView *view) { set_empty_message (view); } @@ -229,7 +232,7 @@ e_minicard_view_set_property (GObject *object, case PROP_ADAPTER: if (view->adapter) { if (view->writable_status_id || view->stop_state_id) { - EABModel *model; + EAddressbookModel *model; g_object_get (view->adapter, "model", &model, NULL); @@ -252,7 +255,7 @@ e_minicard_view_set_property (GObject *object, "model", view->adapter, NULL); if (view->adapter) { - EABModel *model; + EAddressbookModel *model; g_object_get (view->adapter, "model", &model, NULL); @@ -337,7 +340,7 @@ e_minicard_view_dispose (GObject *object) if (view->adapter) { if (view->writable_status_id || view->stop_state_id) { - EABModel *model; + EAddressbookModel *model; g_object_get (view->adapter, "model", &model, NULL); @@ -382,13 +385,8 @@ e_minicard_view_event (GnomeCanvasItem *item, GdkEvent *event) g_object_get(view->adapter, "editable", &editable, NULL); - if (editable) { - EBook *book; - g_object_get(view, "book", &book, NULL); - - if (book && E_IS_BOOK (book)) - eab_show_contact_editor (book, e_contact_new(), TRUE, editable); - } + if (editable) + e_minicard_view_create_contact (view); return TRUE; } case GDK_BUTTON_PRESS: @@ -546,6 +544,22 @@ e_minicard_view_class_init (EMinicardViewClass *klass) FALSE, G_PARAM_READWRITE)); + signals [CREATE_CONTACT] = + g_signal_new ("create-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals [CREATE_CONTACT_LIST] = + g_signal_new ("create-contact-list", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals [RIGHT_CLICK] = g_signal_new ("right_click", G_OBJECT_CLASS_TYPE (object_class), @@ -654,3 +668,19 @@ e_minicard_view_get_card_list (EMinicardView *view) mal.list = g_list_reverse (mal.list); return mal.list; } + +void +e_minicard_view_create_contact (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT], 0); +} + +void +e_minicard_view_create_contact_list (EMinicardView *view) +{ + g_return_if_fail (E_IS_MINICARD_VIEW (view)); + + g_signal_emit (view, signals[CREATE_CONTACT_LIST], 0); +} diff --git a/addressbook/gui/widgets/e-minicard-view.h b/addressbook/gui/widgets/e-minicard-view.h index 82b8cbb63a..babfddd0c3 100644 --- a/addressbook/gui/widgets/e-minicard-view.h +++ b/addressbook/gui/widgets/e-minicard-view.h @@ -26,7 +26,7 @@ #include "e-minicard.h" -#include <misc/e-reflow.h> +#include <text/e-reflow.h> #include <misc/e-selection-model-simple.h> #include <libebook/e-book.h> #include "e-addressbook-reflow-adapter.h" @@ -90,6 +90,8 @@ void e_minicard_view_remove_selection (EMinicardView *view, void e_minicard_view_jump_to_letter (EMinicardView *view, gunichar letter); GList *e_minicard_view_get_card_list (EMinicardView *view); +void e_minicard_view_create_contact (EMinicardView *view); +void e_minicard_view_create_contact_list (EMinicardView *view); G_END_DECLS diff --git a/addressbook/gui/widgets/e-minicard.c b/addressbook/gui/widgets/e-minicard.c index c4568aac3b..1f6bc14117 100644 --- a/addressbook/gui/widgets/e-minicard.c +++ b/addressbook/gui/widgets/e-minicard.c @@ -35,11 +35,10 @@ #include "e-minicard.h" #include "e-minicard-label.h" #include "e-minicard-view.h" -#include "e-contact-editor.h" #include <e-util/e-html-utils.h> #include <e-util/e-icon-factory.h> #include <libebook/e-destination.h> -#include "a11y/addressbook/ea-addressbook.h" +#include "ea-addressbook.h" static void e_minicard_init (EMinicard *card); static void e_minicard_class_init (EMinicardClass *class); @@ -86,6 +85,7 @@ enum { enum { SELECTED, DRAG_BEGIN, + OPEN_CONTACT, STYLE_SET, LAST_SIGNAL }; @@ -101,7 +101,7 @@ common_location [] = { "OTHER", N_ ("Other Email") } }; -static guint e_minicard_signals [LAST_SIGNAL] = {0, }; +static guint signals [LAST_SIGNAL] = {0, }; GType e_minicard_get_type (void) @@ -200,7 +200,7 @@ e_minicard_class_init (EMinicardClass *class) E_TYPE_CONTACT, G_PARAM_READWRITE)); - e_minicard_signals [SELECTED] = + signals [SELECTED] = g_signal_new ("selected", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, @@ -209,7 +209,7 @@ e_minicard_class_init (EMinicardClass *class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); - e_minicard_signals [DRAG_BEGIN] = + signals [DRAG_BEGIN] = g_signal_new ("drag_begin", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, @@ -218,7 +218,17 @@ e_minicard_class_init (EMinicardClass *class) e_marshal_INT__POINTER, G_TYPE_INT, 1, G_TYPE_POINTER); - e_minicard_signals [STYLE_SET] = + signals [OPEN_CONTACT] = + g_signal_new ("open-contact", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EMinicardClass, open_contact), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_CONTACT); + + signals [STYLE_SET] = g_signal_new ("style_set", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, @@ -249,8 +259,6 @@ e_minicard_init (EMinicard *minicard) minicard->list_icon_pixbuf = e_icon_factory_get_icon (LIST_ICON_NAME, GTK_ICON_SIZE_MENU); minicard->list_icon_size = gdk_pixbuf_get_height (minicard->list_icon_pixbuf); - minicard->editor = NULL; - minicard->changed = FALSE; e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(minicard), e_minicard_reflow); @@ -525,50 +533,12 @@ e_minicard_unrealize (GnomeCanvasItem *item) (* GNOME_CANVAS_ITEM_CLASS(parent_class)->unrealize) (item); } -/* Callback used when the contact editor is closed */ -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - EMinicard *minicard = data; - g_object_unref (editor); - minicard->editor = NULL; -} - -gboolean -e_minicard_activate_editor(EMinicard *minicard) +void +e_minicard_activate_editor (EMinicard *minicard) { - GnomeCanvasItem *item = (GnomeCanvasItem *)minicard; - - if (minicard->editor) { - eab_editor_raise (minicard->editor); - } - else { - EBook *book = NULL; - if (E_IS_MINICARD_VIEW(item->parent)) { - g_object_get(item->parent, "book", &book, NULL); - } - - if (book != NULL) { - if (e_contact_get (minicard->contact, E_CONTACT_IS_LIST)) { - EContactListEditor *editor = eab_show_contact_list_editor (book, minicard->contact, - FALSE, e_book_is_writable (book)); - minicard->editor = EAB_EDITOR (editor); - } - else { - EContactEditor *editor = eab_show_contact_editor (book, minicard->contact, - FALSE, e_book_is_writable (book)); - minicard->editor = EAB_EDITOR (editor); - } - - g_object_ref (minicard->editor); - g_signal_connect (minicard->editor, "editor_closed", - G_CALLBACK (editor_closed_cb), minicard); - - g_object_unref (book); - } - } + g_return_if_fail (E_IS_MINICARD (minicard)); - return TRUE; + g_signal_emit (minicard, signals[OPEN_CONTACT], 0, minicard->contact); } static gboolean @@ -652,7 +622,8 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) break; case GDK_2BUTTON_PRESS: if (event->button.button == 1 && E_IS_MINICARD_VIEW (item->parent)) { - return e_minicard_activate_editor (e_minicard); + e_minicard_activate_editor (e_minicard); + return TRUE; } break; case GDK_KEY_PRESS: @@ -722,7 +693,8 @@ e_minicard_event (GnomeCanvasItem *item, GdkEvent *event) } else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter) { - return e_minicard_activate_editor (e_minicard); + e_minicard_activate_editor (e_minicard); + return TRUE; } break; default: @@ -1149,7 +1121,7 @@ e_minicard_drag_begin (EMinicard *minicard, GdkEvent *event) gint ret_val = 0; GnomeCanvasItem *parent; g_signal_emit (minicard, - e_minicard_signals[DRAG_BEGIN], 0, + signals[DRAG_BEGIN], 0, event, &ret_val); parent = GNOME_CANVAS_ITEM (minicard)->parent; diff --git a/addressbook/gui/widgets/e-minicard.h b/addressbook/gui/widgets/e-minicard.h index 033e981636..4135090763 100644 --- a/addressbook/gui/widgets/e-minicard.h +++ b/addressbook/gui/widgets/e-minicard.h @@ -24,7 +24,6 @@ #define __E_MINICARD_H__ #include <gtk/gtk.h> -#include "addressbook/gui/contact-editor/eab-editor.h" #include <libgnomecanvas/gnome-canvas.h> #include <libebook/e-contact.h> @@ -71,8 +70,6 @@ struct _EMinicard GdkPixbuf *list_icon_pixbuf; double list_icon_size; - EABEditor *editor; - GList *fields; /* Of type EMinicardField */ guint needs_remodeling : 1; @@ -101,6 +98,7 @@ struct _EMinicardClass gint (* selected) (EMinicard *minicard, GdkEvent *event); gint (* drag_begin) (EMinicard *minicard, GdkEvent *event); + void (* open_contact) (EMinicard *minicard, EContact *contact); void (* style_set) (EMinicard *minicard, GtkStyle *previous_style); }; @@ -121,7 +119,7 @@ gint e_minicard_compare (EMinicard *minicard1, gint e_minicard_selected (EMinicard *minicard, GdkEvent *event); -gboolean e_minicard_activate_editor (EMinicard *minicard); +void e_minicard_activate_editor (EMinicard *minicard); G_END_DECLS diff --git a/addressbook/gui/widgets/ea-addressbook-view.c b/addressbook/gui/widgets/ea-addressbook-view.c new file mode 100644 index 0000000000..b2d7ebb171 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook-view.c @@ -0,0 +1,123 @@ +/* + * 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: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <glib/gi18n.h> +#include "ea-addressbook-view.h" + +static G_CONST_RETURN gchar * ea_ab_view_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_ab_view_get_description (AtkObject *accessible); + +static void ea_ab_view_class_init (EAddressbookViewClass *class); + +static gpointer parent_class = NULL; + +GType +ea_ab_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EAddressbookViewClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_ab_view_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EAddressbookView), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GTK_TYPE_EVENT_BOX); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaABView", &tinfo, 0); + } + + return type; +} + +static void +ea_ab_view_class_init (EAddressbookViewClass *class) +{ + AtkObjectClass *atk_object_class; + + parent_class = g_type_class_peek_parent (class); + + atk_object_class = ATK_OBJECT_CLASS (class); + atk_object_class->get_name = ea_ab_view_get_name; + atk_object_class->get_description = ea_ab_view_get_description; +} + +static G_CONST_RETURN gchar * +ea_ab_view_get_name (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_AB_VIEW(accessible), NULL); + if (accessible->name) + return accessible->name; + + return _("evolution address book"); +} + +static G_CONST_RETURN gchar * +ea_ab_view_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution address book"); +} + +AtkObject* +ea_ab_view_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail(obj != NULL, NULL); + g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW(obj), NULL); + + object = g_object_new (EA_TYPE_AB_VIEW, NULL); + + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_CANVAS; + + return accessible; +} diff --git a/addressbook/gui/widgets/ea-addressbook-view.h b/addressbook/gui/widgets/ea-addressbook-view.h new file mode 100644 index 0000000000..6179b6758e --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook-view.h @@ -0,0 +1,55 @@ +/* + * 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: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_ADDRESSBOOK_VIEW_H__ +#define __EA_ADDRESSBOOK_VIEW_H__ + +#include <gtk/gtk.h> +#include "e-addressbook-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_AB_VIEW (ea_ab_view_get_type ()) +#define EA_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_AB_VIEW, EaABView)) +#define EA_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_AB_VIEW, EaABViewClass)) +#define EA_IS_AB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_AB_VIEW)) +#define EA_IS_AB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_AB_VIEW)) + +typedef struct _EaABView EaABView; +typedef struct _EaABViewClass EaABViewClass; + +struct _EaABView +{ + GtkAccessible parent; +}; + +struct _EaABViewClass +{ + GtkAccessibleClass parent_class; +}; + +GType ea_ab_view_get_type (void); +AtkObject* ea_ab_view_new(GObject *obj); + +G_END_DECLS + +#endif /* __EA_ADDRESSBOOK_VIEW_H__ */ diff --git a/addressbook/gui/widgets/ea-addressbook.c b/addressbook/gui/widgets/ea-addressbook.c new file mode 100644 index 0000000000..14fc4c1ca3 --- /dev/null +++ b/addressbook/gui/widgets/ea-addressbook.c @@ -0,0 +1,84 @@ +/* + * 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: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <text/e-text.h> +#include "a11y/ea-factory.h" +#include "ea-addressbook.h" +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "ea-addressbook-view.h" + +EA_FACTORY_GOBJECT (EA_TYPE_MINICARD, ea_minicard, ea_minicard_new) +EA_FACTORY_GOBJECT (EA_TYPE_MINICARD_VIEW, ea_minicard_view, ea_minicard_view_new) +EA_FACTORY_GOBJECT (EA_TYPE_AB_VIEW, ea_ab_view, ea_ab_view_new) + +static gboolean ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data); + +void e_minicard_a11y_init (void) +{ + EA_SET_FACTORY (e_minicard_get_type (), ea_minicard); +} + +void e_minicard_view_a11y_init (void) +{ + EA_SET_FACTORY (e_minicard_view_get_type (), ea_minicard_view); + + if (atk_get_root ()) { + g_signal_add_emission_hook (g_signal_lookup ("event", + e_minicard_get_type()), + 0, ea_addressbook_focus_watcher, + NULL, (GDestroyNotify) NULL); + } +} + +void eab_view_a11y_init (void) +{ + EA_SET_FACTORY (E_TYPE_ADDRESSBOOK_VIEW, ea_ab_view); +} + +static gboolean +ea_addressbook_focus_watcher (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + GObject *object; + GdkEvent *event; + AtkObject *ea_event = NULL; + + object = g_value_get_object (param_values + 0); + event = g_value_get_boxed (param_values + 1); + + if (E_IS_MINICARD (object)) { + GnomeCanvasItem *item = GNOME_CANVAS_ITEM (object); + ea_event = atk_gobject_accessible_for_object (object); + if (event->type == GDK_FOCUS_CHANGE) { + if ((event->focus_change.in) && (E_IS_MINICARD (item->canvas->focused_item))) + atk_focus_tracker_notify (ea_event); + } + } + + return TRUE; +} diff --git a/addressbook/gui/component/addressbook-migrate.h b/addressbook/gui/widgets/ea-addressbook.h index 0386d611e6..97b691dc18 100644 --- a/addressbook/gui/component/addressbook-migrate.h +++ b/addressbook/gui/widgets/ea-addressbook.h @@ -1,5 +1,4 @@ /* - * * 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 @@ -15,17 +14,20 @@ * * * Authors: - * Chris Toshok (toshok@ximian.com) + * Leon Zhang <leon.zhang@sun.com> * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ -#ifndef _ADDRESSBOOK_MIGRATE_H_ -#define _ADDRESSBOOK_MIGRATE_H_ +/* Evolution Accessibility +*/ -#include "addressbook-component.h" +#ifndef _EA_ADDRESSBOOK_H__ +#define _EA_ADDRESSBOOK_H__ -gint addressbook_migrate (AddressbookComponent *component, gint major, gint minor, gint revision, GError **err); +void eab_view_a11y_init (void); +void e_minicard_view_a11y_init (void); +void e_minicard_a11y_init (void); -#endif /* _ADDRESSBOOK_MIGRATE_H_ */ +#endif /* _EA_ADDRESSBOOK_H__ */ diff --git a/addressbook/gui/widgets/ea-minicard-view.c b/addressbook/gui/widgets/ea-minicard-view.c new file mode 100644 index 0000000000..ffccbfa1d1 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard-view.c @@ -0,0 +1,412 @@ +/* + * 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: + * Leon Zhang < leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> +#include <string.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "eab-gui-util.h" +#include "e-addressbook-view.h" + +static const gchar * action_name[] = { + N_("New Contact"), + N_("New Contact List") +}; + +static G_CONST_RETURN gchar * ea_minicard_view_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_minicard_view_get_description (AtkObject *accessible); + +static void ea_minicard_view_class_init (EaMinicardViewClass *klass); + +static gint ea_minicard_view_get_n_children (AtkObject *obj); +static AtkObject *ea_minicard_view_ref_child (AtkObject *obj, gint i); + +static AtkStateSet *ea_minicard_view_ref_state_set(AtkObject *obj); + +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject* selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); +static gint atk_action_interface_get_n_action (AtkAction *iface); +static G_CONST_RETURN gchar * atk_action_interface_get_description (AtkAction *iface, gint i); +static G_CONST_RETURN gchar * atk_action_interface_get_name (AtkAction *iface, gint i); + +static gpointer parent_class = NULL; + +GType +ea_minicard_view_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaMinicardViewClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_minicard_view_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EaMinicardView), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_GROUP); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaMinicardView", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, + &atk_selection_info); + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + + } + + return type; +} + +static void +ea_minicard_view_class_init (EaMinicardViewClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_minicard_view_get_name; + class->get_description = ea_minicard_view_get_description; + class->ref_state_set = ea_minicard_view_ref_state_set; + class->get_n_children = ea_minicard_view_get_n_children; + class->ref_child = ea_minicard_view_ref_child; +} + +static G_CONST_RETURN gchar * +ea_minicard_view_get_name (AtkObject *accessible) +{ + EReflow *reflow; + gchar *string; + EMinicardView *card_view; + EBook *book = NULL; + const gchar *source_name; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + + reflow = E_REFLOW(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); + + if (!reflow) + return NULL; + + /* Get the current name of minicard view*/ + card_view = E_MINICARD_VIEW (reflow); + g_object_get (card_view->adapter, "book", &book, NULL); + g_return_val_if_fail (E_IS_BOOK (book), NULL); + source_name = e_source_peek_name (e_book_get_source (book)); + if (!source_name) + source_name=""; + + string = g_strdup_printf (ngettext ("current address book folder %s has %d card", + "current address book folder %s has %d cards", + reflow->count), source_name, reflow->count); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, string); + g_free (string); + g_object_unref(book); + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_minicard_view_get_description (AtkObject *accessible) +{ + g_return_val_if_fail (EA_IS_MINICARD_VIEW(accessible), NULL); + if (accessible->description) + return accessible->description; + + return _("evolution address book"); +} + +AtkObject* +ea_minicard_view_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_MINICARD_VIEW(obj), NULL); + object = g_object_new (EA_TYPE_MINICARD_VIEW, NULL); + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + accessible->role = ATK_ROLE_PANEL; + return accessible; +} + +static gint +ea_minicard_view_get_n_children (AtkObject *accessible) +{ + EReflow *reflow; + + gint child_num = 0; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), -1); + + reflow = E_REFLOW (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible))); + + if (!reflow) + return -1; + + child_num = reflow->count; + + return child_num; +} + +static AtkStateSet *ea_minicard_view_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set = NULL; + GObject *gobj = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + if ( !state_set ) + state_set = atk_state_set_new (); + + gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); + if ( !gobj ) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + return state_set; +} + +static AtkObject * +ea_minicard_view_ref_child (AtkObject *accessible, gint index) +{ + EReflow *reflow; + gint child_num; + AtkObject *atk_object = NULL; + EMinicard *card = NULL; + + g_return_val_if_fail (EA_IS_MINICARD_VIEW (accessible), NULL); + + child_num = atk_object_get_n_accessible_children (accessible); + if (child_num <= 0 || index < 0 || index >= child_num) + return NULL; + + reflow = E_REFLOW (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); + if (!reflow) + return NULL; + if (!reflow->items ) + return NULL; + /* a minicard */ + if (index < child_num) { + card = E_MINICARD (reflow->items[index]); + atk_object = atk_gobject_accessible_for_object (G_OBJECT (card)); + } else { + return NULL; + } + + g_object_ref (atk_object); + return atk_object; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj= NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow) + return FALSE; + + selection_interface_clear_selection (selection); + e_selection_model_select_single_row (reflow->selection, i); + + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW(atk_gobject_accessible_get_object (atk_gobj)); + + if ( !reflow ) + return FALSE; + + e_selection_model_clear (reflow->selection); + + return TRUE; +} + +static AtkObject* +selection_interface_ref_selection (AtkSelection *selection, gint i) +{ + return ea_minicard_view_ref_child (ATK_OBJECT (selection), i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (!reflow ) + return FALSE; + + return e_selection_model_selected_count (reflow->selection); +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, gint i) +{ + AtkGObjectAccessible *atk_gobj = NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (selection); + reflow = E_REFLOW(atk_gobject_accessible_get_object (atk_gobj)); + + if ( !reflow ) + return FALSE; + + return e_selection_model_is_row_selected (reflow->selection, i); +} + +static void atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = atk_action_interface_do_action; + iface->get_n_actions = atk_action_interface_get_n_action; + iface->get_description = atk_action_interface_get_description; + iface->get_name = atk_action_interface_get_name; +} + +static gboolean atk_action_interface_do_action (AtkAction *action, gint i) +{ + gboolean return_value = TRUE; + EMinicardView *card_view; + + AtkGObjectAccessible *atk_gobj= NULL; + EReflow *reflow = NULL; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (action); + reflow = E_REFLOW (atk_gobject_accessible_get_object (atk_gobj)); + + if (reflow == NULL) + return FALSE; + + card_view = E_MINICARD_VIEW (reflow); + + switch (i) { + case 0: + /* New Contact */ + e_minicard_view_create_contact (card_view); + break; + case 1: + /* New Contact List */ + e_minicard_view_create_contact_list (card_view); + break; + default: + return_value = FALSE; + break; + } + + return return_value; +} + +static gint atk_action_interface_get_n_action (AtkAction *iface) +{ + return G_N_ELEMENTS (action_name); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_description (AtkAction *iface, gint i) +{ + return atk_action_interface_get_name (iface, i); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_name (AtkAction *iface, gint i) +{ + if ( i >= G_N_ELEMENTS (action_name) || i < 0) + return NULL; + + return action_name[i]; +} + diff --git a/addressbook/gui/widgets/ea-minicard-view.h b/addressbook/gui/widgets/ea-minicard-view.h new file mode 100644 index 0000000000..cc8eaecae7 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard-view.h @@ -0,0 +1,56 @@ +/* + * 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: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_MINICARD_VIEW_H__ +#define __EA_MINICARD_VIEW_H__ + +#include <atk/atkgobjectaccessible.h> +#include "e-minicard-view.h" + +G_BEGIN_DECLS + +#define EA_TYPE_MINICARD_VIEW (ea_minicard_view_get_type ()) +#define EA_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD_VIEW, EaMinicardView)) +#define EA_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD_VIEW, EaMiniCardViewClass)) +#define EA_IS_MINICARD_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) +#define EA_IS_MINICARD_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD_VIEW)) + +typedef struct _EaMinicardView EaMinicardView; +typedef struct _EaMinicardViewClass EaMinicardViewClass; + +struct _EaMinicardView +{ + AtkGObjectAccessible parent; +}; + +struct _EaMinicardViewClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +GType ea_minicard_view_get_type (void); + +AtkObject* ea_minicard_view_new(GObject *obj); + +G_END_DECLS + +#endif /* __EA_MINICARD_VIEW_H__ */ diff --git a/addressbook/gui/widgets/ea-minicard.c b/addressbook/gui/widgets/ea-minicard.c new file mode 100644 index 0000000000..8791a68e73 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard.c @@ -0,0 +1,273 @@ +/* + * 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: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> +#include <string.h> +#include <glib/gi18n.h> +#include "ea-minicard.h" +#include "ea-minicard-view.h" +#include "e-minicard.h" + +static const gchar * action_name[] = { + N_("Open") +}; + +static G_CONST_RETURN gchar * ea_minicard_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar * ea_minicard_get_description (AtkObject *accessible); + +static void ea_minicard_class_init (EaMinicardClass *klass); + +static gint ea_minicard_get_n_children (AtkObject *obj); +static AtkObject* ea_minicard_ref_child(AtkObject *obj, gint i); + +static AtkStateSet *ea_minicard_ref_state_set (AtkObject *obj); + +static void atk_action_interface_init (AtkActionIface *iface); +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i); +static gint atk_action_interface_get_n_action (AtkAction *iface); +static G_CONST_RETURN gchar * atk_action_interface_get_description (AtkAction *iface, gint i); +static G_CONST_RETURN gchar * atk_action_interface_get_name (AtkAction *iface, gint i); + +static gpointer parent_class = NULL; + +GType +ea_minicard_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaMinicardClass), + (GBaseInitFunc) NULL, /* base_init */ + (GBaseFinalizeFunc) NULL, /* base_finalize */ + (GClassInitFunc) ea_minicard_class_init, + (GClassFinalizeFunc) NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EaMinicard), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailWidget, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_GROUP); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static ( derived_atk_type, + "EaMinicard", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); + } + + return type; +} + +static void +ea_minicard_class_init (EaMinicardClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_minicard_get_name; + class->get_description = ea_minicard_get_description; + class->ref_state_set = ea_minicard_ref_state_set; + class->get_n_children = ea_minicard_get_n_children; + class->ref_child = ea_minicard_ref_child; +} + +/* + * we access the main content of current minicard, including + * header text, label(field, field name) + */ +static G_CONST_RETURN gchar * +ea_minicard_get_name (AtkObject *accessible) +{ +#define BUFFERSIZE 500 + + static gchar name[BUFFERSIZE]; + GString *new_str = g_string_new (NULL); + gchar *string; + EMinicard *card; + + g_return_val_if_fail (EA_IS_MINICARD(accessible), NULL); + memset (name, '\0', BUFFERSIZE); + + card = E_MINICARD(atk_gobject_accessible_get_object + (ATK_GOBJECT_ACCESSIBLE(accessible))); + if (!card) + return NULL; + + g_object_get (card->header_text, "text", &string, NULL); + + if (e_contact_get (card->contact, E_CONTACT_IS_LIST)) + g_string_append (new_str, _("Contact List: ")); + else g_string_append (new_str, _("Contact: ")); + + /* get header of current card */ + g_string_append (new_str, string); + g_free (string); + + /* if there exist no enough space for remain info, return */ + if (new_str->len >= BUFFERSIZE) { + strncpy (name, new_str->str, BUFFERSIZE); + return name; + } + + strcpy (name, new_str->str); + g_string_free (new_str, TRUE); + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name); + + return accessible->name; +} + +static G_CONST_RETURN gchar * +ea_minicard_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution minicard"); +} + +AtkObject* +ea_minicard_new (GObject *obj) +{ + GObject *object; + AtkObject *accessible; + + g_return_val_if_fail(obj != NULL, NULL); + g_return_val_if_fail (E_IS_MINICARD(obj), NULL); + + object = g_object_new (EA_TYPE_MINICARD, NULL); + accessible = ATK_OBJECT (object); + atk_object_initialize (accessible, obj); + + accessible->role = ATK_ROLE_PANEL; + return accessible; +} + +static AtkStateSet *ea_minicard_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set = NULL; + GObject *gobj = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj); + if ( !state_set ) + state_set = atk_state_set_new (); + + gobj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (obj)); + if ( !gobj ) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + + return state_set; +} + +static gint +ea_minicard_get_n_children (AtkObject *accessible) +{ + return 0; +} + +static AtkObject * +ea_minicard_ref_child (AtkObject *accessible, gint index) +{ + return NULL; +} + +static void atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = atk_action_interface_do_action; + iface->get_n_actions = atk_action_interface_get_n_action; + iface->get_description = atk_action_interface_get_description; + iface->get_name = atk_action_interface_get_name; +} + +static gboolean atk_action_interface_do_action (AtkAction *iface, gint i) +{ + EMinicard *minicard = NULL; + + minicard = E_MINICARD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (iface))); + if ( minicard == NULL ) + return FALSE; + + if ( i >= G_N_ELEMENTS (action_name) || i < 0 ) + return FALSE; + + switch (i) { + /* open card */ + case 0: + e_minicard_activate_editor (minicard); + break; + default: + return FALSE; + } + + return TRUE; +} + +static gint atk_action_interface_get_n_action (AtkAction *iface) +{ + return G_N_ELEMENTS (action_name); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_description (AtkAction *iface, gint i) +{ + return atk_action_interface_get_name (iface, i); +} + +static G_CONST_RETURN gchar * +atk_action_interface_get_name (AtkAction *iface, gint i) +{ + if ( i >= G_N_ELEMENTS (action_name) || i < 0) + return NULL; + + return action_name[i]; +} + diff --git a/addressbook/gui/widgets/ea-minicard.h b/addressbook/gui/widgets/ea-minicard.h new file mode 100644 index 0000000000..8b49ab6284 --- /dev/null +++ b/addressbook/gui/widgets/ea-minicard.h @@ -0,0 +1,56 @@ +/* + * 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: + * Leon Zhang <leon.zhang@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_MINICARD_H__ +#define __EA_MINICARD_H__ + +#include <atk/atkgobjectaccessible.h> +#include "e-minicard.h" +#include "e-minicard-label.h" + +G_BEGIN_DECLS + +#define EA_TYPE_MINICARD (ea_minicard_get_type ()) +#define EA_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_MINICARD, EaMinicard)) +#define EA_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_MINICARD, EaMiniCardClass)) +#define EA_IS_MINICARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_MINICARD)) +#define EA_IS_MINICARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EA_TYPE_MINICARD)) + +typedef struct _EaMinicard EaMinicard; +typedef struct _EaMinicardClass EaMinicardClass; + +struct _EaMinicard +{ + AtkGObjectAccessible parent; +}; + +struct _EaMinicardClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +GType ea_minicard_get_type (void); +AtkObject* ea_minicard_new(GObject *obj); + +G_END_DECLS + +#endif /* __EA_MINICARD_H__ */ diff --git a/addressbook/gui/widgets/eab-config.c b/addressbook/gui/widgets/eab-config.c index 91056e0544..f47a696195 100644 --- a/addressbook/gui/widgets/eab-config.c +++ b/addressbook/gui/widgets/eab-config.c @@ -27,7 +27,6 @@ #include "eab-config.h" static GObjectClass *ecp_parent_class; -static GObjectClass *ecph_parent_class; struct _EABConfigPrivate { guint source_changed_id; @@ -143,48 +142,3 @@ eab_config_target_new_source (EABConfig *ecp, struct _ESource *source) return t; } - -static const EConfigHookTargetMask ecph_no_masks[] = { - { NULL } -}; - -static const EConfigHookTargetMap ecph_targets[] = { - { "source", EAB_CONFIG_TARGET_SOURCE, ecph_no_masks }, - { NULL }, -}; - -static void -ecph_class_init (EPluginHookClass *klass) -{ - gint i; - - klass->id = "org.gnome.evolution.addressbook.config:1.0"; - - for (i = 0; ecph_targets[i].type; i++) { - e_config_hook_class_add_target_map ((EConfigHookClass *)klass, &ecph_targets[i]); - } - - ((EConfigHookClass *)klass)->config_class = g_type_class_ref (eab_config_get_type ()); -} - -GType -eab_config_hook_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (EABConfigHookClass), - NULL, NULL, - (GClassInitFunc) ecph_class_init, - NULL, NULL, - sizeof (EABConfigHook), 0, - (GInstanceInitFunc) NULL - }; - - ecph_parent_class = g_type_class_ref (e_config_hook_get_type ()); - type = g_type_register_static (e_config_hook_get_type (), "EABConfigHook", &info, 0); - } - - return type; -} diff --git a/addressbook/gui/widgets/eab-config.h b/addressbook/gui/widgets/eab-config.h index 8ecc8525bc..fcf6b76f00 100644 --- a/addressbook/gui/widgets/eab-config.h +++ b/addressbook/gui/widgets/eab-config.h @@ -60,21 +60,6 @@ EABConfig *eab_config_new (gint type, const gchar *menuid); EABConfigTargetSource *eab_config_target_new_source (EABConfig *ecp, struct _ESource *source); -/* ********************************************************************** */ - -typedef struct _EABConfigHook EABConfigHook; -typedef struct _EABConfigHookClass EABConfigHookClass; - -struct _EABConfigHook { - EConfigHook hook; -}; - -struct _EABConfigHookClass { - EConfigHookClass hook_class; -}; - -GType eab_config_hook_get_type (void); - G_END_DECLS #endif diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c index bea167cc45..d47b3e1866 100644 --- a/addressbook/gui/widgets/eab-contact-display.c +++ b/addressbook/gui/widgets/eab-contact-display.c @@ -25,27 +25,46 @@ #endif #include "eab-contact-display.h" -#include "eab-popup.h" #include "eab-gui-util.h" #include "e-util/e-util.h" #include "e-util/e-html-utils.h" #include "e-util/e-icon-factory.h" +#include "e-util/e-plugin-ui.h" #include <string.h> #include <glib/gi18n.h> #include <gtkhtml/gtkhtml.h> #include <gtkhtml/gtkhtml-stream.h> -#define HANDLE_MAILTO_INTERNALLY 1 +#define EAB_CONTACT_DISPLAY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayPrivate)) -#define PARENT_TYPE (GTK_TYPE_HTML) +#define HANDLE_MAILTO_INTERNALLY 1 struct _EABContactDisplayPrivate { EContact *contact; + EABContactDisplayMode mode; + GtkUIManager *ui_manager; + GtkActionGroup *email_actions; + GtkActionGroup *uri_actions; GtkWidget *invisible; - gchar *selection_uri; + + gchar *selected_uri; + gchar *clipboard_uri; +}; + +enum { + PROP_0, + PROP_CONTACT, + PROP_MODE +}; + +enum { + SEND_MESSAGE, + LAST_SIGNAL }; static struct { @@ -77,150 +96,154 @@ common_location [] = #define MAX_COMPACT_IMAGE_DIMENSION 48 -static void -eab_uri_popup_link_open(EPopup *ep, EPopupItem *item, gpointer data) -{ - EABPopupTargetURI *t = (EABPopupTargetURI *)ep->target; +static const gchar *ui = +"<ui>" +" <popup>" +" <menuitem action='open-link'/>" +" <menuitem action='copy-link'/>" +" <menuitem action='send-message'/>" +" <menuitem action='copy-address'/>" +" </popup>" +"</ui>"; - /* FIXME Pass a parent window. */ - e_show_uri (NULL, t->uri); -} +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; static void -eab_uri_popup_email_address_copy(EPopup *ep, EPopupItem *item, gpointer data) +action_copy_address_cb (GtkAction *action, + EABContactDisplay *display) { - EABContactDisplay *display = data; - struct _EABContactDisplayPrivate *p = display->priv; - EABPopupTargetURI *t = (EABPopupTargetURI *)ep->target; - const gchar *url = t->uri; - gchar *html=NULL; - gint i=0; - GList *email_list, *l; - gint email_num = atoi (url + strlen ("internal-mailto:")); - - email_list = e_contact_get (p->contact, E_CONTACT_EMAIL); - for (l = email_list; l; l=l->next) { - if (i==email_num) - html = e_text_to_html (l->data, 0); - i++; - } - - g_free(p->selection_uri); - p->selection_uri = g_strdup(html); - g_free (html); - - gtk_selection_owner_set(p->invisible, GDK_SELECTION_PRIMARY, gtk_get_current_event_time()); - gtk_selection_owner_set(p->invisible, GDK_SELECTION_CLIPBOARD, gtk_get_current_event_time()); + EContact *contact; + GList *list; + const gchar *uri; + gchar *html; + gint index; + + uri = display->priv->selected_uri; + index = atoi (uri + strlen ("internal-mailto:")); + contact = eab_contact_display_get_contact (display); + + list = e_contact_get (contact, E_CONTACT_EMAIL); + html = e_text_to_html (g_list_nth_data (list, index), 0); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + + display->priv->clipboard_uri = html; + display->priv->selected_uri = NULL; + + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_PRIMARY, + gtk_get_current_event_time ()); + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_CLIPBOARD, + gtk_get_current_event_time ()); } static void -eab_uri_popup_link_copy(EPopup *ep, EPopupItem *pitem, gpointer data) +action_copy_link_cb (GtkAction *action, + EABContactDisplay *display) { - EABContactDisplay *display = data; - struct _EABContactDisplayPrivate *p = display->priv; - - g_free(p->selection_uri); - p->selection_uri = g_strdup(pitem->user_data); - - gtk_selection_owner_set(p->invisible, GDK_SELECTION_PRIMARY, gtk_get_current_event_time()); - gtk_selection_owner_set(p->invisible, GDK_SELECTION_CLIPBOARD, gtk_get_current_event_time()); + display->priv->clipboard_uri = display->priv->selected_uri; + display->priv->selected_uri = NULL; + + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_PRIMARY, + gtk_get_current_event_time ()); + gtk_selection_owner_set ( + display->priv->invisible, GDK_SELECTION_CLIPBOARD, + gtk_get_current_event_time ()); } static void -eab_uri_popup_address_send(EPopup *ep, EPopupItem *item, gpointer data) +action_open_link_cb (GtkAction *action, + EABContactDisplay *display) { - EABPopupTargetURI *t = (EABPopupTargetURI *)ep->target; - const gchar *url = t->uri; - EABContactDisplay *display = data; - struct _EABContactDisplayPrivate *p = display->priv; - - gint mail_num = atoi (url + strlen ("internal-mailto:")); - - if (mail_num == -1) - return; - - eab_send_contact (p->contact, mail_num, EAB_DISPOSITION_AS_TO); - + /* XXX Pass a parent window. */ + e_show_uri (NULL, display->priv->selected_uri); } static void -eab_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint time_stamp, EABContactDisplay *display) +action_send_message_cb (GtkAction *action, + EABContactDisplay *display) { - struct _EABContactDisplayPrivate *p = display->priv; - - if (p->selection_uri == NULL) - return; - - gtk_selection_data_set(data, data->target, 8, (guchar *)p->selection_uri, strlen(p->selection_uri)); + EDestination *destination; + EContact *contact; + const gchar *uri; + gint row; + + uri = display->priv->selected_uri; + row = atoi (uri + strlen ("internal-mailto:")); + g_return_if_fail (row >= 0); + + destination = e_destination_new (); + contact = eab_contact_display_get_contact (display); + e_destination_set_contact (destination, contact, row); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); } -static void -eab_selection_clear_event(GtkWidget *widget, GdkEventSelection *event, EABContactDisplay *display) -{ -#if 0 - struct _EABContactDisplayPrivate *p = display->priv; - - g_free(p->selection_uri); - p->selection_uri = NULL; -#endif -} +static GtkActionEntry email_entries[] = { + + { "copy-address", + NULL, + N_("Copy _Email Address"), + NULL, + NULL, + G_CALLBACK (action_copy_address_cb) }, + + { "send-message", + NULL, + N_("_Send New Message To..."), + NULL, + NULL, + G_CALLBACK (action_send_message_cb) } +}; -static EPopupItem eab_uri_popups[] = { - { E_POPUP_ITEM, (gchar *) "05.open", (gchar *) N_("_Open Link in Browser"), eab_uri_popup_link_open, NULL, NULL, EAB_POPUP_URI_NOT_MAILTO }, - { E_POPUP_ITEM, (gchar *) "10.copy", (gchar *) N_("_Copy Link Location"), eab_uri_popup_link_copy, NULL, (gchar *) "edit-copy", EAB_POPUP_URI_NOT_MAILTO }, - { E_POPUP_ITEM, (gchar *) "15.send", (gchar *) N_("_Send New Message To..."), eab_uri_popup_address_send, NULL, (gchar *) "mail-message-new", EAB_POPUP_URI_MAILTO}, - { E_POPUP_ITEM, (gchar *) "20.copy", (gchar *) N_("Copy _Email Address"), eab_uri_popup_email_address_copy, NULL, (gchar *) "edit-copy", EAB_POPUP_URI_MAILTO}, - }; +static GtkActionEntry uri_entries[] = { + + { "copy-link", + NULL, + N_("_Copy Link Location"), + NULL, + NULL, + G_CALLBACK (action_copy_link_cb) }, + + { "open-link", + NULL, + N_("_Open Link in Browser"), + NULL, + NULL, + G_CALLBACK (action_open_link_cb) } +}; static void -eab_uri_popup_free(EPopup *ep, GSList *list, gpointer data) +contact_display_selection_get (EABContactDisplay *display, + GtkSelectionData *data, + guint info, + guint time_stamp) { - while (list) { - GSList *n = list->next; - struct _EPopupItem *item = list->data; - - g_free(item->user_data); - item->user_data = NULL; - g_slist_free_1(list); + if (display->priv->clipboard_uri == NULL) + return; - list = n; - } + gtk_selection_data_set ( + data, data->target, 8, + (guchar *) display->priv->clipboard_uri, + strlen (display->priv->clipboard_uri)); } -static gint -eab_uri_popup_event(EABContactDisplay *display, GdkEvent *event, const gchar *uri) +static void +contact_display_selection_clear_event (EABContactDisplay *display, + GdkEventSelection *event) { - EABPopup *emp; - EABPopupTargetURI *t; - GtkMenu *menu; - GSList *menus = NULL; - gint i; - - emp = eab_popup_new("org.gnome.evolution.addressbook.contactdisplay.popup"); - - t = eab_popup_target_new_uri(emp, uri); - t->target.widget = (GtkWidget *)display; - - for (i=0;i<sizeof(eab_uri_popups)/sizeof(eab_uri_popups[0]);i++) { - eab_uri_popups[i].user_data = g_strdup(t->uri); - menus = g_slist_prepend(menus, &eab_uri_popups[i]); - } - e_popup_add_items((EPopup *)emp, menus, NULL, eab_uri_popup_free, display); - - menu = e_popup_create_menu_once((EPopup *)emp,(EPopupTarget*)t, 0); - - if (event == NULL) { - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); - } else { - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); - } - - return TRUE; + g_free (display->priv->clipboard_uri); + display->priv->clipboard_uri = NULL; } static void -on_url_requested (GtkHTML *html, const gchar *url, GtkHTMLStream *handle, - EABContactDisplay *display) +contact_display_on_url_requested (GtkHTML *html, + const gchar *url, + GtkHTMLStream *handle, + EABContactDisplay *display) { if (!strcmp (url, "internal-contact-photo:")) { EContactPhoto *photo; @@ -253,16 +276,25 @@ on_url_requested (GtkHTML *html, const gchar *url, GtkHTMLStream *handle, } static void -on_link_clicked (GtkHTML *html, const gchar *uri, EABContactDisplay *display) +contact_display_on_link_clicked (GtkHTML *html, + const gchar *uri, + EABContactDisplay *display) { #ifdef HANDLE_MAILTO_INTERNALLY if (!strncmp (uri, "internal-mailto:", strlen ("internal-mailto:"))) { - gint mail_num = atoi (uri + strlen ("internal-mailto:")); + EDestination *destination; + EContact *contact; + gint email_num; - if (mail_num == -1) + email_num = atoi (uri + strlen ("internal-mailto:")); + if (email_num == -1) return; - eab_send_contact (display->priv->contact, mail_num, EAB_DISPOSITION_AS_TO); + destination = e_destination_new (); + contact = eab_contact_display_get_contact (display); + e_destination_set_contact (destination, contact, email_num); + g_signal_emit (display, signals[SEND_MESSAGE], 0, destination); + g_object_unref (destination); return; } @@ -272,44 +304,6 @@ on_link_clicked (GtkHTML *html, const gchar *uri, EABContactDisplay *display) e_show_uri (NULL, uri); } -#if 0 -static void -render_address (GtkHTMLStream *html_stream, EContact *contact, const gchar *html_label, EContactField adr_field, EContactField label_field) -{ - EContactAddress *adr; - const gchar *label; - - label = e_contact_get_const (contact, label_field); - if (label) { - gchar *html = e_text_to_html (label, E_TEXT_TO_HTML_CONVERT_NL); - - gtk_html_stream_printf (html_stream, "<tr><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td><td valign=\"top\" width=\"100\"><font color=" HEADER_COLOR ">%s:</font><br><a href=\"http://www.mapquest.com/\">%s</a></td><td valign=\"top\">%s</td></tr>", html_label, _("(map)"), html); - -This shoul g_free (html); - return; - } - - adr = e_contact_get (contact, adr_field); - if (adr && - (adr->po || adr->ext || adr->street || adr->locality || adr->region || adr->code || adr->country)) { - - gtk_html_stream_printf (html_stream, "<tr><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td><td valign=\"top\" width=\"100\"><font color=" HEADER_COLOR ">%s:</font><br><a href=\"http://www.mapquest.com/\">%s</a></td><td valign=\"top\">", html_label, _("map")); - - if (adr->po && *adr->po) gtk_html_stream_printf (html_stream, "%s<br>", adr->po); - if (adr->ext && *adr->ext) gtk_html_stream_printf (html_stream, "%s<br>", adr->ext); - if (adr->street && *adr->street) gtk_html_stream_printf (html_stream, "%s<br>", adr->street); - if (adr->locality && *adr->locality) gtk_html_stream_printf (html_stream, "%s<br>", adr->locality); - if (adr->region && *adr->region) gtk_html_stream_printf (html_stream, "%s<br>", adr->region); - if (adr->code && *adr->code) gtk_html_stream_printf (html_stream, "%s<br>", adr->code); - if (adr->country && *adr->country) gtk_html_stream_printf (html_stream, "%s<br>", adr->country); - - gtk_html_stream_printf (html_stream, "</td></tr>"); - } - if (adr) - e_contact_address_free (adr); -} -#endif - static void render_name_value (GtkHTMLStream *html_stream, const gchar *label, const gchar *str, const gchar *icon, guint html_flags) { @@ -667,12 +661,6 @@ eab_contact_display_render_normal (EABContactDisplay *display, EContact *contact GtkHTMLStream *html_stream; gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL); - if (display->priv->contact) - g_object_unref (display->priv->contact); - display->priv->contact = contact; - if (display->priv->contact) - g_object_ref (display->priv->contact); - html_stream = gtk_html_begin (GTK_HTML (display)); gtk_html_stream_write (html_stream, HTML_HEADER, sizeof (HTML_HEADER) - 1); gtk_html_stream_printf (html_stream, "<body><table width=\"100%%\"><tr><td %s>\n", is_rtl ? " align=\"right\" " : ""); @@ -722,16 +710,11 @@ eab_contact_display_render_normal (EABContactDisplay *display, EContact *contact } static void -eab_contact_display_render_compact (EABContactDisplay *display, EContact *contact) +eab_contact_display_render_compact (EABContactDisplay *display, + EContact *contact) { GtkHTMLStream *html_stream; - if (display->priv->contact) - g_object_unref (display->priv->contact); - display->priv->contact = contact; - if (display->priv->contact) - g_object_ref (display->priv->contact); - html_stream = gtk_html_begin (GTK_HTML (display)); gtk_html_stream_write (html_stream, HTML_HEADER, sizeof (HTML_HEADER) - 1); gtk_html_stream_write (html_stream, "<body>\n", 7); @@ -905,97 +888,266 @@ eab_contact_display_render_compact (EABContactDisplay *display, EContact *contac gtk_html_end (GTK_HTML (display), html_stream, GTK_HTML_STREAM_OK); } -void -eab_contact_display_render (EABContactDisplay *display, EContact *contact, - EABContactDisplayRenderMode mode) +static gint +contact_display_button_press_event (GtkWidget *widget, + GdkEvent *event, + EABContactDisplay *display) { - switch (mode) { - case EAB_CONTACT_DISPLAY_RENDER_NORMAL: - eab_contact_display_render_normal (display, contact); - break; - case EAB_CONTACT_DISPLAY_RENDER_COMPACT: - eab_contact_display_render_compact (display, contact); - break; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + GtkWidget *menu; + gboolean has_email; + gchar *uri; + + if (event->button.button != 3) + return FALSE; + + uri = gtk_html_get_url_at ( + GTK_HTML (widget), + event->button.x, event->button.y); + + if (uri == NULL) + return FALSE; + + g_free (display->priv->selected_uri); + display->priv->selected_uri = uri; + + ui_manager = display->priv->ui_manager; + menu = gtk_ui_manager_get_widget (ui_manager, "/popup"); + g_return_val_if_fail (GTK_IS_MENU (menu), FALSE); + + has_email = (g_ascii_strncasecmp (uri, "internal-mailto:", 16) == 0); + + /* Show the appropriate actions. */ + action_group = display->priv->email_actions; + gtk_action_group_set_visible (action_group, has_email); + action_group = display->priv->uri_actions; + gtk_action_group_set_visible (action_group, !has_email); + + if (event != NULL) + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + event->button.button, event->button.time); + else + gtk_menu_popup ( + GTK_MENU (menu), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time ()); + + return TRUE; +} + +static void +contact_display_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_CONTACT: + eab_contact_display_set_contact ( + EAB_CONTACT_DISPLAY (object), + g_value_get_object (value)); + return; + + case PROP_MODE: + eab_contact_display_set_mode ( + EAB_CONTACT_DISPLAY (object), + g_value_get_int (value)); + return; } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -static gint -eab_html_press_event (GtkWidget *widget, GdkEvent *event,EABContactDisplay *display) +static void +contact_display_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - gchar *uri; - gboolean res = FALSE; + switch (property_id) { + case PROP_CONTACT: + g_value_set_object ( + value, eab_contact_display_get_contact ( + EAB_CONTACT_DISPLAY (object))); + return; - if (event->button.button!= 3 ) - return FALSE; + case PROP_MODE: + g_value_set_int ( + value, eab_contact_display_get_mode ( + EAB_CONTACT_DISPLAY (object))); + return; + } - uri = gtk_html_get_url_at (GTK_HTML (widget), event->button.x, event->button.y); - if (uri) { - eab_uri_popup_event(display,event,uri); - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - g_free(uri); +static void +contact_display_dispose (GObject *object) +{ + EABContactDisplayPrivate *priv; - return res; + priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (object); + + if (priv->contact != NULL) { + g_object_unref (priv->contact); + priv->contact = NULL; + } + + if (priv->ui_manager != NULL) { + g_object_unref (priv->ui_manager); + priv->ui_manager = NULL; + } + + if (priv->email_actions != NULL) { + g_object_unref (priv->email_actions); + priv->email_actions = NULL; + } + + if (priv->uri_actions != NULL) { + g_object_unref (priv->uri_actions); + priv->uri_actions = NULL; + } + + if (priv->invisible != NULL) { + g_object_unref (priv->invisible); + priv->invisible = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } -GtkWidget* -eab_contact_display_new (void) +static void +contact_display_finalize (GObject *object) { - EABContactDisplay *display; - - struct _EABContactDisplayPrivate *p; - - display = g_object_new (EAB_TYPE_CONTACT_DISPLAY, NULL); - p=display->priv = g_new0 (EABContactDisplayPrivate, 1); - - gtk_html_set_default_content_type (GTK_HTML (display), "text/html; charset=utf-8"); - - gtk_html_set_editable (GTK_HTML (display), FALSE); - - g_signal_connect (display, "url_requested", - G_CALLBACK (on_url_requested), - display); - g_signal_connect (display, "link_clicked", - G_CALLBACK (on_link_clicked), - display); - g_signal_connect(display, "button_press_event", - G_CALLBACK(eab_html_press_event), - display); - p->invisible = gtk_invisible_new(); - g_signal_connect(p->invisible, "selection_get", G_CALLBACK(eab_selection_get), display); - g_signal_connect(p->invisible, "selection_clear_event", G_CALLBACK(eab_selection_clear_event), display); - gtk_selection_add_target(p->invisible, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 0); - gtk_selection_add_target(p->invisible, GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1); - -#if 0 - g_signal_connect (display, "object_requested", - G_CALLBACK (on_object_requested), - mail_display); - g_signal_connect (display, "button_press_event", - G_CALLBACK (html_button_press_event), mail_display); - g_signal_connect (display, "motion_notify_event", - G_CALLBACK (html_motion_notify_event), mail_display); - g_signal_connect (display, "enter_notify_event", - G_CALLBACK (html_enter_notify_event), mail_display); - g_signal_connect (display, "iframe_created", - G_CALLBACK (html_iframe_created), mail_display); - g_signal_connect (display, "on_url", - G_CALLBACK (html_on_url), mail_display); -#endif + EABContactDisplayPrivate *priv; + + priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (object); - return GTK_WIDGET (display); + g_free (priv->selected_uri); + g_free (priv->clipboard_uri); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -eab_contact_display_init (GObject *object) +eab_contact_display_class_init (EABContactDisplayClass *class) { - gtk_html_construct ((GtkHTML *)object); + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EABContactDisplayPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = contact_display_set_property; + object_class->get_property = contact_display_get_property; + object_class->dispose = contact_display_dispose; + object_class->finalize = contact_display_finalize; + + g_object_class_install_property ( + object_class, + PROP_CONTACT, + g_param_spec_object ( + "contact", + NULL, + NULL, + E_TYPE_CONTACT, + G_PARAM_READWRITE)); + + /* XXX Make this a real enum property. */ + g_object_class_install_property ( + object_class, + PROP_MODE, + g_param_spec_int ( + "mode", + NULL, + NULL, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + EAB_CONTACT_DISPLAY_RENDER_COMPACT, + EAB_CONTACT_DISPLAY_RENDER_NORMAL, + G_PARAM_READWRITE)); + + signals[SEND_MESSAGE] = g_signal_new ( + "send-message", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EABContactDisplayClass, send_message), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + E_TYPE_DESTINATION); } static void -eab_contact_display_class_init (GtkObjectClass *object_class) +eab_contact_display_init (EABContactDisplay *display) { - /* object_class->destroy = mail_display_destroy;*/ + GtkActionGroup *action_group; + GtkHTML *html; + const gchar *id; + + display->priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (display); + display->priv->mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; + display->priv->ui_manager = gtk_ui_manager_new (); + display->priv->invisible = gtk_invisible_new (); + + g_object_ref_sink (display->priv->invisible); + + action_group = gtk_action_group_new ("email"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, email_entries, + G_N_ELEMENTS (email_entries), display); + gtk_ui_manager_insert_action_group ( + display->priv->ui_manager, action_group, 0); + display->priv->email_actions = action_group; + + action_group = gtk_action_group_new ("uri"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, uri_entries, + G_N_ELEMENTS (uri_entries), display); + gtk_ui_manager_insert_action_group ( + display->priv->ui_manager, action_group, 0); + display->priv->uri_actions = action_group; + + gtk_ui_manager_add_ui_from_string ( + display->priv->ui_manager, ui, -1, NULL); + + html = GTK_HTML (display); + gtk_html_construct (html); + gtk_html_set_editable (html, FALSE); + gtk_html_set_default_content_type (html, "text/html; charset=utf-8"); + + g_signal_connect ( + display, "url-requested", + G_CALLBACK (contact_display_on_url_requested), display); + g_signal_connect ( + display, "link-clicked", + G_CALLBACK (contact_display_on_link_clicked), display); + g_signal_connect ( + display, "button-press-event", + G_CALLBACK (contact_display_button_press_event), display); + + g_signal_connect_swapped ( + display->priv->invisible, "selection-get", + G_CALLBACK (contact_display_selection_get), display); + g_signal_connect_swapped ( + display->priv->invisible, "selection-clear-event", + G_CALLBACK (contact_display_selection_clear_event), display); + gtk_selection_add_target ( + display->priv->invisible, + GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 0); + gtk_selection_add_target ( + display->priv->invisible, + GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1); + + id = "org.gnome.evolution.contact-display"; + e_plugin_ui_register_manager (display->priv->ui_manager, id, display); + e_plugin_ui_enable_manager (display->priv->ui_manager, id); } GType @@ -1003,21 +1155,98 @@ eab_contact_display_get_type (void) { static GType type = 0; - if (!type) { - static const GTypeInfo info = { + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { sizeof (EABContactDisplayClass), - NULL, /* base_init */ - NULL, /* base_finalize */ + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, (GClassInitFunc) eab_contact_display_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EABContactDisplay), - 0, /* n_preallocs */ + 0, /* n_preallocs */ (GInstanceInitFunc) eab_contact_display_init, + NULL /* value_table */ }; - type = g_type_register_static (PARENT_TYPE, "EABContactDisplay", &info, 0); + type = g_type_register_static ( + GTK_TYPE_HTML, "EABContactDisplay", &type_info, 0); } return type; } + +GtkWidget * +eab_contact_display_new (void) +{ + return g_object_new (EAB_TYPE_CONTACT_DISPLAY, NULL); +} + +EContact * +eab_contact_display_get_contact (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), NULL); + + return display->priv->contact; +} + +void +eab_contact_display_set_contact (EABContactDisplay *display, + EContact *contact) +{ + EABContactDisplayMode mode; + + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + mode = eab_contact_display_get_mode (display); + + if (contact != NULL) + g_object_ref (contact); + if (display->priv->contact != NULL) + g_object_unref (display->priv->contact); + display->priv->contact = contact; + + switch (mode) { + case EAB_CONTACT_DISPLAY_RENDER_NORMAL: + eab_contact_display_render_normal (display, contact); + break; + + case EAB_CONTACT_DISPLAY_RENDER_COMPACT: + eab_contact_display_render_compact (display, contact); + break; + } + + g_object_notify (G_OBJECT (display), "contact"); +} + +EABContactDisplayMode +eab_contact_display_get_mode (EABContactDisplay *display) +{ + g_return_val_if_fail (EAB_IS_CONTACT_DISPLAY (display), 0); + + return display->priv->mode; +} + +void +eab_contact_display_set_mode (EABContactDisplay *display, + EABContactDisplayMode mode) +{ + EContact *contact; + + g_return_if_fail (EAB_IS_CONTACT_DISPLAY (display)); + + display->priv->mode = mode; + contact = eab_contact_display_get_contact (display); + + switch (mode) { + case EAB_CONTACT_DISPLAY_RENDER_NORMAL: + eab_contact_display_render_normal (display, contact); + break; + + case EAB_CONTACT_DISPLAY_RENDER_COMPACT: + eab_contact_display_render_compact (display, contact); + break; + } + + g_object_notify (G_OBJECT (display), "mode"); +} diff --git a/addressbook/gui/widgets/eab-contact-display.h b/addressbook/gui/widgets/eab-contact-display.h index 80acc5eefe..5a6902fc20 100644 --- a/addressbook/gui/widgets/eab-contact-display.h +++ b/addressbook/gui/widgets/eab-contact-display.h @@ -20,41 +20,67 @@ * */ -#ifndef _EAB_CONTACT_DISPLAY_H_ -#define _EAB_CONTACT_DISPLAY_H_ +#ifndef EAB_CONTACT_DISPLAY_H +#define EAB_CONTACT_DISPLAY_H #include <gtkhtml/gtkhtml.h> #include <libebook/e-contact.h> +#include <libebook/e-destination.h> -#define EAB_TYPE_CONTACT_DISPLAY (eab_contact_display_get_type ()) -#define EAB_CONTACT_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplay)) -#define EAB_CONTACT_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) -#define IS_EAB_CONTACT_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EAB_TYPE_CONTACT_DISPLAY)) -#define IS_EAB_CONTACT_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EAB_TYPE_CONTACT_DISPLAY)) +/* Standard GObject macros */ +#define EAB_TYPE_CONTACT_DISPLAY \ + (eab_contact_display_get_type ()) +#define EAB_CONTACT_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplay)) +#define EAB_CONTACT_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) +#define EAB_IS_CONTACT_DISPLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), EAB_TYPE_CONTACT_DISPLAY)) +#define EAB_IS_CONTACT_DISPLAY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), EAB_TYPE_CONTACT_DISPLAY)) +#define EAB_CONTACT_DISPLAY_GET_CLASS(obj) \ + (G_TYPE_ISNTANCE_GET_CLASS \ + ((obj), EAB_TYPE_CONTACT_DISPLAY, EABContactDisplayClass)) + +G_BEGIN_DECLS typedef struct _EABContactDisplay EABContactDisplay; -typedef struct _EABContactDisplayPrivate EABContactDisplayPrivate; typedef struct _EABContactDisplayClass EABContactDisplayClass; +typedef struct _EABContactDisplayPrivate EABContactDisplayPrivate; typedef enum { EAB_CONTACT_DISPLAY_RENDER_NORMAL, /* for use in the preview pane */ EAB_CONTACT_DISPLAY_RENDER_COMPACT /* for use with embedded vcards (e.g, the EABVCardControl) */ -} EABContactDisplayRenderMode; +} EABContactDisplayMode; struct _EABContactDisplay { GtkHTML parent; - EABContactDisplayPrivate *priv; }; struct _EABContactDisplayClass { GtkHTMLClass parent_class; + + /* Signals */ + void (*send_message) (EABContactDisplay *display, + EDestination *destination); }; -GType eab_contact_display_get_type (void); -GtkWidget * eab_contact_display_new (void); +GType eab_contact_display_get_type (void); +GtkWidget * eab_contact_display_new (void); + +EContact * eab_contact_display_get_contact (EABContactDisplay *display); +void eab_contact_display_set_contact (EABContactDisplay *display, + EContact *contact); +EABContactDisplayMode + eab_contact_display_get_mode (EABContactDisplay *display); +void eab_contact_display_set_mode (EABContactDisplay *display, + EABContactDisplayMode mode); -void eab_contact_display_render (EABContactDisplay *display, EContact *contact, - EABContactDisplayRenderMode render_mode); +G_END_DECLS -#endif /* _EAB_CONTACT_DISPLAY_H_ */ +#endif /* EAB_CONTACT_DISPLAY_H */ diff --git a/addressbook/gui/widgets/eab-gui-util.c b/addressbook/gui/widgets/eab-gui-util.c index c11ff5351a..effea132c3 100644 --- a/addressbook/gui/widgets/eab-gui-util.c +++ b/addressbook/gui/widgets/eab-gui-util.c @@ -40,17 +40,11 @@ #include "misc/e-image-chooser.h" #include <e-util/e-icon-factory.h> #include "eab-contact-merging.h" -#include <composer/e-msg-composer.h> -#include <mail/em-composer-utils.h> /* we link to camel for decoding quoted printable email addresses */ #include <camel/camel-mime-utils.h> -#include "addressbook/gui/contact-editor/eab-editor.h" -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" -#include "addressbook/gui/component/addressbook-component.h" -#include "addressbook/gui/component/addressbook.h" +#include "addressbook/util/addressbook.h" /* the NULL's in this table correspond to the status codes that should *never* be generated by a backend */ @@ -201,139 +195,6 @@ eab_prompt_save_dialog (GtkWindow *parent) return e_error_run (parent, "addressbook:prompt-save", NULL); } -static void -added_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK && status != E_BOOK_ERROR_CANCELLED) { - eab_error_dialog (is_list ? _("Error adding list") : _("Error adding contact"), status); - } -} - -static void -modified_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK && status != E_BOOK_ERROR_CANCELLED) { - eab_error_dialog (is_list ? _("Error modifying list") : _("Error modifying contact"), - status); - } -} - -static void -deleted_cb (EBook* book, EBookStatus status, EContact *contact, - gpointer data) -{ - gboolean is_list = GPOINTER_TO_INT (data); - - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (is_list ? _("Error removing list") : _("Error removing contact"), - status); - } -} - -static void -editor_closed_cb (GtkObject *editor, gpointer data) -{ - g_object_unref (editor); -} - -EContactEditor * -eab_show_contact_editor (EBook *book, EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactEditor *ce; - - ce = e_contact_editor_new (book, contact, is_new_contact, editable); - - g_signal_connect (ce, "contact_added", - G_CALLBACK (added_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "contact_modified", - G_CALLBACK (modified_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "contact_deleted", - G_CALLBACK (deleted_cb), GINT_TO_POINTER (FALSE)); - g_signal_connect (ce, "editor_closed", - G_CALLBACK (editor_closed_cb), NULL); - - return ce; -} - -EContactListEditor * -eab_show_contact_list_editor (EBook *book, EContact *contact, - gboolean is_new_contact, - gboolean editable) -{ - EContactListEditor *ce; - - ce = e_contact_list_editor_new (book, contact, is_new_contact, editable); - - g_signal_connect (ce, "contact_added", - G_CALLBACK (added_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "contact_modified", - G_CALLBACK (modified_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "contact_deleted", - G_CALLBACK (deleted_cb), GINT_TO_POINTER (TRUE)); - g_signal_connect (ce, "editor_closed", - G_CALLBACK (editor_closed_cb), GINT_TO_POINTER (TRUE)); - - eab_editor_show (EAB_EDITOR (ce)); - - return ce; -} - -static void -view_contacts (EBook *book, GList *list, gboolean editable) -{ - for (; list; list = list->next) { - EContact *contact = list->data; - if (e_contact_get (contact, E_CONTACT_IS_LIST)) - eab_show_contact_list_editor (book, contact, FALSE, editable); - else - eab_show_contact_editor (book, contact, FALSE, editable); - } -} - -void -eab_show_multiple_contacts (EBook *book, - GList *list, - gboolean editable) -{ - if (list) { - gint length = g_list_length (list); - if (length > 5) { - GtkWidget *dialog; - gint response; - - dialog = gtk_message_dialog_new (NULL, - 0, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - ngettext("Opening %d contact will open %d new window as well.\n" - "Do you really want to display this contact?", - "Opening %d contacts will open %d new windows as well.\n" - "Do you really want to display all of these contacts?", - length), - length, - length); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - _("_Don't Display"), GTK_RESPONSE_NO, - _("Display _All Contacts"), GTK_RESPONSE_YES, - NULL); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - if (response == GTK_RESPONSE_YES) - view_contacts (book, list, editable); - } else { - view_contacts (book, list, editable); - } - } -} - static gint file_exists(GtkWindow *window, const gchar *filename) { @@ -627,16 +488,6 @@ struct ContactCopyProcess_ { ContactCopyDone done_cb; }; -#if 0 -static void -contact_deleted_cb (EBook* book, EBookStatus status, gpointer user_data) -{ - if (status != E_BOOK_ERROR_OK) { - eab_error_dialog (_("Error removing contact"), status); - } -} -#endif - static void do_delete (gpointer data, gpointer user_data) { @@ -781,234 +632,6 @@ eab_transfer_contacts (EBook *source, GList *contacts /* adopted */, gboolean de addressbook_load (dest, got_book_cb, process); } -typedef struct { - EContact *contact; - gint email_num; /* if the contact is a person (not a list), the email address to use */ -} ContactAndEmailNum; - -static void -eab_send_to_contact_and_email_num_list (GList *contact_list) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - GPtrArray *to_array; - GPtrArray *bcc_array; - - union { - gpointer *pdata; - EDestination **destinations; - } convert; - - if (contact_list == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); - - to_array = g_ptr_array_new (); - bcc_array = g_ptr_array_new (); - - /* Sort contacts into "To" and "Bcc" destinations. */ - while (contact_list != NULL) { - ContactAndEmailNum *ce = contact_list->data; - EContact *contact = ce->contact; - EDestination *destination; - - destination = e_destination_new (); - e_destination_set_contact (destination, contact, 0); - - if (e_destination_is_evolution_list (destination)) { - if (e_destination_list_show_addresses (destination)) - g_ptr_array_add (to_array, destination); - else - g_ptr_array_add (bcc_array, destination); - } else - g_ptr_array_add (to_array, destination); - - contact_list = g_list_next (contact_list); - } - - /* Add sentinels to each array. */ - g_ptr_array_add (to_array, NULL); - g_ptr_array_add (bcc_array, NULL); - - /* XXX Acrobatics like this make me question whether NULL-terminated - * arrays are really the best argument type for passing a list of - * destinations to the header table. */ - - /* Set "To" destinations. */ - convert.pdata = to_array->pdata; - e_composer_header_table_set_destinations_to ( - table, convert.destinations); - g_ptr_array_free (to_array, FALSE); - e_destination_freev (convert.destinations); - - /* Add "Bcc" destinations. - * Add destinations instead of setting, so we don't remove - * automatic BCC addresses that have already been added. */ - convert.pdata = bcc_array->pdata; - e_composer_header_table_add_destinations_bcc ( - table, convert.destinations); - g_ptr_array_free (bcc_array, FALSE); - e_destination_freev (convert.destinations); - - gtk_widget_show (GTK_WIDGET (composer)); -} - -static const gchar * -get_email (EContact *contact, EContactField field_id, gchar **to_free) -{ - gchar *name = NULL, *mail = NULL; - const gchar *value = e_contact_get_const (contact, field_id); - - *to_free = NULL; - - if (eab_parse_qp_email (value, &name, &mail)) { - *to_free = g_strdup_printf ("%s <%s>", name, mail); - value = *to_free; - } - - g_free (name); - g_free (mail); - - return value; -} - -static void -eab_send_contact_list_as_attachment (GList *contacts) -{ - EMsgComposer *composer; - EComposerHeaderTable *table; - CamelMimePart *attachment; - gchar *data; - - if (contacts == NULL) - return; - - composer = e_msg_composer_new (); - table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); - - attachment = camel_mime_part_new (); - data = eab_contact_list_to_string (contacts); - - camel_mime_part_set_content ( - attachment, data, strlen (data), "text/x-vcard"); - - if (contacts->next != NULL) - camel_mime_part_set_description ( - attachment, _("Multiple vCards")); - else { - EContact *contact = contacts->data; - const gchar *file_as; - gchar *description; - - file_as = e_contact_get_const (contact, E_CONTACT_FILE_AS); - description = g_strdup_printf (_("vCard for %s"), file_as); - camel_mime_part_set_description (attachment, description); - g_free (description); - } - - camel_mime_part_set_disposition (attachment, "attachment"); - - e_msg_composer_attach (composer, attachment); - camel_object_unref (attachment); - - if (contacts->next != NULL) - e_composer_header_table_set_subject ( - table, _("Contact information")); - else { - EContact *contact = contacts->data; - gchar *tempstr; - const gchar *tempstr2; - gchar *tempfree = NULL; - - tempstr2 = e_contact_get_const (contact, E_CONTACT_FILE_AS); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_FULL_NAME); - if (!tempstr2 || !*tempstr2) - tempstr2 = e_contact_get_const (contact, E_CONTACT_ORG); - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_1, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_2, &tempfree); - } - if (!tempstr2 || !*tempstr2) { - g_free (tempfree); - tempstr2 = get_email (contact, E_CONTACT_EMAIL_3, &tempfree); - } - - if (!tempstr2 || !*tempstr2) - tempstr = g_strdup_printf (_("Contact information")); - else - tempstr = g_strdup_printf (_("Contact information for %s"), tempstr2); - - e_composer_header_table_set_subject (table, tempstr); - - g_free (tempstr); - g_free (tempfree); - } - - gtk_widget_show (GTK_WIDGET (composer)); -} - -void -eab_send_contact_list (GList *contacts, EABDisposition disposition) -{ - switch (disposition) { - case EAB_DISPOSITION_AS_TO: { - GList *list = NULL, *l; - - for (l = contacts; l; l = l->next) { - ContactAndEmailNum *ce = g_new (ContactAndEmailNum, 1); - ce->contact = l->data; - ce->email_num = 0; /* hardcode this */ - - list = g_list_append (list, ce); - } - - eab_send_to_contact_and_email_num_list (list); - - g_list_foreach (list, (GFunc)g_free, NULL); - g_list_free (list); - break; - } - case EAB_DISPOSITION_AS_ATTACHMENT: - eab_send_contact_list_as_attachment (contacts); - break; - } -} - -void -eab_send_contact (EContact *contact, gint email_num, EABDisposition disposition) -{ - GList *list = NULL; - - switch (disposition) { - case EAB_DISPOSITION_AS_TO: { - ContactAndEmailNum ce; - - ce.contact = contact; - ce.email_num = email_num; - - list = g_list_prepend (NULL, &ce); - eab_send_to_contact_and_email_num_list (list); - break; - } - case EAB_DISPOSITION_AS_ATTACHMENT: { - list = g_list_prepend (NULL, contact); - eab_send_contact_list_as_attachment (list); - break; - } - } - - g_list_free (list); -} - GtkWidget * eab_create_image_chooser_widget(gchar *name, gchar *string1, gchar *string2, diff --git a/addressbook/gui/widgets/eab-gui-util.h b/addressbook/gui/widgets/eab-gui-util.h index cc7b127aaf..7422eabb65 100644 --- a/addressbook/gui/widgets/eab-gui-util.h +++ b/addressbook/gui/widgets/eab-gui-util.h @@ -26,8 +26,6 @@ #include <gtk/gtk.h> #include <libebook/e-book.h> -#include "addressbook/gui/contact-editor/e-contact-editor.h" -#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h" G_BEGIN_DECLS @@ -40,17 +38,6 @@ void eab_search_result_dialog (GtkWidget *parent, EBookViewStatus status); gint eab_prompt_save_dialog (GtkWindow *parent); -EContactEditor *eab_show_contact_editor (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -EContactListEditor *eab_show_contact_list_editor (EBook *book, - EContact *contact, - gboolean is_new_contact, - gboolean editable); -void eab_show_multiple_contacts (EBook *book, - GList *list, - gboolean editable); void eab_transfer_contacts (EBook *source, GList *contacts, /* adopted */ gboolean delete_from_source, @@ -64,25 +51,16 @@ void eab_contact_list_save (gchar *title, GList *list, GtkWindow *parent_window); -typedef enum { - EAB_DISPOSITION_AS_ATTACHMENT, - EAB_DISPOSITION_AS_TO -} EABDisposition; - -void eab_send_contact (EContact *contact, - gint email_num, - EABDisposition disposition); -void eab_send_contact_list (GList *contacts, - EABDisposition disposition); - GtkWidget *eab_create_image_chooser_widget (gchar *name, gchar *string1, gchar *string2, gint int1, gint int2); ESource *eab_select_source (const gchar *title, const gchar *message, const gchar *select_uid, GtkWindow *parent); /* To parse quoted printable address & return email & name fields */ -gboolean eab_parse_qp_email (const gchar *string, gchar **name, gchar **email); -gchar *eab_parse_qp_email_to_html (const gchar *string); +gboolean eab_parse_qp_email (const gchar *string, + gchar **name, + gchar **email); +gchar * eab_parse_qp_email_to_html (const gchar *string); G_END_DECLS diff --git a/addressbook/gui/widgets/eab-menu.c b/addressbook/gui/widgets/eab-menu.c deleted file mode 100644 index e26e621437..0000000000 --- a/addressbook/gui/widgets/eab-menu.c +++ /dev/null @@ -1,258 +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 <libebook/e-contact.h> - -#include "eab-menu.h" - -static void eabm_standard_menu_factory(EMenu *emp, gpointer data); - -static GObjectClass *eabm_parent; - -static void -eabm_init(GObject *o) -{ - /*EABMenu *emp = (EABMenu *)o; */ -} - -static void -eabm_finalise(GObject *o) -{ - ((GObjectClass *)eabm_parent)->finalize(o); -} - -static void -eabm_target_free(EMenu *ep, EMenuTarget *t) -{ - switch (t->type) { - case EAB_MENU_TARGET_SELECT: { - EABMenuTargetSelect *s = (EABMenuTargetSelect *)t; - gint i; - - for (i=0;i<s->cards->len;i++) - g_object_unref(s->cards->pdata[i]); - g_ptr_array_free(s->cards, TRUE); - if (s->book) - g_object_unref(s->book); - break; } - } - - ((EMenuClass *)eabm_parent)->target_free(ep, t); -} - -static void -eabm_class_init(GObjectClass *klass) -{ - klass->finalize = eabm_finalise; - ((EMenuClass *)klass)->target_free = eabm_target_free; - - e_menu_class_add_factory((EMenuClass *)klass, NULL, (EMenuFactoryFunc)eabm_standard_menu_factory, NULL); -} - -GType -eab_menu_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EABMenuClass), - NULL, NULL, - (GClassInitFunc)eabm_class_init, - NULL, NULL, - sizeof(EABMenu), 0, - (GInstanceInitFunc)eabm_init - }; - eabm_parent = g_type_class_ref(e_menu_get_type()); - type = g_type_register_static(e_menu_get_type(), "EABMenu", &info, 0); - } - - return type; -} - -EABMenu *eab_menu_new(const gchar *menuid) -{ - EABMenu *emp = g_object_new(eab_menu_get_type(), NULL); - - e_menu_construct(&emp->menu, menuid); - - return emp; -} - -/** - * eab_menu_target_new_select - create a menu target of the current selection. - * @eabp: Address book menu. - * @book: Book the cards belong to. May be NULL in which case cards must be an empty GPtrArray. - * @readonly: Book is read-only mode. FIXME: Why can't we just get this off the book? - * @cards: Cards selected. This will be freed on completion and the array indices unreferenced. - * - * Create a new selection menu target. - * - * Return value: - **/ -EABMenuTargetSelect * -eab_menu_target_new_select(EABMenu *eabp, struct _EBook *book, gint readonly, GPtrArray *cards) -{ - EABMenuTargetSelect *t = e_menu_target_new(&eabp->menu, EAB_MENU_TARGET_SELECT, sizeof(*t)); - guint32 mask = ~0; - gint has_email = FALSE, i; - - /* FIXME: duplicated in eab-popup.c */ - - t->book = book; - if (book) - g_object_ref(book); - t->cards = cards; - - for (i=0;i<cards->len && !has_email;i++) { - EContact *contact = cards->pdata[i]; - GList *email; - - email = e_contact_get(E_CONTACT(contact), E_CONTACT_EMAIL); - if (email) { - has_email = TRUE; - - g_list_foreach(email, (GFunc)g_free, NULL); - g_list_free(email); - } - } - - if (has_email) - mask &= ~EAB_MENU_SELECT_EMAIL; - - if (!readonly) - mask &= ~EAB_MENU_SELECT_EDITABLE; - - if (cards->len == 1) - mask &= ~EAB_MENU_SELECT_ONE; - - if (cards->len > 1) - mask &= ~EAB_MENU_SELECT_MANY; - - if (cards->len >= 1) - mask &= ~EAB_MENU_SELECT_ANY; - - t->target.mask = mask; - - return t; -} - -static void -eabm_standard_menu_factory(EMenu *emp, gpointer data) -{ - /* noop */ -} - -/* ********************************************************************** */ - -/* menu plugin handler */ - -/* -<e-plugin - class="org.gnome.mail.plugin.popup:1.0" - id="org.gnome.mail.plugin.popup.item:1.0" - type="shlib" - location="/opt/gnome2/lib/camel/1.0/libcamelimap.so" - name="imap" - description="IMAP4 and IMAP4v1 mail store"> - <hook class="org.gnome.mail.popupMenu:1.0" - handler="HandlePopup"> - <menu id="any" target="select"> - <item - type="item|toggle|radio|image|submenu|bar" - active - path="foo/bar" - label="label" - icon="foo" - mask="select_one" - activate="eabm_view_emacs"/> - </menu> - </extension> - -*/ - -static gpointer eabmph_parent_class; -#define eabmph ((EABMenuHook *)eph) - -static const EMenuHookTargetMask eabmph_select_masks[] = { - { "one", EAB_MENU_SELECT_ONE }, - { "many", EAB_MENU_SELECT_MANY }, - { "any", EAB_MENU_SELECT_ANY }, - { "editable", EAB_MENU_SELECT_EDITABLE }, - { "email", EAB_MENU_SELECT_EMAIL }, - { NULL } -}; - -static const EMenuHookTargetMap eabmph_targets[] = { - { "select", EAB_MENU_TARGET_SELECT, eabmph_select_masks }, - { NULL } -}; - -static void -eabmph_finalise(GObject *o) -{ - /*EPluginHook *eph = (EPluginHook *)o;*/ - - ((GObjectClass *)eabmph_parent_class)->finalize(o); -} - -static void -eabmph_class_init(EPluginHookClass *klass) -{ - gint i; - - ((GObjectClass *)klass)->finalize = eabmph_finalise; - ((EPluginHookClass *)klass)->id = "org.gnome.evolution.addressbook.bonobomenu:1.0"; - - for (i=0;eabmph_targets[i].type;i++) - e_menu_hook_class_add_target_map((EMenuHookClass *)klass, &eabmph_targets[i]); - - /* FIXME: leaks parent set class? */ - ((EMenuHookClass *)klass)->menu_class = g_type_class_ref(eab_menu_get_type()); -} - -GType -eab_menu_hook_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(EABMenuHookClass), NULL, NULL, (GClassInitFunc) eabmph_class_init, NULL, NULL, - sizeof(EABMenuHook), 0, (GInstanceInitFunc) NULL, - }; - - eabmph_parent_class = g_type_class_ref(e_menu_hook_get_type()); - type = g_type_register_static(e_menu_hook_get_type(), "EABMenuHook", &info, 0); - } - - return type; -} diff --git a/addressbook/gui/widgets/eab-menu.h b/addressbook/gui/widgets/eab-menu.h deleted file mode 100644 index 6f2b74c755..0000000000 --- a/addressbook/gui/widgets/eab-menu.h +++ /dev/null @@ -1,104 +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 __EAB_MENU_H__ -#define __EAB_MENU_H__ - -#include <glib-object.h> -#include <libebook/e-book.h> - -#include "e-util/e-menu.h" - -G_BEGIN_DECLS - -typedef struct _EABMenu EABMenu; -typedef struct _EABMenuClass EABMenuClass; - -/* Current target description */ -enum _eab_menu_target_t { - EAB_MENU_TARGET_SELECT -}; - -/** - * enum _eab_menu_target_select_t - EABMenuTargetSelect qualifiers. - * - * @EAB_MENU_SELECT_ONE: Only one item is selected. - * @EAB_MENU_SELECT_MANY: More than one item selected. - * @EAB_MENU_SELECT_ANY: One or more items selected. - * @EAB_MENU_SELECT_EDITABLE: Editable addressbook. - * @EAB_MENU_SELECT_EMAIL: Has an email address. - **/ -enum _eab_menu_target_select_t { - EAB_MENU_SELECT_ONE = 1<<0, - EAB_MENU_SELECT_MANY = 1<<1, - EAB_MENU_SELECT_ANY = 1<<2, - EAB_MENU_SELECT_EDITABLE = 1<<3, - EAB_MENU_SELECT_EMAIL = 1<<4 -}; - -typedef struct _EABMenuTargetSelect EABMenuTargetSelect; - -struct _EABMenuTargetSelect { - EMenuTarget target; - - struct _EBook *book; - GPtrArray *cards; -}; - -typedef struct _EMenuItem EABMenuItem; - -/* The object */ -struct _EABMenu { - EMenu menu; - - struct _EABMenuPrivate *priv; -}; - -struct _EABMenuClass { - EMenuClass menu_class; -}; - -GType eab_menu_get_type(void); - -EABMenu *eab_menu_new(const gchar *menuid); - -EABMenuTargetSelect *eab_menu_target_new_select(EABMenu *eabp, struct _EBook *book, gint readonly, GPtrArray *cards); - -/* ********************************************************************** */ - -typedef struct _EABMenuHook EABMenuHook; -typedef struct _EABMenuHookClass EABMenuHookClass; - -struct _EABMenuHook { - EMenuHook hook; -}; - -struct _EABMenuHookClass { - EMenuHookClass hook_class; -}; - -GType eab_menu_hook_get_type(void); - -G_END_DECLS - -#endif /* __EAB_MENU_H__ */ diff --git a/addressbook/gui/widgets/eab-popup-control.c b/addressbook/gui/widgets/eab-popup-control.c deleted file mode 100644 index 28aa819e73..0000000000 --- a/addressbook/gui/widgets/eab-popup-control.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * This file is too big and this widget is too complicated. Forgive me. - * - * 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: - * Jon Trowbridge <trow@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#include <config.h> -#include <string.h> -#include "addressbook.h" -#include "eab-popup-control.h" -#include <bonobo/bonobo-control.h> -#include <bonobo/bonobo-property-bag.h> -#include <bonobo/bonobo-generic-factory.h> -#include <addressbook/util/eab-book-util.h> -#include <addressbook/gui/contact-editor/e-contact-editor.h> -#include <addressbook/gui/contact-editor/e-contact-quick-add.h> -#include <addressbook/gui/widgets/eab-contact-display.h> -#include <addressbook/gui/widgets/eab-gui-util.h> - -static void eab_popup_control_set_name (EABPopupControl *pop, const gchar *name); -static void eab_popup_control_set_email (EABPopupControl *pop, const gchar *email); -static void eab_popup_control_set_vcard (EABPopupControl *pop, const gchar *vcard); - -static GtkObjectClass *parent_class; - -static void eab_popup_control_dispose (GObject *); -static void eab_popup_control_query (EABPopupControl *); - -static void -eab_popup_control_class_init (EABPopupControlClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->dispose = eab_popup_control_dispose; -} - -static void -eab_popup_control_init (EABPopupControl *pop) -{ - pop->transitory = TRUE; -} - -static void -eab_popup_control_cleanup (EABPopupControl *pop) -{ - if (pop->contact) { - g_object_unref (pop->contact); - pop->contact = NULL; - } - - if (pop->scheduled_refresh) { - g_source_remove (pop->scheduled_refresh); - pop->scheduled_refresh = 0; - } - - if (pop->query_tag) { -#ifdef notyet - e_book_simple_query_cancel (pop->book, pop->query_tag); -#endif - pop->query_tag = 0; - } - - if (pop->book) { - g_object_unref (pop->book); - pop->book = NULL; - } - - g_free (pop->name); - pop->name = NULL; - - g_free (pop->email); - pop->email = NULL; - - g_free (pop->vcard); - pop->vcard = NULL; -} - -static void -eab_popup_control_dispose (GObject *obj) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (obj); - - eab_popup_control_cleanup (pop); - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (obj); -} - -GType -eab_popup_control_get_type (void) -{ - static GType pop_type = 0; - - if (!pop_type) { - static const GTypeInfo pop_info = { - sizeof (EABPopupControlClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_popup_control_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABPopupControl), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_popup_control_init, - }; - - pop_type = g_type_register_static (gtk_event_box_get_type (), "EABPopupControl", &pop_info, 0); - } - - return pop_type; -} - -static void -eab_popup_control_refresh_names (EABPopupControl *pop) -{ - if (pop->name_widget) { - if (pop->name && *pop->name) { - gtk_label_set_text (GTK_LABEL (pop->name_widget), pop->name); - gtk_widget_show (pop->name_widget); - } else { - gtk_widget_hide (pop->name_widget); - } - } - - if (pop->email_widget) { - if (pop->email && *pop->email) { - gtk_label_set_text (GTK_LABEL (pop->email_widget), pop->email); - gtk_widget_show (pop->email_widget); - } else { - gtk_widget_hide (pop->email_widget); - } - } - - eab_popup_control_query (pop); -} - -static gint -refresh_timeout_cb (gpointer ptr) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (ptr); - eab_popup_control_refresh_names (pop); - pop->scheduled_refresh = 0; - return 0; -} - -static void -eab_popup_control_schedule_refresh (EABPopupControl *pop) -{ - if (pop->scheduled_refresh == 0) - pop->scheduled_refresh = g_timeout_add (20, refresh_timeout_cb, pop); -} - -/* If we are handed something of the form "Foo <bar@bar.com>", - do the right thing. */ -static gboolean -eab_popup_control_set_free_form (EABPopupControl *pop, const gchar *txt) -{ - gchar *lt, *gt = NULL; - - g_return_val_if_fail (pop && EAB_IS_POPUP_CONTROL (pop), FALSE); - - if (txt == NULL) - return FALSE; - - lt = strchr (txt, '<'); - if (lt) - gt = strchr (txt, '>'); - - if (lt && gt && lt+1 < gt) { - gchar *name = g_strndup (txt, lt-txt); - gchar *email = g_strndup (lt+1, gt-lt-1); - eab_popup_control_set_name (pop, name); - eab_popup_control_set_email (pop, email); - g_free(name); - g_free(email); - - return TRUE; - } - - return FALSE; -} - -static void -eab_popup_control_set_name (EABPopupControl *pop, const gchar *name) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - /* We only allow the name to be set once. */ - if (pop->name) - return; - - if (!eab_popup_control_set_free_form (pop, name)) { - pop->name = g_strdup (name); - if (pop->name) - g_strstrip (pop->name); - } - - eab_popup_control_schedule_refresh (pop); -} - -static void -eab_popup_control_set_email (EABPopupControl *pop, const gchar *email) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - /* We only allow the e-mail to be set once. */ - if (pop->email) - return; - - if (!eab_popup_control_set_free_form (pop, email)) { - pop->email = g_strdup (email); - if (pop->email) - g_strstrip (pop->email); - } - - eab_popup_control_schedule_refresh (pop); -} - -static void -eab_popup_control_set_vcard (EABPopupControl *pop, const gchar *vcard) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - /* We only allow the vcard to be set once. */ - if (pop->vcard) - return; - - g_free (pop->name); - g_free (pop->email); - - pop->name = NULL; - pop->email = NULL; - - pop->vcard = g_strdup (vcard); - - eab_popup_control_schedule_refresh (pop); -} - -void -eab_popup_control_construct (EABPopupControl *pop) -{ - GtkWidget *vbox, *name_holder; - GdkColor color = { 0x0, 0xffff, 0xffff, 0xffff }; - - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - pop->main_vbox = gtk_vbox_new (FALSE, 0); - - /* Build Generic View */ - - name_holder = gtk_event_box_new (); - vbox = gtk_vbox_new (FALSE, 2); - pop->name_widget = gtk_label_new (""); - pop->email_widget = gtk_label_new (""); - - gtk_box_pack_start (GTK_BOX (vbox), pop->name_widget, TRUE, TRUE, 2); - gtk_box_pack_start (GTK_BOX (vbox), pop->email_widget, TRUE, TRUE, 2); - gtk_container_add (GTK_CONTAINER (name_holder), GTK_WIDGET (vbox)); - - if (gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (name_holder)), &color, FALSE, TRUE)) { - GtkStyle *style = gtk_style_copy (gtk_widget_get_style (GTK_WIDGET (name_holder))); - style->bg[0] = color; - gtk_widget_set_style (GTK_WIDGET (name_holder), style); - g_object_unref (style); - } - - pop->generic_view = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (pop->generic_view), name_holder); - gtk_box_pack_start (GTK_BOX (pop->main_vbox), pop->generic_view, TRUE, TRUE, 0); - gtk_widget_show_all (pop->generic_view); - - pop->query_msg = gtk_label_new (_("Querying Address Book...")); - gtk_box_pack_start (GTK_BOX (pop->main_vbox), pop->query_msg, TRUE, TRUE, 0); - gtk_widget_show (pop->query_msg); - - /* Build ContactDisplay */ - pop->contact_display = eab_contact_display_new (); - gtk_box_pack_start (GTK_BOX (pop->main_vbox), pop->contact_display, TRUE, TRUE, 0); - - /* Final assembly */ - - gtk_container_add (GTK_CONTAINER (pop), pop->main_vbox); - gtk_widget_show (pop->main_vbox); - - gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); - gtk_container_set_border_width (GTK_CONTAINER (pop), 2); -} - -static GtkWidget * -eab_popup_new (void) -{ - EABPopupControl *pop = g_object_new (EAB_TYPE_POPUP_CONTROL, NULL); - eab_popup_control_construct (pop); - return GTK_WIDGET (pop); -} - -static void -emit_event (EABPopupControl *pop, const gchar *event) -{ - if (pop->es) { - BonoboArg *arg; - - arg = bonobo_arg_new (BONOBO_ARG_BOOLEAN); - BONOBO_ARG_SET_BOOLEAN (arg, TRUE); - bonobo_event_source_notify_listeners_full (pop->es, - "GNOME/Evolution/Addressbook/AddressPopup", - "Event", - event, - arg, NULL); - bonobo_arg_release (arg); - } -} - -static void -eab_popup_control_no_matches (EABPopupControl *pop) -{ - if (pop->vcard && *pop->vcard) - e_contact_quick_add_vcard (pop->vcard, NULL, NULL); - else if (pop->email && *pop->email) { - if (pop->name && *pop->name) - e_contact_quick_add (pop->name, pop->email, NULL, NULL); - else - e_contact_quick_add_free_form (pop->email, NULL, NULL); - - } - eab_popup_control_cleanup (pop); - emit_event (pop, "Destroy"); -} - -static void -eab_popup_control_query (EABPopupControl *pop) -{ - g_return_if_fail (pop && EAB_IS_POPUP_CONTROL (pop)); - - g_object_ref (pop); - - eab_popup_control_no_matches (pop); - - g_object_unref (pop); - -} - -/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ - -enum { - PROPERTY_NAME, - PROPERTY_EMAIL, - PROPERTY_TRANSITORY, - PROPERTY_VCARD -}; - -static void -set_prop (BonoboPropertyBag *bag, const BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (user_data); - - switch (arg_id) { - - case PROPERTY_NAME: - eab_popup_control_set_name (pop, BONOBO_ARG_GET_STRING (arg)); - break; - - case PROPERTY_EMAIL: - eab_popup_control_set_email (pop, BONOBO_ARG_GET_STRING (arg)); - break; - - case PROPERTY_VCARD: - eab_popup_control_set_vcard (pop, BONOBO_ARG_GET_STRING (arg)); - break; - - default: - g_return_if_reached (); - } -} - -static void -get_prop (BonoboPropertyBag *bag, BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data) -{ - EABPopupControl *pop = EAB_POPUP_CONTROL (user_data); - - switch (arg_id) { - - case PROPERTY_NAME: - BONOBO_ARG_SET_STRING (arg, pop->name); - break; - - case PROPERTY_EMAIL: - BONOBO_ARG_SET_STRING (arg, pop->email); - break; - - case PROPERTY_TRANSITORY: - BONOBO_ARG_SET_BOOLEAN (arg, pop->transitory); - break; - - case PROPERTY_VCARD: - BONOBO_ARG_SET_STRING (arg, pop->vcard); - break; - - default: - g_return_if_reached (); - } -} - -BonoboControl * -eab_popup_control_new (void) -{ - BonoboControl *control; - BonoboPropertyBag *bag; - EABPopupControl *addy; - GtkWidget *w; - - w = eab_popup_new (); - addy = EAB_POPUP_CONTROL (w); - - control = bonobo_control_new (w); - gtk_widget_show (w); - - bag = bonobo_property_bag_new (get_prop, set_prop, w); - bonobo_property_bag_add (bag, "name", PROPERTY_NAME, - BONOBO_ARG_STRING, NULL, NULL, - BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE); - - bonobo_property_bag_add (bag, "email", PROPERTY_EMAIL, - BONOBO_ARG_STRING, NULL, NULL, - BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE); - - bonobo_property_bag_add (bag, "transitory", PROPERTY_TRANSITORY, - BONOBO_ARG_BOOLEAN, NULL, NULL, - BONOBO_PROPERTY_READABLE); - - bonobo_property_bag_add (bag, "vcard", PROPERTY_VCARD, - BONOBO_ARG_STRING, NULL, NULL, - BONOBO_PROPERTY_WRITEABLE | BONOBO_PROPERTY_READABLE); - - bonobo_control_set_properties (control, bonobo_object_corba_objref (BONOBO_OBJECT (bag)), NULL); - bonobo_object_unref (BONOBO_OBJECT (bag)); - - addy->es = bonobo_event_source_new (); - bonobo_object_add_interface (BONOBO_OBJECT (control), - BONOBO_OBJECT (addy->es)); - - return control; -} diff --git a/addressbook/gui/widgets/eab-popup-control.h b/addressbook/gui/widgets/eab-popup-control.h deleted file mode 100644 index 9eeedc8e00..0000000000 --- a/addressbook/gui/widgets/eab-popup-control.h +++ /dev/null @@ -1,84 +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: - * Jon Trowbridge <trow@ximian.com> - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef __EAB_POPUP_CONTROL_H__ -#define __EAB_POPUP_CONTROL_H__ - -#include <bonobo/bonobo-event-source.h> -#include <libebook/e-book.h> -#include <libebook/e-contact.h> - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define EAB_TYPE_POPUP_CONTROL (eab_popup_control_get_type ()) -#define EAB_POPUP_CONTROL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EAB_TYPE_POPUP_CONTROL, EABPopupControl)) -#define EAB_POPUP_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EAB_TYPE_POPUP_CONTROL, EABPopupControlClass)) -#define EAB_IS_POPUP_CONTROL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EAB_TYPE_POPUP_CONTROL)) -#define EAB_IS_POPUP_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EAB_TYPE_POPUP_CONTROL)) - -typedef struct _EABPopupControl EABPopupControl; -typedef struct _EABPopupControlClass EABPopupControlClass; - -struct _EABPopupControl { - GtkEventBox parent; - - gchar *name; - gchar *email; - gchar *vcard; - - GtkWidget *name_widget; - GtkWidget *email_widget; - GtkWidget *query_msg; - - GtkWidget *main_vbox; - GtkWidget *generic_view; - GtkWidget *contact_display; - - gboolean transitory; - - guint scheduled_refresh; - EBook *book; - guint query_tag; - gboolean multiple_matches; - EContact *contact; - - BonoboEventSource *es; -}; - -struct _EABPopupControlClass { - GtkEventBoxClass parent_class; -}; - -GType eab_popup_control_get_type (void); - -void eab_popup_control_construct (EABPopupControl *); - -BonoboControl *eab_popup_control_new (void); - -G_END_DECLS - -#endif /* __EAB_POPUP_CONTROL_H__ */ - diff --git a/addressbook/gui/widgets/eab-popup.c b/addressbook/gui/widgets/eab-popup.c deleted file mode 100644 index 30ab08f837..0000000000 --- a/addressbook/gui/widgets/eab-popup.c +++ /dev/null @@ -1,364 +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 "eab-popup.h" -#include <libedataserverui/e-source-selector.h> -#include <libebook/e-contact.h> - -static GObjectClass *eabp_parent; - -static void -eabp_init(GObject *o) -{ - /*EABPopup *eabp = (EABPopup *)o; */ -} - -static void -eabp_finalise(GObject *o) -{ - ((GObjectClass *)eabp_parent)->finalize(o); -} - -static void -eabp_target_free(EPopup *ep, EPopupTarget *t) -{ - switch (t->type) { - case EAB_POPUP_TARGET_SELECT: { - EABPopupTargetSelect *s = (EABPopupTargetSelect *)t; - gint i; - - for (i=0;i<s->cards->len;i++) - g_object_unref(s->cards->pdata[i]); - g_ptr_array_free(s->cards, TRUE); - g_object_unref(s->book); - - break; } - case EAB_POPUP_TARGET_URI: { - EABPopupTargetURI *s = (EABPopupTargetURI *)t; - - g_free(s->uri); - break; } - case EAB_POPUP_TARGET_SOURCE: { - EABPopupTargetSource *s = (EABPopupTargetSource *)t; - - g_object_unref(s->selector); - break; } - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - - case EAB_POPUP_TARGET_SELECT_NAMES: { - EABPopupTargetSelectNames *s = (EABPopupTargetSelectNames *)t; - - g_object_unref(s->model); - break; } - -#endif - - } - - ((EPopupClass *)eabp_parent)->target_free(ep, t); -} - -static void -eabp_class_init(GObjectClass *klass) -{ - klass->finalize = eabp_finalise; - ((EPopupClass *)klass)->target_free = eabp_target_free; -} - -GType -eab_popup_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - static const GTypeInfo info = { - sizeof(EABPopupClass), - NULL, NULL, - (GClassInitFunc)eabp_class_init, - NULL, NULL, - sizeof(EABPopup), 0, - (GInstanceInitFunc)eabp_init - }; - eabp_parent = g_type_class_ref(e_popup_get_type()); - type = g_type_register_static(e_popup_get_type(), "EABPopup", &info, 0); - } - - return type; -} - -EABPopup *eab_popup_new(const gchar *menuid) -{ - EABPopup *eabp = g_object_new(eab_popup_get_type(), NULL); - - e_popup_construct(&eabp->popup, menuid); - - return eabp; -} - -/** - * eab_popup_target_new_select: - * @eabp: Address book popup. - * @book: Book the cards belong to. - * @readonly: Book is read-only mode. FIXME: Why can't we just get this off the book? - * @cards: Cards selected. This will be freed on completion. - * - * Create a new selection popup target. - * - * Return value: - **/ - -EABPopupTargetURI * -eab_popup_target_new_uri(EABPopup *emp, const gchar *uri) -{ - EABPopupTargetURI *t = e_popup_target_new(&emp->popup, EAB_POPUP_TARGET_URI, sizeof(*t)); - guint32 mask = ~0; - - t->uri = g_strdup(uri); - - if (g_ascii_strncasecmp(uri, "http:", 5) == 0 - || g_ascii_strncasecmp(uri, "https:", 6) == 0) - mask &= ~EAB_POPUP_URI_HTTP; - if (g_ascii_strncasecmp(uri, "internal-mailto:", 16) == 0) - mask &= ~EAB_POPUP_URI_MAILTO; - else - mask &= ~EAB_POPUP_URI_NOT_MAILTO; - - t->target.mask = mask; - - return t; -} - -EABPopupTargetSelect * -eab_popup_target_new_select(EABPopup *eabp, struct _EBook *book, gint readonly, GPtrArray *cards) -{ - EABPopupTargetSelect *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SELECT, sizeof(*t)); - guint32 mask = ~0; - gint has_email = FALSE, i; - - /* FIXME: duplicated in eab-menu.c */ - - t->book = book; - g_object_ref(book); - t->cards = cards; - - for (i=0;i<cards->len && !has_email;i++) { - EContact *contact = cards->pdata[i]; - GList *email; - - email = e_contact_get(E_CONTACT(contact), E_CONTACT_EMAIL); - if (email) { - has_email = TRUE; - - g_list_foreach(email, (GFunc)g_free, NULL); - g_list_free(email); - } - } - - if (cards->len == 1) { - if (e_contact_get (E_CONTACT(cards->pdata[0]), E_CONTACT_IS_LIST)) - mask &= ~EAB_POPUP_LIST; - else - mask &= ~EAB_POPUP_CONTACT; - } - - if (has_email) - mask &= ~EAB_POPUP_SELECT_EMAIL; - - if (!readonly) - mask &= ~EAB_POPUP_SELECT_EDITABLE; - - if (cards->len == 1) - mask &= ~EAB_POPUP_SELECT_ONE; - - if (cards->len > 1) - mask &= ~EAB_POPUP_SELECT_MANY; - - if (cards->len >= 1) - mask &= ~EAB_POPUP_SELECT_ANY; - - t->target.mask = mask; - - return t; -} - -EABPopupTargetSource * -eab_popup_target_new_source(EABPopup *eabp, ESourceSelector *selector) -{ - EABPopupTargetSource *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SOURCE, sizeof(*t)); - guint32 mask = ~0; - const gchar *source_uri; - ESource *source; - - /* TODO: this is duplicated for calendar and tasks too */ - - t->selector = selector; - g_object_ref(selector); - - /* TODO: perhaps we need to copy this so it doesn't change during the lifecycle */ - source = e_source_selector_peek_primary_selection(selector); - if (source) - mask &= ~EAB_POPUP_SOURCE_PRIMARY; - - /* FIXME Gross hack, should have a property or something */ - source_uri = e_source_peek_relative_uri(source); - if (source_uri && !strcmp("system", source_uri)) - mask &= ~EAB_POPUP_SOURCE_SYSTEM; - else - mask &= ~EAB_POPUP_SOURCE_USER; - - t->target.mask = mask; - - return t; -} - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - -EABPopupTargetSelectNames * -eab_popup_target_new_select_names(EABPopup *eabp, struct _ESelectNamesModel *model, gint row) -{ - EABPopupTargetSelectNames *t = e_popup_target_new(&eabp->popup, EAB_POPUP_TARGET_SELECT_NAMES, sizeof(*t)); - - /* TODO: this is sort of not very useful, maybe the popup which uses it doesn't - need to be pluggable */ - - t->model = model; - g_object_ref(model); - t->row = row; - - return t; -} - -#endif - -/* ********************************************************************** */ -/* Popup menu plugin handler */ - -/* -<e-plugin - class="org.gnome.mail.plugin.popup:1.0" - id="org.gnome.mail.plugin.popup.iteab:1.0" - type="shlib" - location="/opt/gnome2/lib/camel/1.0/libcamelimap.so" - name="imap" - description="IMAP4 and IMAP4v1 mail store"> - <hook class="org.gnome.mail.popupMenu:1.0" - handler="HandlePopup"> - <menu id="any" target="select"> - <iteab - type="iteab|toggle|radio|image|submenu|bar" - active - path="foo/bar" - label="label" - icon="foo" - mask="select_one" - activate="eabp_view_eabacs"/> - </menu> - </extension> - -*/ - -static gpointer eabph_parent_class; -#define eabph ((EABPopupHook *)eph) - -static const EPopupHookTargetMask eabph_select_masks[] = { - { "one", EAB_POPUP_SELECT_ONE }, - { "many", EAB_POPUP_SELECT_MANY }, - { "any", EAB_POPUP_SELECT_ANY }, - { "editable", EAB_POPUP_SELECT_EDITABLE }, - { "email", EAB_POPUP_SELECT_EMAIL }, - { NULL } -}; - -static const EPopupHookTargetMask eabph_source_masks[] = { - { "primary", EAB_POPUP_SOURCE_PRIMARY }, - { "system", EAB_POPUP_SOURCE_SYSTEM }, - { NULL } -}; - -static const EPopupHookTargetMask eabph_uri_masks[] = { - { "http", EAB_POPUP_URI_HTTP }, - { "internal-mailto", EAB_POPUP_URI_MAILTO }, - { "notmailto", EAB_POPUP_URI_NOT_MAILTO }, - { NULL } -}; - -static const EPopupHookTargetMask eabph_select_names_masks[] = { - { NULL } -}; - -static const EPopupHookTargetMap eabph_targets[] = { - { "select", EAB_POPUP_TARGET_SELECT, eabph_select_masks }, - { "uri", EAB_POPUP_TARGET_URI, eabph_uri_masks }, - { "source", EAB_POPUP_TARGET_SOURCE, eabph_source_masks }, - { "select-names", EAB_POPUP_TARGET_SELECT_NAMES, eabph_select_names_masks }, - { NULL } -}; - -static void -eabph_finalise(GObject *o) -{ - /*EPluginHook *eph = (EPluginHook *)o;*/ - - ((GObjectClass *)eabph_parent_class)->finalize(o); -} - -static void -eabph_class_init(EPluginHookClass *klass) -{ - gint i; - - ((GObjectClass *)klass)->finalize = eabph_finalise; - ((EPluginHookClass *)klass)->id = "org.gnome.evolution.addressbook.popup:1.0"; - - for (i=0;eabph_targets[i].type;i++) - e_popup_hook_class_add_target_map((EPopupHookClass *)klass, &eabph_targets[i]); - - ((EPopupHookClass *)klass)->popup_class = g_type_class_ref(eab_popup_get_type()); -} - -GType -eab_popup_hook_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(EABPopupHookClass), NULL, NULL, (GClassInitFunc) eabph_class_init, NULL, NULL, - sizeof(EABPopupHook), 0, (GInstanceInitFunc) NULL, - }; - - eabph_parent_class = g_type_class_ref(e_popup_hook_get_type()); - type = g_type_register_static(e_popup_hook_get_type(), "EABPopupHook", &info, 0); - } - - return type; -} diff --git a/addressbook/gui/widgets/eab-popup.h b/addressbook/gui/widgets/eab-popup.h deleted file mode 100644 index 31d0310829..0000000000 --- a/addressbook/gui/widgets/eab-popup.h +++ /dev/null @@ -1,195 +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 __EAB_POPUP_H__ -#define __EAB_POPUP_H__ - -#include <glib-object.h> - -#include "e-util/e-popup.h" - -G_BEGIN_DECLS - -#define ADAPTED_TO_E_NAME_SELECTOR 1 - -typedef struct _EABPopup EABPopup; -typedef struct _EABPopupClass EABPopupClass; - -/** - * enum _eab_popup_target_t - A list of mail popup target types. - * - * @EAB_POPUP_TARGET_SELECT: A selection of cards - * @EAB_POPUP_TARGET_SOURCE: A source selection. - * - * Defines the value of the targetid for all EABPopup target types. - **/ -enum _eab_popup_target_t { - EAB_POPUP_TARGET_SELECT, - EAB_POPUP_TARGET_URI, - EAB_POPUP_TARGET_SOURCE, - EAB_POPUP_TARGET_SELECT_NAMES -}; - -/** - * enum _eab_popup_target_select_t - EABPopupTargetSelect qualifiers. - * - * @EAB_POPUP_SELECT_ONE: Only one item is selected. - * @EAB_POPUP_SELECT_MANY: Two or more items are selected. - * @EAB_POPUP_SELECT_ANY: One or more items are selected. - * @EAB_POPUP_SELECT_EDITABLE: Read/writable source. - * @EAB_POPUP_SELECT_EMAIL: Has an email address. - **/ -enum _eab_popup_target_select_t { - EAB_POPUP_SELECT_ONE = 1<<0, - EAB_POPUP_SELECT_MANY = 1<<1, - EAB_POPUP_SELECT_ANY = 1<<2, - EAB_POPUP_SELECT_EDITABLE = 1<<3, - EAB_POPUP_SELECT_EMAIL = 1<<4, - EAB_POPUP_LIST = 1<<5, - EAB_POPUP_CONTACT = 1<<6 -}; - -enum _eab_popup_target_uri_t { - EAB_POPUP_URI_HTTP = 1<<0, - EAB_POPUP_URI_MAILTO = 1<<1, - EAB_POPUP_URI_NOT_MAILTO = 1<<2 -}; -/** - * enum _eab_popup_target_source_t - EABPopupTargetSource qualifiers. - * - * @EAB_POPUP_SOURCE_PRIMARY: Has a primary selection. - * @EAB_POPUP_SOURCE_SYSTEM: Is a 'system' folder. - * - **/ -enum _eab_popup_target_source_t { - EAB_POPUP_SOURCE_PRIMARY = 1<<0, - EAB_POPUP_SOURCE_SYSTEM = 1<<1, /* system folder */ - EAB_POPUP_SOURCE_USER = 1<<2 /* user folder (!system) */ -}; - -typedef struct _EABPopupTargetSelect EABPopupTargetSelect; -typedef struct _EABPopupTargetSource EABPopupTargetSource; -typedef struct _EABPopupTargetSelectNames EABPopupTargetSelectNames; -typedef struct _EABPopupTargetURI EABPopupTargetURI; -/** - * struct _EABPopupTargetSelect - A list of address cards. - * - * @target: Superclass. - * @book: Book the cards belong to. - * @cards: All selected cards. - * - * Used to represent a selection of cards as context for a popup - * menu. - **/ -struct _EABPopupTargetSelect { - EPopupTarget target; - - struct _EBook *book; - GPtrArray *cards; -}; - -struct _EABPopupTargetURI { - EPopupTarget target; - gchar *uri; -}; - -/** - * struct _EABPopupTargetSource - A source target. - * - * @target: Superclass. - * @selector: Selector holding the source selection. - * - * This target is used to represent a source selection. - **/ -struct _EABPopupTargetSource { - EPopupTarget target; - - struct _ESourceSelector *selector; -}; - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - -/** - * struct _EABPopupTargetSelectNames - A select names target. - * - * @target: Superclass. - * @model: Select names model. - * @row: Row of item selected. - * - * This target is used to represent an item selected in an - * ESelectNames model. - **/ -struct _EABPopupTargetSelectNames { - EPopupTarget target; - - struct _ESelectNamesModel *model; - gint row; -}; - -#endif - -typedef struct _EPopupItem EABPopupItem; - -/* The object */ -struct _EABPopup { - EPopup popup; - - struct _EABPopupPrivate *priv; -}; - -struct _EABPopupClass { - EPopupClass popup_class; -}; - -GType eab_popup_get_type(void); - -EABPopup *eab_popup_new(const gchar *menuid); - -EABPopupTargetSelect *eab_popup_target_new_select(EABPopup *eabp, struct _EBook *book, gint readonly, GPtrArray *cards); -EABPopupTargetURI *eab_popup_target_new_uri(EABPopup *emp, const gchar *uri); -EABPopupTargetSource *eab_popup_target_new_source(EABPopup *eabp, struct _ESourceSelector *selector); - -#ifdef ADAPTED_TO_E_NAME_SELECTOR - -EABPopupTargetSelectNames *eab_popup_target_new_select_names(EABPopup *eabp, struct _ESelectNamesModel *model, gint row); - -#endif - -/* ********************************************************************** */ - -typedef struct _EABPopupHook EABPopupHook; -typedef struct _EABPopupHookClass EABPopupHookClass; - -struct _EABPopupHook { - EPopupHook hook; -}; - -struct _EABPopupHookClass { - EPopupHookClass hook_class; -}; - -GType eab_popup_hook_get_type(void); - -G_END_DECLS - -#endif /* __EAB_POPUP_H__ */ diff --git a/addressbook/gui/widgets/gal-view-minicard.c b/addressbook/gui/widgets/gal-view-minicard.c index 8ff48bede6..c7b2a4a38f 100644 --- a/addressbook/gui/widgets/gal-view-minicard.c +++ b/addressbook/gui/widgets/gal-view-minicard.c @@ -26,115 +26,172 @@ #include <config.h> #include <libxml/parser.h> - -#include <libedataserver/e-xml-utils.h> - #include <e-util/e-xml-utils.h> +#include <libedataserver/e-xml-utils.h> #include "gal-view-minicard.h" -#define PARENT_TYPE gal_view_get_type () -#define d(x) +static gpointer parent_class; + +static void +view_minicard_column_width_changed (EAddressbookView *address_view, + gdouble width) +{ + GalView *view; + GalViewInstance *view_instance; + GalViewMinicard *view_minicard; + GtkScrolledWindow *scrolled_window; + GtkAdjustment *adjustment; + GtkWidget *widget; + gdouble value, lower, upper; + gdouble page_increment, page_size; + + view_instance = e_addressbook_view_get_view_instance (address_view); + view = gal_view_instance_get_current_view (view_instance); + view_minicard = GAL_VIEW_MINICARD (view); + + if (view_minicard->column_width != width) { + view_minicard->column_width = width; + gal_view_changed (view); + } + + widget = e_addressbook_view_get_view_widget (address_view); + scrolled_window = GTK_SCROLLED_WINDOW (widget); + adjustment = gtk_scrolled_window_get_hadjustment (scrolled_window); + + value = gtk_adjustment_get_value (adjustment); + lower = gtk_adjustment_get_lower (adjustment); + upper = gtk_adjustment_get_upper (adjustment); + page_increment = gtk_adjustment_get_page_increment (adjustment); + page_size = gtk_adjustment_get_page_size (adjustment); + + adjustment = GTK_ADJUSTMENT (gtk_adjustment_new ( + value, lower, upper, page_size, page_increment, page_size)); + gtk_scrolled_window_set_hadjustment (scrolled_window, adjustment); +} + +static void +view_minicard_finalize (GObject *object) +{ + GalViewMinicard *view = GAL_VIEW_MINICARD (object); + + if (view->title != NULL) { + gal_view_minicard_detach (view); + g_free (view->title); + view->title = NULL; + } -static GalViewClass *gal_view_minicard_parent_class; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} static void -gal_view_minicard_load (GalView *view, - const gchar *filename) +view_minicard_load (GalView *view, + const gchar *filename) { + GalViewMinicard *view_minicard; xmlDoc *doc; + xmlNode *root; + + view_minicard = GAL_VIEW_MINICARD (view); doc = e_xml_parse_file (filename); - if (doc) { - xmlNode *root = xmlDocGetRootElement(doc); - GAL_VIEW_MINICARD (view)->column_width = e_xml_get_double_prop_by_name_with_default (root, (const guchar *)"column_width", 150); - xmlFreeDoc(doc); - } + g_return_if_fail (doc != NULL); + + root = xmlDocGetRootElement (doc); + view_minicard->column_width = + e_xml_get_double_prop_by_name_with_default ( + root, (guchar *) "column_width", 150); + xmlFreeDoc (doc); } static void -gal_view_minicard_save (GalView *view, - const gchar *filename) +view_minicard_save (GalView *view, + const gchar *filename) { + GalViewMinicard *view_minicard; xmlDoc *doc; xmlNode *root; - doc = xmlNewDoc((const guchar *)"1.0"); - root = xmlNewNode (NULL, (const guchar *)"EMinicardViewState"); - e_xml_set_double_prop_by_name (root, (const guchar *)"column_width", GAL_VIEW_MINICARD (view)->column_width); - xmlDocSetRootElement(doc, root); + view_minicard = GAL_VIEW_MINICARD (view); + + doc = xmlNewDoc ((guchar *) "1.0"); + root = xmlNewNode (NULL, (guchar *) "EMinicardViewState"); + e_xml_set_double_prop_by_name ( + root, (guchar *) "column_width", + view_minicard->column_width); + xmlDocSetRootElement (doc, root); e_xml_save_file (filename, doc); - xmlFreeDoc(doc); + xmlFreeDoc (doc); } static const gchar * -gal_view_minicard_get_title (GalView *view) +view_minicard_get_title (GalView *view) { - return GAL_VIEW_MINICARD(view)->title; + GalViewMinicard *view_minicard; + + view_minicard = GAL_VIEW_MINICARD (view); + + return view_minicard->title; } static void -gal_view_minicard_set_title (GalView *view, - const gchar *title) +view_minicard_set_title (GalView *view, + const gchar *title) { - g_free(GAL_VIEW_MINICARD(view)->title); - GAL_VIEW_MINICARD(view)->title = g_strdup(title); + GalViewMinicard *view_minicard; + + view_minicard = GAL_VIEW_MINICARD (view); + + g_free (view_minicard->title); + view_minicard->title = g_strdup (title); } static const gchar * -gal_view_minicard_get_type_code (GalView *view) +view_minicard_get_type_code (GalView *view) { return "minicard"; } static GalView * -gal_view_minicard_clone (GalView *view) +view_minicard_clone (GalView *view) { - GalViewMinicard *gvm, *new; + GalViewMinicard *view_minicard; + GalViewMinicard *clone; - gvm = GAL_VIEW_MINICARD(view); + view_minicard = GAL_VIEW_MINICARD(view); - new = g_object_new (GAL_TYPE_VIEW_MINICARD, NULL); - new->title = g_strdup (gvm->title); - new->column_width = gvm->column_width; + clone = g_object_new (GAL_TYPE_VIEW_MINICARD, NULL); + clone->column_width = view_minicard->column_width; + clone->title = g_strdup (view_minicard->title); - return GAL_VIEW(new); + return GAL_VIEW (clone); } static void -gal_view_minicard_dispose (GObject *object) +gal_view_minicard_class_init (GalViewMinicardClass *class) { - GalViewMinicard *view = GAL_VIEW_MINICARD(object); + GObjectClass *object_class; + GalViewClass *gal_view_class; - if (view->title != NULL) { - gal_view_minicard_detach (view); - g_free(view->title); - view->title = NULL; - } + parent_class = g_type_class_peek_parent (class); - if (G_OBJECT_CLASS (gal_view_minicard_parent_class)->dispose) - (* G_OBJECT_CLASS (gal_view_minicard_parent_class)->dispose) (object); -} + object_class = G_OBJECT_CLASS (class); + object_class->dispose = view_minicard_finalize; + + gal_view_class = GAL_VIEW_CLASS (class); + gal_view_class->edit = NULL; + gal_view_class->load = view_minicard_load; + gal_view_class->save = view_minicard_save; + gal_view_class->get_title = view_minicard_get_title; + gal_view_class->set_title = view_minicard_set_title; + gal_view_class->get_type_code = view_minicard_get_type_code; + gal_view_class->clone = view_minicard_clone; -static void -gal_view_minicard_class_init (GObjectClass *object_class) -{ - GalViewClass *gal_view_class = GAL_VIEW_CLASS(object_class); - gal_view_minicard_parent_class = g_type_class_ref (PARENT_TYPE); - - gal_view_class->edit = NULL; - gal_view_class->load = gal_view_minicard_load; - gal_view_class->save = gal_view_minicard_save; - gal_view_class->get_title = gal_view_minicard_get_title; - gal_view_class->set_title = gal_view_minicard_set_title; - gal_view_class->get_type_code = gal_view_minicard_get_type_code; - gal_view_class->clone = gal_view_minicard_clone; - - object_class->dispose = gal_view_minicard_dispose; } static void -gal_view_minicard_init (GalViewMinicard *gvm) +gal_view_minicard_init (GalViewMinicard *gvm) { gvm->title = NULL; gvm->column_width = 150.0; @@ -143,6 +200,32 @@ gal_view_minicard_init (GalViewMinicard *gvm) gvm->emvw_column_width_changed_id = 0; } +GType +gal_view_minicard_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (GalViewMinicardClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_view_minicard_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalViewMinicard), + 0, /* n_preallocs */ + (GInstanceInitFunc) gal_view_minicard_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GAL_VIEW_TYPE, "GalViewMinicard", &type_info, 0); + } + + return type; +} + /** * gal_view_minicard_new * @title: The name of the new view. @@ -155,7 +238,8 @@ gal_view_minicard_init (GalViewMinicard *gvm) GalView * gal_view_minicard_new (const gchar *title) { - return gal_view_minicard_construct (g_object_new (GAL_TYPE_VIEW_MINICARD, NULL), title); + return gal_view_minicard_construct ( + g_object_new (GAL_TYPE_VIEW_MINICARD, NULL), title); } /** @@ -163,7 +247,7 @@ gal_view_minicard_new (const gchar *title) * @view: The view to construct. * @title: The name of the new view. * - * constructs the GalViewMinicard. To be used by subclasses and + * Constructs the GalViewMinicard. To be used by subclasses and * language bindings. * * Returns: The GalViewMinicard. @@ -172,85 +256,49 @@ GalView * gal_view_minicard_construct (GalViewMinicard *view, const gchar *title) { - view->title = g_strdup(title); - return GAL_VIEW(view); -} - -GType -gal_view_minicard_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (GalViewMinicardClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gal_view_minicard_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GalViewMinicard), - 0, /* n_preallocs */ - (GInstanceInitFunc) gal_view_minicard_init, - }; + view->title = g_strdup (title); - type = g_type_register_static (PARENT_TYPE, "GalViewMinicard", &info, 0); - } - - return type; + return GAL_VIEW (view); } -static void -column_width_changed (EMinicardViewWidget *w, double width, EABView *address_view) +void +gal_view_minicard_attach (GalViewMinicard *view, + EAddressbookView *address_view) { - GalViewMinicard *view = GAL_VIEW_MINICARD (gal_view_instance_get_current_view (address_view->view_instance)); - GtkScrolledWindow *scrolled_window; - GtkAdjustment *adj; - GtkAdjustment *adj_new; + GObject *object; - d(g_print("%s: Old width = %f, New width = %f\n", G_STRFUNC, view->column_width, width)); - if (view->column_width != width) { - view->column_width = width; - gal_view_changed(GAL_VIEW(view)); - } + g_return_if_fail (GAL_IS_VIEW_MINICARD (view)); + g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (address_view)); - scrolled_window = GTK_SCROLLED_WINDOW (address_view->widget); - adj = gtk_scrolled_window_get_hadjustment (scrolled_window); - adj_new = GTK_ADJUSTMENT (gtk_adjustment_new (adj->value, adj->lower, adj->upper, - adj->page_size, adj->page_increment, - adj->page_size)); - gtk_scrolled_window_set_hadjustment (scrolled_window, adj_new); -} + object = e_addressbook_view_get_view_object (address_view); + g_return_if_fail (E_IS_MINICARD_VIEW_WIDGET (object)); -void -gal_view_minicard_attach (GalViewMinicard *view, EABView *address_view) -{ - EMinicardViewWidget *emvw = E_MINICARD_VIEW_WIDGET (address_view->object); gal_view_minicard_detach (view); + view->emvw = g_object_ref (object); - view->emvw = emvw; - - g_object_ref (view->emvw); - - g_object_set (view->emvw, - "column_width", view->column_width, - NULL); + g_object_set (view->emvw, "column-width", view->column_width, NULL); view->emvw_column_width_changed_id = - g_signal_connect(view->emvw, "column_width_changed", - G_CALLBACK (column_width_changed), address_view); + g_signal_connect_swapped ( + view->emvw, "column-width-changed", + G_CALLBACK (view_minicard_column_width_changed), + address_view); } void gal_view_minicard_detach (GalViewMinicard *view) { + g_return_if_fail (GAL_IS_VIEW_MINICARD (view)); + if (view->emvw == NULL) return; - if (view->emvw_column_width_changed_id) { - g_signal_handler_disconnect (view->emvw, - view->emvw_column_width_changed_id); + + if (view->emvw_column_width_changed_id > 0) { + g_signal_handler_disconnect ( + view->emvw, view->emvw_column_width_changed_id); view->emvw_column_width_changed_id = 0; } + g_object_unref (view->emvw); view->emvw = NULL; } diff --git a/addressbook/gui/widgets/gal-view-minicard.h b/addressbook/gui/widgets/gal-view-minicard.h index f5681fcca5..c506fb1a2b 100644 --- a/addressbook/gui/widgets/gal-view-minicard.h +++ b/addressbook/gui/widgets/gal-view-minicard.h @@ -22,40 +22,59 @@ * */ -#ifndef _GAL_VIEW_MINICARD_H_ -#define _GAL_VIEW_MINICARD_H_ +#ifndef GAL_VIEW_MINICARD_H +#define GAL_VIEW_MINICARD_H #include <widgets/menus/gal-view.h> #include <e-minicard-view-widget.h> #include "e-addressbook-view.h" -#define GAL_TYPE_VIEW_MINICARD (gal_view_minicard_get_type ()) -#define GAL_VIEW_MINICARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GAL_TYPE_VIEW_MINICARD, GalViewMinicard)) -#define GAL_VIEW_MINICARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) -#define GAL_IS_VIEW_MINICARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GAL_TYPE_VIEW_MINICARD)) -#define GAL_IS_VIEW_MINICARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GAL_TYPE_VIEW_MINICARD)) +/* Standard GObject macros */ +#define GAL_TYPE_VIEW_MINICARD \ + (gal_view_minicard_get_type ()) +#define GAL_VIEW_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), GAL_TYPE_VIEW_MINICARD, GalViewMinicard)) +#define GAL_VIEW_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) +#define GAL_IS_VIEW_MINICARD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), GAL_TYPE_VIEW_MINICARD)) +#define GAL_IS_VIEW_MINICARD_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), GAL_TYPE_VIEW_MINICARD)) +#define GAL_VIEW_MINICARD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), GAL_TYPE_VIEW_MINICARD, GalViewMinicardClass)) -typedef struct { - GalView base; +G_BEGIN_DECLS + +typedef struct _GalViewMinicard GalViewMinicard; +typedef struct _GalViewMinicardClass GalViewMinicardClass; + +struct _GalViewMinicard { + GalView parent; gchar *title; double column_width; EMinicardViewWidget *emvw; guint emvw_column_width_changed_id; -} GalViewMinicard; +}; -typedef struct { +struct _GalViewMinicardClass { GalViewClass parent_class; -} GalViewMinicardClass; - -/* Standard functions */ -GType gal_view_minicard_get_type (void); -GalView *gal_view_minicard_new (const gchar *title); -GalView *gal_view_minicard_construct (GalViewMinicard *view, - const gchar *title); -void gal_view_minicard_attach (GalViewMinicard *view, - EABView *address_view); -void gal_view_minicard_detach (GalViewMinicard *view); - -#endif /* _GAL_VIEW_MINICARD_H_ */ +}; + +GType gal_view_minicard_get_type (void); +GalView * gal_view_minicard_new (const gchar *title); +GalView * gal_view_minicard_construct (GalViewMinicard *view, + const gchar *title); +void gal_view_minicard_attach (GalViewMinicard *view, + EAddressbookView *address_view); +void gal_view_minicard_detach (GalViewMinicard *view); + +G_END_DECLS + +#endif /* GAL_VIEW_MINICARD_H */ diff --git a/addressbook/util/Makefile.am b/addressbook/util/Makefile.am index 42f160ea5f..50d5d430e2 100644 --- a/addressbook/util/Makefile.am +++ b/addressbook/util/Makefile.am @@ -12,6 +12,8 @@ AM_CPPFLAGS = \ privsolib_LTLIBRARIES = libeabutil.la libeabutil_la_SOURCES = \ + addressbook.c \ + addressbook.h \ eab-book-util.c \ eab-book-util.h diff --git a/addressbook/gui/component/addressbook.c b/addressbook/util/addressbook.c index 7caa545059..7caa545059 100644 --- a/addressbook/gui/component/addressbook.c +++ b/addressbook/util/addressbook.c diff --git a/addressbook/gui/component/addressbook.h b/addressbook/util/addressbook.h index 3997c9c176..7bc92ee344 100644 --- a/addressbook/gui/component/addressbook.h +++ b/addressbook/util/addressbook.h @@ -22,9 +22,6 @@ #ifndef __ADDRESSBOOK_H__ #define __ADDRESSBOOK_H__ -#include <bonobo/bonobo-control.h> -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-moniker-util.h> #include <libebook/e-book.h> guint addressbook_load (EBook *book, EBookCallback cb, gpointer closure); diff --git a/addressbook/util/eab-book-util.h b/addressbook/util/eab-book-util.h index 8c43b64bcd..9f8a79eae1 100644 --- a/addressbook/util/eab-book-util.h +++ b/addressbook/util/eab-book-util.h @@ -24,8 +24,6 @@ #ifndef __EAB_UTIL_H__ #define __EAB_UTIL_H__ -#include <bonobo/bonobo-object.h> -#include <bonobo/bonobo-moniker-util.h> #include <libebook/e-book.h> G_BEGIN_DECLS |