DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --with-private-docs --with-krb5=/usr --enable-introspection
-SUBDIRS = camel data private libedataserver libebackend addressbook calendar libedataserverui modules services tests docs art po
+SUBDIRS = camel data private libedataserver libebackend addressbook calendar modules services tests docs art po
if HAVE_INTROSPECTION
if HAVE_VALA
dnl ******************************
PKG_CHECK_MODULES(SQLITE3, [sqlite3 >= sqlite_minimum_version])
+if test "x$enable_maintainer_mode" = "xyes" ; then
+ EVO_SET_COMPILE_FLAGS(FACTORY_GTK, "gtk+-3.0")
+ AC_SUBST(FACTORY_GTK_CFLAGS)
+ AC_SUBST(FACTORY_GTK_LIBS)
+fi
+
dnl ******************************
dnl libedataserver flags
dnl ******************************
AC_SUBST(E_DATA_SERVER_LIBS)
dnl ******************************
-dnl libedataserverui
+dnl libebackend flags
dnl ******************************
-E_DATA_SERVER_UI_DEPS="gtk+-3.0 libxml-2.0 libsoup-2.4"
-
-EVO_SET_COMPILE_FLAGS(E_DATA_SERVER_UI, $E_DATA_SERVER_UI_DEPS, , )
-AC_SUBST(E_DATA_SERVER_UI_CFLAGS)
-AC_SUBST(E_DATA_SERVER_UI_LIBS)
-
-if test "x$enable_maintainer_mode" = "xyes" ; then
- FACTORY_GTK_CFLAGS=$E_DATA_SERVER_UI_CFLAGS
- FACTORY_GTK_LIBS=$E_DATA_SERVER_UI_LIBS
- AC_SUBST(FACTORY_GTK_CFLAGS)
- AC_SUBST(FACTORY_GTK_LIBS)
-fi
-
E_BACKEND_DEPS="gio-2.0 gmodule-2.0 libsecret-1 libsoup-2.4 libxml-2.0"
-dnl ******************************
-dnl libebackend flags
-dnl ******************************
EVO_SET_COMPILE_FLAGS(E_BACKEND, $E_BACKEND_DEPS)
AC_SUBST(E_BACKEND_CFLAGS)
AC_SUBST(E_BACKEND_LIBS)
libedataserver/Makefile
libedataserver/eds-version.h
libedataserver/libedataserver.pc
-libedataserverui/Makefile
-libedataserverui/libedataserverui.pc
modules/Makefile
modules/cache-reaper/Makefile
modules/gnome-online-accounts/Makefile
tests/libecal/client/Makefile
tests/libedata-cal/Makefile
tests/libedataserver/Makefile
-tests/libedataserverui/Makefile
tests/tools/Makefile
docs/Makefile
docs/reference/Makefile
docs/reference/calendar/libedata-cal/Makefile
docs/reference/camel/Makefile
docs/reference/libedataserver/Makefile
-docs/reference/libedataserverui/Makefile
docs/reference/libebackend/Makefile
docs/reference/private/Makefile
po/Makefile.in
calendar \
camel \
libedataserver \
- libedataserverui \
libebackend \
$(PRIVATE_DIR) \
$(NULL)
+++ /dev/null
-# The name of the module.
-DOC_MODULE = libedataserverui
-
-# The top-level SGML file.
-DOC_MAIN_SGML_FILE = libedataserverui-docs.sgml
-
-# Extra options to supply to gtkdoc-scan.
-SCAN_OPTIONS = --deprecated-guards="EDS_DISABLE_DEPRECATED"
-
-# The directory containing the source code. Relative to $(srcdir).
-DOC_SOURCE_DIR = $(top_srcdir)/libedataserverui
-
-# Used for dependencies. The docs will be rebuilt if any of these change.
-HFILE_GLOB = $(top_srcdir)/libedataserverui/*.h
-CFILE_GLOB = $(top_srcdir)/libedataserverui/*.c
-
-IGNORE_HFILES = \
- e-data-server-ui-marshal.h
-
-GTKDOC_CFLAGS = \
- -I$(top_srcdir)/libedataserverui \
- -I$(top_srcdir)/libedataserver \
- -I$(top_srcdir)/addressbook \
- -I$(top_srcdir) \
- -I$(top_builddir) \
- -I$(top_builddir)/addressbook \
- $(E_DATA_SERVER_UI_CFLAGS) \
- $(CAMEL_CFLAGS)
-
-GTKDOC_LIBS = \
- $(top_builddir)/libedataserverui/libedataserverui-3.0.la \
- $(top_builddir)/calendar/libecal/libecal-1.2.la \
- $(top_builddir)/addressbook/libebook/libebook-1.2.la \
- $(top_builddir)/libebackend/libebackend-1.2.la \
- $(top_builddir)/libedataserver/libedataserver-1.2.la \
- $(E_DATA_SERVER_UI_LIBS) \
- $(CAMEL_LIBS)
-
-# This includes the standard gtk-doc make rules, copied by gtkdocize.
-include $(top_srcdir)/gtk-doc.make
-
-#TESTS = $(GTKDOC_CHECK)
-
--include $(top_srcdir)/git.mk
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
-]>
-<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
- <bookinfo>
- <title>Evolution-Data-Server Manual: Graphical Utilities (libedataserverui)</title>
- </bookinfo>
-
- <chapter>
- <title>Evolution-Data-Server Manual: Graphical Utilities (libedataserverui)</title>
- <xi:include href="xml/e-book-auth-util.xml"/>
- <xi:include href="xml/e-categories-dialog.xml"/>
- <xi:include href="xml/e-categories-editor.xml"/>
- <xi:include href="xml/e-categories-selector.xml"/>
- <xi:include href="xml/e-category-editor.xml"/>
- <xi:include href="xml/e-category-completion.xml"/>
- <xi:include href="xml/e-cell-renderer-color.xml"/>
- <xi:include href="xml/e-client-utils.xml"/>
- <xi:include href="xml/e-contact-store.xml"/>
- <xi:include href="xml/e-destination-store.xml"/>
- <xi:include href="xml/e-name-selector.xml"/>
- <xi:include href="xml/e-name-selector-dialog.xml"/>
- <xi:include href="xml/e-name-selector-entry.xml"/>
- <xi:include href="xml/e-name-selector-list.xml"/>
- <xi:include href="xml/e-name-selector-model.xml"/>
- <xi:include href="xml/e-passwords.xml"/>
- <xi:include href="xml/e-source-combo-box.xml"/>
- <xi:include href="xml/e-source-selector.xml"/>
- <xi:include href="xml/e-source-selector-dialog.xml"/>
- <xi:include href="xml/e-tree-model-generator.xml"/>
- </chapter>
-
- <index id="api-index-full">
- <title>Index</title>
- <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-deprecated" role="deprecated">
- <title>Index of deprecated symbols</title>
- <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-3.8" role="3.8">
- <title>Index of new symbols in 3.8</title>
- <xi:include href="xml/api-index-3.8.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-3.6" role="3.6">
- <title>Index of new symbols in 3.6</title>
- <xi:include href="xml/api-index-3.6.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-3.4" role="3.4">
- <title>Index of new symbols in 3.4</title>
- <xi:include href="xml/api-index-3.4.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-3.2" role="3.2">
- <title>Index of new symbols in 3.2</title>
- <xi:include href="xml/api-index-3.2.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-3.0" role="3.0">
- <title>Index of new symbols in 3.0</title>
- <xi:include href="xml/api-index-3.0.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-2.32" role="2.32">
- <title>Index of new symbols in 2.32</title>
- <xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-2.30" role="2.30">
- <title>Index of new symbols in 2.30</title>
- <xi:include href="xml/api-index-2.30.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-2.28" role="2.28">
- <title>Index of new symbols in 2.28</title>
- <xi:include href="xml/api-index-2.28.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-2.26" role="2.26">
- <title>Index of new symbols in 2.26</title>
- <xi:include href="xml/api-index-2.26.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-2.24" role="2.24">
- <title>Index of new symbols in 2.24</title>
- <xi:include href="xml/api-index-2.24.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-2.22" role="2.22">
- <title>Index of new symbols in 2.22</title>
- <xi:include href="xml/api-index-2.22.xml"><xi:fallback /></xi:include>
- </index>
- <index id="api-index-1.12" role="1.12">
- <title>Index of new symbols in 1.12</title>
- <xi:include href="xml/api-index-1.12.xml"><xi:fallback /></xi:include>
- </index>
-
- <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
-
-</book>
+++ /dev/null
-<SECTION>
-<FILE>e-book-auth-util</FILE>
-e_load_book_source_async
-e_load_book_source_finish
-</SECTION>
-
-<SECTION>
-<FILE>e-categories-dialog</FILE>
-<TITLE>ECategoriesDialog</TITLE>
-ECategoriesDialog
-e_categories_dialog_new
-e_categories_dialog_get_categories
-e_categories_dialog_set_categories
-<SUBSECTION Standard>
-E_CATEGORIES_DIALOG
-E_IS_CATEGORIES_DIALOG
-E_TYPE_CATEGORIES_DIALOG
-E_CATEGORIES_DIALOG_CLASS
-E_IS_CATEGORIES_DIALOG_CLASS
-E_CATEGORIES_DIALOG_GET_CLASS
-ECategoriesDialogClass
-<SUBSECTION Private>
-ECategoriesDialogPrivate
-e_categories_dialog_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-categories-editor</FILE>
-<TITLE>ECategoriesEditor</TITLE>
-ECategoriesEditor
-e_categories_editor_new
-e_categories_editor_get_categories
-e_categories_editor_set_categories
-e_categories_editor_get_entry_visible
-e_categories_editor_set_entry_visible
-<SUBSECTION Standard>
-E_CATEGORIES_EDITOR
-E_IS_CATEGORIES_EDITOR
-E_TYPE_CATEGORIES_EDITOR
-E_CATEGORIES_EDITOR_CLASS
-E_IS_CATEGORIES_EDITOR_CLASS
-E_CATEGORIES_EDITOR_GET_CLASS
-ECategoriesEditorClass
-<SUBSECTION Private>
-ECategoriesEditorPrivate
-e_categories_editor_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-categories-selector</FILE>
-<TITLE>ECategoriesSelector</TITLE>
-ECategoriesSelector
-e_categories_selector_new
-e_categories_selector_get_checked
-e_categories_selector_set_checked
-e_categories_selector_get_items_checkable
-e_categories_selector_set_items_checkable
-e_categories_selector_delete_selection
-e_categories_selector_get_selected
-<SUBSECTION Standard>
-E_CATEGORIES_SELECTOR
-E_IS_CATEGORIES_SELECTOR
-E_TYPE_CATEGORIES_SELECTOR
-E_CATEGORIES_SELECTOR_CLASS
-E_IS_CATEGORIES_SELECTOR_CLASS
-E_CATEGORIES_SELECTOR_GET_CLASS
-ECategoriesSelectorClass
-<SUBSECTION Private>
-ECategoriesSelectorPrivate
-e_categories_selector_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-category-completion</FILE>
-<TITLE>ECategoryCompletion</TITLE>
-ECategoryCompletion
-e_category_completion_new
-<SUBSECTION Standard>
-E_TYPE_CATEGORY_COMPLETION
-E_CATEGORY_COMPLETION
-E_CATEGORY_COMPLETION_CLASS
-E_IS_CATEGORY_COMPLETION
-E_IS_CATEGORY_COMPLETION_CLASS
-E_CATEGORY_COMPLETION_GET_CLASS
-ECategoryCompletionClass
-<SUBSECTION Private>
-ECategoryCompletionPrivate
-e_category_completion_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-category-editor</FILE>
-<TITLE>ECategoryEditor</TITLE>
-ECategoryEditor
-e_category_editor_new
-e_category_editor_create_category
-e_category_editor_edit_category
-<SUBSECTION Standard>
-E_CATEGORY_EDITOR
-E_IS_CATEGORY_EDITOR
-E_TYPE_CATEGORY_EDITOR
-E_CATEGORY_EDITOR_CLASS
-E_IS_CATEGORY_EDITOR_CLASS
-E_CATEGORY_EDITOR_GET_CLASS
-ECategoryEditorClass
-<SUBSECTION Private>
-ECategoryEditorPrivate
-e_category_editor_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-cell-renderer-color</FILE>
-<TITLE>ECellRendererColor</TITLE>
-ECellRendererColor
-e_cell_renderer_color_new
-<SUBSECTION Standard>
-E_TYPE_CELL_RENDERER_COLOR
-E_CELL_RENDERER_COLOR
-E_CELL_RENDERER_COLOR_CLASS
-E_IS_CELL_RENDERER_COLOR
-E_IS_CELL_RENDERER_COLOR_CLASS
-E_CELL_RENDERER_COLOR_GET_CLASS
-ECellRendererColorClass
-<SUBSECTION Private>
-ECellRendererColorPrivate
-e_cell_renderer_color_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-client-utils</FILE>
-<TITLE>EClient Utilities</TITLE>
-EClientSourceType
-e_client_utils_new
-e_client_utils_open_new
-e_client_utils_open_new_finish
-</SECTION>
-
-<SECTION>
-<FILE>e-contact-store</FILE>
-<TITLE>EContactStore</TITLE>
-EContactStore
-e_contact_store_new
-e_contact_store_get_client
-e_contact_store_get_contact
-e_contact_store_find_contact
-e_contact_store_get_clients
-e_contact_store_add_client
-e_contact_store_remove_client
-e_contact_store_set_query
-e_contact_store_peek_query
-<SUBSECTION Standard>
-E_CONTACT_STORE
-E_IS_CONTACT_STORE
-E_TYPE_CONTACT_STORE
-E_CONTACT_STORE_CLASS
-E_IS_CONTACT_STORE_CLASS
-E_CONTACT_STORE_GET_CLASS
-EContactStoreClass
-<SUBSECTION Private>
-EContactStorePrivate
-e_contact_store_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-destination-store</FILE>
-<TITLE>EDestinationStore</TITLE>
-EDestinationStore
-EDestinationStoreColumnType
-e_destination_store_new
-e_destination_store_get_destination
-e_destination_store_list_destinations
-e_destination_store_insert_destination
-e_destination_store_append_destination
-e_destination_store_remove_destination
-e_destination_store_remove_destination_nth
-e_destination_store_get_destination_count
-e_destination_store_get_path
-e_destination_store_get_stamp
-<SUBSECTION Standard>
-E_DESTINATION_STORE
-E_IS_DESTINATION_STORE
-E_TYPE_DESTINATION_STORE
-E_DESTINATION_STORE_CLASS
-E_IS_DESTINATION_STORE_CLASS
-E_DESTINATION_STORE_GET_CLASS
-EDestinationStoreClass
-<SUBSECTION Private>
-EDestinationStorePrivate
-e_destination_store_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-name-selector</FILE>
-<TITLE>ENameSelector</TITLE>
-ENameSelector
-e_name_selector_new
-e_name_selector_get_registry
-e_name_selector_peek_model
-e_name_selector_peek_dialog
-e_name_selector_peek_section_entry
-e_name_selector_peek_section_list
-e_name_selector_show_dialog
-e_name_selector_load_books
-e_name_selector_cancel_loading
-<SUBSECTION Standard>
-E_NAME_SELECTOR
-E_IS_NAME_SELECTOR
-E_TYPE_NAME_SELECTOR
-E_NAME_SELECTOR_CLASS
-E_IS_NAME_SELECTOR_CLASS
-E_NAME_SELECTOR_GET_CLASS
-ENameSelectorClass
-<SUBSECTION Private>
-ENameSelectorPrivate
-e_name_selector_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-name-selector-dialog</FILE>
-<TITLE>ENameSelectorDialog</TITLE>
-ENameSelectorDialog
-e_name_selector_dialog_new
-e_name_selector_dialog_get_registry
-e_name_selector_dialog_peek_model
-e_name_selector_dialog_set_model
-e_name_selector_dialog_set_destination_index
-e_name_selector_dialog_set_scrolling_policy
-e_name_selector_dialog_get_section_visible
-e_name_selector_dialog_set_section_visible
-<SUBSECTION Standard>
-E_NAME_SELECTOR_DIALOG
-E_IS_NAME_SELECTOR_DIALOG
-E_TYPE_NAME_SELECTOR_DIALOG
-E_NAME_SELECTOR_DIALOG_CLASS
-E_IS_NAME_SELECTOR_DIALOG_CLASS
-E_NAME_SELECTOR_DIALOG_GET_CLASS
-ENameSelectorDialogClass
-<SUBSECTION Private>
-ENameSelectorDialogPrivate
-e_name_selector_dialog_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-name-selector-entry</FILE>
-<TITLE>ENameSelectorEntry</TITLE>
-ENameSelectorEntry
-e_name_selector_entry_new
-e_name_selector_entry_get_registry
-e_name_selector_entry_set_registry
-e_name_selector_entry_get_minimum_query_length
-e_name_selector_entry_set_minimum_query_length
-e_name_selector_entry_get_show_address
-e_name_selector_entry_set_show_address
-e_name_selector_entry_peek_contact_store
-e_name_selector_entry_set_contact_store
-e_name_selector_entry_peek_destination_store
-e_name_selector_entry_set_destination_store
-e_name_selector_entry_get_popup_destination
-e_name_selector_entry_set_contact_editor_func
-e_name_selector_entry_set_contact_list_editor_func
-ens_util_populate_user_query_fields
-<SUBSECTION Standard>
-E_NAME_SELECTOR_ENTRY
-E_IS_NAME_SELECTOR_ENTRY
-E_TYPE_NAME_SELECTOR_ENTRY
-E_NAME_SELECTOR_ENTRY_CLASS
-E_IS_NAME_SELECTOR_ENTRY_CLASS
-E_NAME_SELECTOR_ENTRY_GET_CLASS
-ENameSelectorEntryClass
-<SUBSECTION Private>
-ENameSelectorEntryPrivate
-e_name_selector_entry_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-name-selector-list</FILE>
-<TITLE>ENameSelectorList</TITLE>
-ENameSelectorList
-e_name_selector_list_new
-e_name_selector_list_expand_clicked
-<SUBSECTION Standard>
-E_NAME_SELECTOR_LIST
-E_IS_NAME_SELECTOR_LIST
-E_TYPE_NAME_SELECTOR_LIST
-E_NAME_SELECTOR_LIST_CLASS
-E_IS_NAME_SELECTOR_LIST_CLASS
-E_NAME_SELECTOR_LIST_GET_CLASS
-ENameSelectorListClass
-<SUBSECTION Private>
-ENameSelectorListPrivate
-e_name_selector_list_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-name-selector-model</FILE>
-<TITLE>ENameSelectorModel</TITLE>
-ENameSelectorModel
-e_name_selector_model_new
-e_name_selector_model_peek_contact_store
-e_name_selector_model_peek_contact_filter
-e_name_selector_model_list_sections
-e_name_selector_model_peek_section
-e_name_selector_model_add_section
-e_name_selector_model_remove_section
-e_name_selector_model_get_contact_emails_without_used
-e_name_selector_model_free_emails_list
-<SUBSECTION Standard>
-E_NAME_SELECTOR_MODEL
-E_IS_NAME_SELECTOR_MODEL
-E_TYPE_NAME_SELECTOR_MODEL
-E_NAME_SELECTOR_MODEL_CLASS
-E_IS_NAME_SELECTOR_MODEL_CLASS
-E_NAME_SELECTOR_MODEL_GET_CLASS
-ENameSelectorModelClass
-<SUBSECTION Private>
-ENameSelectorModelPrivate
-e_name_selector_model_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-passwords</FILE>
-e_passwords_init
-e_passwords_shutdown
-e_passwords_cancel
-e_passwords_set_online
-e_passwords_remember_password
-e_passwords_add_password
-e_passwords_get_password
-e_passwords_forget_password
-e_passwords_forget_passwords
-e_passwords_clear_passwords
-EPasswordsRememberType
-e_passwords_ask_password
-</SECTION>
-
-<SECTION>
-<FILE>e-source-combo-box</FILE>
-<TITLE>ESourceComboBox</TITLE>
-ESourceComboBox
-e_source_combo_box_new
-e_source_combo_box_get_registry
-e_source_combo_box_set_registry
-e_source_combo_box_get_extension_name
-e_source_combo_box_set_extension_name
-e_source_combo_box_get_show_colors
-e_source_combo_box_set_show_colors
-e_source_combo_box_ref_active
-e_source_combo_box_set_active
-<SUBSECTION Standard>
-E_SOURCE_COMBO_BOX
-E_IS_SOURCE_COMBO_BOX
-E_TYPE_SOURCE_COMBO_BOX
-E_SOURCE_COMBO_BOX_CLASS
-E_IS_SOURCE_COMBO_BOX_CLASS
-E_SOURCE_COMBO_BOX_GET_CLASS
-ESourceComboBoxClass
-<SUBSECTION Private>
-ESourceComboBoxPrivate
-e_source_combo_box_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-tree-model-generator</FILE>
-<TITLE>ETreeModelGenerator</TITLE>
-ETreeModelGeneratorGenerateFunc
-ETreeModelGeneratorModifyFunc
-ETreeModelGenerator
-e_tree_model_generator_new
-e_tree_model_generator_get_model
-e_tree_model_generator_set_generate_func
-e_tree_model_generator_set_modify_func
-e_tree_model_generator_convert_child_path_to_path
-e_tree_model_generator_convert_child_iter_to_iter
-e_tree_model_generator_convert_path_to_child_path
-e_tree_model_generator_convert_iter_to_child_iter
-<SUBSECTION Standard>
-E_TREE_MODEL_GENERATOR
-E_IS_TREE_MODEL_GENERATOR
-E_TYPE_TREE_MODEL_GENERATOR
-E_TREE_MODEL_GENERATOR_CLASS
-E_IS_TREE_MODEL_GENERATOR_CLASS
-E_TREE_MODEL_GENERATOR_GET_CLASS
-ETreeModelGeneratorClass
-<SUBSECTION Private>
-ETreeModelGeneratorPrivate
-e_tree_model_generator_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-source-selector</FILE>
-<TITLE>ESourceSelector</TITLE>
-ESourceSelector
-e_source_selector_new
-e_source_selector_get_registry
-e_source_selector_get_extension_name
-e_source_selector_get_show_colors
-e_source_selector_set_show_colors
-e_source_selector_get_show_toggles
-e_source_selector_set_show_toggles
-e_source_selector_select_source
-e_source_selector_unselect_source
-e_source_selector_select_exclusive
-e_source_selector_source_is_selected
-e_source_selector_get_selection
-e_source_selector_free_selection
-e_source_selector_set_select_new
-e_source_selector_edit_primary_selection
-e_source_selector_ref_primary_selection
-e_source_selector_set_primary_selection
-e_source_selector_ref_source_by_path
-e_source_selector_queue_write
-<SUBSECTION Standard>
-E_SOURCE_SELECTOR
-E_IS_SOURCE_SELECTOR
-E_TYPE_SOURCE_SELECTOR
-E_SOURCE_SELECTOR_CLASS
-E_IS_SOURCE_SELECTOR_CLASS
-E_SOURCE_SELECTOR_GET_CLASS
-ESourceSelectorClass
-<SUBSECTION Private>
-ESourceSelectorPrivate
-e_source_selector_get_type
-</SECTION>
-
-<SECTION>
-<FILE>e-source-selector-dialog</FILE>
-<TITLE>ESourceSelectorDialog</TITLE>
-ESourceSelectorDialog
-e_source_selector_dialog_new
-e_source_selector_dialog_get_registry
-e_source_selector_dialog_get_extension_name
-e_source_selector_dialog_get_selector
-e_source_selector_dialog_peek_primary_selection
-<SUBSECTION Standard>
-E_SOURCE_SELECTOR_DIALOG
-E_IS_SOURCE_SELECTOR_DIALOG
-E_TYPE_SOURCE_SELECTOR_DIALOG
-E_SOURCE_SELECTOR_DIALOG_CLASS
-E_IS_SOURCE_SELECTOR_DIALOG_CLASS
-E_SOURCE_SELECTOR_DIALOG_GET_CLASS
-ESourceSelectorDialogClass
-<SUBSECTION Private>
-ESourceSelectorDialogPrivate
-e_source_selector_dialog_get_type
-</SECTION>
-
+++ /dev/null
-#include <libedataserverui/libedataserverui.h>
-
-e_categories_dialog_get_type
-e_categories_editor_get_type
-e_categories_selector_get_type
-e_category_editor_get_type
-e_contact_store_get_type
-e_destination_store_get_type
-e_name_selector_get_type
-e_name_selector_dialog_get_type
-e_name_selector_entry_get_type
-e_name_selector_list_get_type
-e_name_selector_model_get_type
-e_source_combo_box_get_type
-e_source_selector_get_type
-e_source_selector_dialog_get_type
-e_tree_model_generator_get_type
+++ /dev/null
-# The marshallers
-MARSHAL_GENERATED = e-data-server-ui-marshal.c e-data-server-ui-marshal.h
-@EVO_MARSHAL_RULE@
-
-lib_LTLIBRARIES = libedataserverui-3.0.la
-
-libedataserverui_3_0_la_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -I$(top_srcdir) \
- -I$(top_srcdir)/addressbook \
- -I$(top_builddir)/addressbook \
- -I$(top_srcdir)/calendar \
- -I$(top_builddir)/calendar \
- -DLIBEDATASERVERUI_COMPILATION \
- -DG_LOG_DOMAIN=\"e-data-server-ui\" \
- -DE_DATA_SERVER_UI_UIDIR=\""$(uidir)"\" \
- $(E_DATA_SERVER_UI_CFLAGS) \
- $(LIBSECRET_CFLAGS) \
- $(CAMEL_CFLAGS) \
- $(SOUP_CFLAGS) \
- $(CODE_COVERAGE_CFLAGS) \
- $(NULL)
-
-libedataserveruiinclude_HEADERS = \
- libedataserverui.h \
- e-categories-dialog.h \
- e-categories-editor.h \
- e-categories-selector.h \
- e-category-completion.h \
- e-category-editor.h \
- e-destination-store.h \
- e-book-auth-util.h \
- e-client-utils.h \
- e-contact-store.h \
- e-name-selector.h \
- e-name-selector-dialog.h \
- e-name-selector-entry.h \
- e-name-selector-model.h \
- e-name-selector-list.h \
- e-passwords.h \
- e-source-selector.h \
- e-source-selector-dialog.h \
- e-source-combo-box.h \
- e-tree-model-generator.h \
- e-cell-renderer-color.h
-
-if OS_WIN32
-e_passwords_build = e-passwords-win32.c
-e_passwords_dist = e-passwords.c
-else
-e_passwords_build = e-passwords.c
-e_passwords_dist = e-passwords-win32.c
-endif
-
-libedataserverui_3_0_la_SOURCES = \
- $(MARSHAL_GENERATED) \
- e-categories-dialog.c \
- e-categories-editor.c \
- e-categories-selector.c \
- e-category-completion.c \
- e-category-editor.c \
- e-destination-store.c \
- e-book-auth-util.c \
- e-client-utils.c \
- e-contact-store.c \
- e-name-selector.c \
- e-name-selector-dialog.c \
- e-name-selector-entry.c \
- e-name-selector-model.c \
- e-name-selector-list.c \
- $(e_passwords_build) \
- e-source-selector.c \
- e-source-selector-dialog.c \
- e-source-combo-box.c \
- e-tree-model-generator.c \
- e-cell-renderer-color.c
-
-libedataserverui_3_0_la_LIBADD = \
- $(top_builddir)/addressbook/libebook/libebook-1.2.la \
- $(top_builddir)/calendar/libecal/libecal-1.2.la \
- $(top_builddir)/libedataserver/libedataserver-1.2.la \
- $(top_builddir)/libebackend/libebackend-1.2.la \
- $(top_builddir)/camel/libcamel-1.2.la \
- $(E_DATA_SERVER_UI_LIBS) \
- $(LIBSECRET_LIBS) \
- $(CAMEL_LIBS) \
- $(SOUP_LIBS)
-
-libedataserverui_3_0_la_LDFLAGS = \
- -version-info $(LIBEDATASERVERUI_CURRENT):$(LIBEDATASERVERUI_REVISION):$(LIBEDATASERVERUI_AGE) $(NO_UNDEFINED) \
- $(CODE_COVERAGE_LDFLAGS) \
- $(NULL)
-
-libedataserveruiincludedir = $(privincludedir)/libedataserverui
-
-%-3.0.pc: %.pc
- cp $< $@
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libedataserverui-3.0.pc
-
-BUILT_SOURCES = $(MARSHAL_GENERATED)
-
-EXTRA_DIST = \
- $(e_passwords_dist) \
- e-data-server-ui-marshal.list \
- $(pkgconfig_DATA:-3.0.pc=.pc.in)
-
-CLEANFILES = $(BUILT_SOURCES)
-DISTCLEANFILES = $(pkgconfig_DATA)
-
--include $(top_srcdir)/git.mk
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-book-auth-util.c - Lame helper to load addressbooks with authentication.
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- *
- * Mostly taken from Evolution's addressbook/gui/component/addressbook.c
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserverui/e-passwords.h>
-
-#include "e-book-auth-util.h"
-
-typedef struct {
- EBook *book;
-} LoadContext;
-
-static void
-load_book_source_context_free (LoadContext *context)
-{
- if (context->book != NULL)
- g_object_unref (context->book);
-
- g_slice_free (LoadContext, context);
-}
-
-static void
-load_book_source_thread (GSimpleAsyncResult *simple,
- ESource *source,
- GCancellable *cancellable)
-{
- EBook *book;
- LoadContext *context;
- GError *error = NULL;
-
- context = g_simple_async_result_get_op_res_gpointer (simple);
-
- book = e_book_new (source, &error);
- if (book == NULL) {
- g_simple_async_result_take_error (simple, error);
- return;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, &error)) {
- g_simple_async_result_take_error (simple, error);
- g_object_unref (book);
- return;
- }
-
- if (!e_book_open (book, FALSE, &error)) {
- g_simple_async_result_take_error (simple, error);
- g_object_unref (book);
- return;
- }
-
- context->book = book;
-}
-
-/**
- * e_load_book_source_async:
- * @source: an #ESource
- * @parent: parent window for password dialogs, or %NULL
- * @cancellable: optional #GCancellable object, %NULL to ignore
- * @callback: a #GAsyncReadyCallback to call when the request is satisfied
- * @user_data: the data to pass to @callback
- *
- * Creates a new #EBook specified by @source and opens it, prompting the
- * user for authentication if necessary.
- *
- * When the operation is finished, @callback will be called. You can
- * then call e_load_book_source_finish() to obtain the resulting #EBook.
- *
- * Since: 2.32
- *
- * Deprecated: 3.2: Use e_client_utils_open_new(), e_client_utils_open_new_finish() instead.
- **/
-void
-e_load_book_source_async (ESource *source,
- GtkWindow *parent,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple;
- LoadContext *context;
-
- g_return_if_fail (E_IS_SOURCE (source));
-
- if (parent != NULL) {
- g_return_if_fail (GTK_IS_WINDOW (parent));
- g_object_ref (parent);
- }
-
- if (cancellable != NULL) {
- g_return_if_fail (G_IS_CANCELLABLE (cancellable));
- g_object_ref (cancellable);
- } else {
- /* always provide cancellable, because the code depends on it */
- cancellable = g_cancellable_new ();
- }
-
- context = g_slice_new0 (LoadContext);
-
- simple = g_simple_async_result_new (
- G_OBJECT (source), callback,
- user_data, e_load_book_source_async);
-
- g_simple_async_result_set_check_cancellable (simple, cancellable);
-
- g_simple_async_result_set_op_res_gpointer (
- simple, context, (GDestroyNotify)
- load_book_source_context_free);
-
- g_simple_async_result_run_in_thread (
- simple, (GSimpleAsyncThreadFunc) load_book_source_thread,
- G_PRIORITY_DEFAULT, cancellable);
-
- g_object_unref (simple);
-}
-
-/**
- * e_load_book_source_finish:
- * @source: an #ESource
- * @result: a #GAsyncResult
- * @error: return location for a #GError, or %NULL
- *
- * Finishes an asynchronous #EBook open operation started with
- * e_load_book_source_async(). If an error occurred, or the user
- * declined to authenticate, the function will return %NULL and
- * set @error.
- *
- * Returns: a ready-to-use #EBook, or %NULL or error
- *
- * Since: 2.32
- *
- * Deprecated: 3.2: Use e_client_utils_open_new(), e_client_utils_open_new_finish() instead.
- **/
-EBook *
-e_load_book_source_finish (ESource *source,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
- LoadContext *context;
-
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
- g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
-
- g_return_val_if_fail (
- g_simple_async_result_is_valid (
- result, G_OBJECT (source),
- e_load_book_source_async), NULL);
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
-
- context = g_simple_async_result_get_op_res_gpointer (simple);
- g_return_val_if_fail (context != NULL, NULL);
-
- return g_object_ref (context->book);
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-book-auth-util.h - Lame helper to load addressbooks with authentication.
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef EDS_DISABLE_DEPRECATED
-
-#ifndef E_BOOK_AUTH_UTIL_H
-#define E_BOOK_AUTH_UTIL_H
-
-#include <gtk/gtk.h>
-#include <libebook/libebook.h>
-
-G_BEGIN_DECLS
-
-void e_load_book_source_async (ESource *source,
- GtkWindow *parent,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-EBook * e_load_book_source_finish (ESource *source,
- GAsyncResult *result,
- GError **error);
-G_END_DECLS
-
-#endif /* E_BOOK_AUTH_UTIL_H */
-
-#endif /* EDS_DISABLE_DEPRECATED */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserver/libedataserver.h>
-#include <libedataserver/libedataserver-private.h>
-
-#include "e-categories-dialog.h"
-#include "e-categories-editor.h"
-#include "e-categories-selector.h"
-#include "e-category-completion.h"
-#include "e-category-editor.h"
-
-#define E_CATEGORIES_DIALOG_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CATEGORIES_DIALOG, ECategoriesDialogPrivate))
-
-G_DEFINE_TYPE (ECategoriesDialog, e_categories_dialog, GTK_TYPE_DIALOG)
-
-struct _ECategoriesDialogPrivate {
- GtkWidget *categories_editor;
-};
-
-static void
-entry_changed_cb (GtkEntry *entry,
- ECategoriesDialog *dialog)
-{
- gtk_dialog_set_response_sensitive (
- GTK_DIALOG (dialog), GTK_RESPONSE_OK, TRUE);
-}
-
-static void
-e_categories_dialog_class_init (ECategoriesDialogClass *class)
-{
- g_type_class_add_private (class, sizeof (ECategoriesDialogPrivate));
-}
-
-static void
-e_categories_dialog_init (ECategoriesDialog *dialog)
-{
- GtkWidget *dialog_content;
- GtkWidget *categories_editor;
-
- dialog->priv = E_CATEGORIES_DIALOG_GET_PRIVATE (dialog);
-
- categories_editor = e_categories_editor_new ();
- dialog->priv->categories_editor = categories_editor;
-
- dialog_content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
- gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
- gtk_box_pack_start (
- GTK_BOX (dialog_content), categories_editor, TRUE, TRUE, 0);
- gtk_box_set_spacing (GTK_BOX (dialog_content), 12);
-
- g_signal_connect (
- categories_editor, "entry-changed",
- G_CALLBACK (entry_changed_cb), dialog);
-
- gtk_dialog_add_buttons (
- GTK_DIALOG (dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
- gtk_dialog_set_response_sensitive (
- GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
- gtk_window_set_title (GTK_WINDOW (dialog), _("Categories"));
-
- gtk_widget_show_all (categories_editor);
-}
-
-/**
- * e_categories_dialog_new:
- * @categories: Comma-separated list of categories
- *
- * Creates a new #ECategoriesDialog widget and sets the initial selection
- * to @categories.
- *
- * Returns: a new #ECategoriesDialog
- **/
-GtkWidget *
-e_categories_dialog_new (const gchar *categories)
-{
- ECategoriesDialog *dialog;
-
- dialog = g_object_new (E_TYPE_CATEGORIES_DIALOG, NULL);
-
- if (categories)
- e_categories_dialog_set_categories (dialog, categories);
-
- return GTK_WIDGET (dialog);
-}
-
-/**
- * e_categories_dialog_get_categories:
- * @dialog: An #ECategoriesDialog
- *
- * Gets a comma-separated list of the categories currently selected
- * in the dialog.
- *
- * Returns: a comma-separated list of categories. Free returned
- * pointer with g_free().
- **/
-gchar *
-e_categories_dialog_get_categories (ECategoriesDialog *dialog)
-{
- gchar *categories;
-
- g_return_val_if_fail (E_IS_CATEGORIES_DIALOG (dialog), NULL);
-
- categories = e_categories_editor_get_categories (
- E_CATEGORIES_EDITOR (dialog->priv->categories_editor));
-
- return categories;
-}
-
-/**
- * e_categories_dialog_set_categories:
- * @dialog: An #ECategoriesDialog
- * @categories: Comma-separated list of categories
- *
- * Sets the list of categories selected on the dialog.
- **/
-void
-e_categories_dialog_set_categories (ECategoriesDialog *dialog,
- const gchar *categories)
-{
- g_return_if_fail (E_IS_CATEGORIES_DIALOG (dialog));
-
- e_categories_editor_set_categories (
- E_CATEGORIES_EDITOR (dialog->priv->categories_editor),
- categories);
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CATEGORIES_DIALOG_H
-#define E_CATEGORIES_DIALOG_H
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CATEGORIES_DIALOG \
- (e_categories_dialog_get_type ())
-#define E_CATEGORIES_DIALOG(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CATEGORIES_DIALOG, ECategoriesDialog))
-#define E_CATEGORIES_DIALOG_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CATEGORIES_DIALOG, ECategoriesDialogClass))
-#define E_IS_CATEGORIES_DIALOG(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CATEGORIES_DIALOG))
-#define E_IS_CATEGORIES_DIALOG_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_CATEGORIES_DIALOG))
-#define E_CATEGORIES_DIALOG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CATEGORIES_DIALOG, ECategoriesDialogClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECategoriesDialog ECategoriesDialog;
-typedef struct _ECategoriesDialogClass ECategoriesDialogClass;
-typedef struct _ECategoriesDialogPrivate ECategoriesDialogPrivate;
-
-struct _ECategoriesDialog {
- GtkDialog parent;
- ECategoriesDialogPrivate *priv;
-};
-
-struct _ECategoriesDialogClass {
- GtkDialogClass parent_class;
-};
-
-GType e_categories_dialog_get_type (void);
-GtkWidget * e_categories_dialog_new (const gchar *categories);
-gchar * e_categories_dialog_get_categories
- (ECategoriesDialog *dialog);
-void e_categories_dialog_set_categories
- (ECategoriesDialog *dialog,
- const gchar *categories);
-
-G_END_DECLS
-
-#endif /* E_CATEGORIES_DIALOG_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <config.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserver/libedataserver.h>
-#include <libedataserver/libedataserver-private.h>
-
-#include "e-categories-editor.h"
-#include "e-categories-selector.h"
-#include "e-category-completion.h"
-#include "e-category-editor.h"
-
-#define E_CATEGORIES_EDITOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CATEGORIES_EDITOR, ECategoriesEditorPrivate))
-
-struct _ECategoriesEditorPrivate {
- ECategoriesSelector *categories_list;
- GtkWidget *categories_entry;
- GtkWidget *categories_entry_label;
- GtkWidget *new_button;
- GtkWidget *edit_button;
- GtkWidget *delete_button;
-
- guint ignore_category_changes : 1;
-};
-
-enum {
- COLUMN_ACTIVE,
- COLUMN_ICON,
- COLUMN_CATEGORY,
- N_COLUMNS
-};
-
-enum {
- PROP_0,
- PROP_ENTRY_VISIBLE
-};
-
-enum {
- ENTRY_CHANGED,
- LAST_SIGNAL
-};
-
-static gint signals[LAST_SIGNAL] = {0};
-
-G_DEFINE_TYPE (ECategoriesEditor, e_categories_editor, GTK_TYPE_GRID)
-
-static void
-entry_changed_cb (GtkEntry *entry,
- ECategoriesEditor *editor)
-{
- g_signal_emit (editor, signals[ENTRY_CHANGED], 0);
-}
-
-static void
-categories_editor_selection_changed_cb (ECategoriesEditor *editor,
- GtkTreeSelection *selection)
-{
- GtkWidget *widget;
- gint n_rows;
-
- n_rows = gtk_tree_selection_count_selected_rows (selection);
-
- widget = editor->priv->edit_button;
- gtk_widget_set_sensitive (widget, n_rows == 1);
-
- widget = editor->priv->delete_button;
- gtk_widget_set_sensitive (widget, n_rows >= 1);
-}
-
-static void
-category_checked_cb (ECategoriesSelector *selector,
- const gchar *category,
- const gboolean checked,
- ECategoriesEditor *editor)
-{
- GtkEntry *entry;
- gchar *categories;
-
- entry = GTK_ENTRY (editor->priv->categories_entry);
- categories = e_categories_selector_get_checked (selector);
-
- gtk_entry_set_text (entry, categories);
-
- g_free (categories);
-}
-
-static void
-new_button_clicked_cb (GtkButton *button,
- ECategoriesEditor *editor)
-{
- ECategoryEditor *cat_editor = e_category_editor_new ();
-
- e_category_editor_create_category (cat_editor);
-
- gtk_widget_destroy (GTK_WIDGET (cat_editor));
-}
-
-static void
-edit_button_clicked_cb (GtkButton *button,
- ECategoriesEditor *editor)
-{
- ECategoryEditor *cat_editor = e_category_editor_new ();
- gchar *category;
-
- category = e_categories_selector_get_selected (
- editor->priv->categories_list);
-
- e_category_editor_edit_category (cat_editor, category);
-
- gtk_widget_destroy (GTK_WIDGET (cat_editor));
- g_free (category);
-}
-
-static void
-categories_editor_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ENTRY_VISIBLE:
- e_categories_editor_set_entry_visible (
- E_CATEGORIES_EDITOR (object),
- g_value_get_boolean (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-categories_editor_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ENTRY_VISIBLE:
- g_value_set_boolean (
- value, e_categories_editor_get_entry_visible (
- E_CATEGORIES_EDITOR (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-e_categories_editor_class_init (ECategoriesEditorClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ECategoriesEditorPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = categories_editor_set_property;
- object_class->get_property = categories_editor_get_property;
-
- g_object_class_install_property (
- object_class,
- PROP_ENTRY_VISIBLE,
- g_param_spec_boolean (
- "entry-visible",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- signals[ENTRY_CHANGED] = g_signal_new (
- "entry-changed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ECategoriesEditorClass, entry_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-e_categories_editor_init (ECategoriesEditor *editor)
-{
- GtkEntryCompletion *completion;
- GtkGrid *grid;
- GtkWidget *entry_categories;
- GtkWidget *label_header;
- GtkWidget *label2;
- GtkWidget *scrolledwindow1;
- GtkWidget *categories_list;
- GtkWidget *hbuttonbox1;
- GtkWidget *button_new;
- GtkWidget *button_edit;
- GtkWidget *button_delete;
-
- gtk_widget_set_size_request (GTK_WIDGET (editor), -1, 400);
-
- grid = GTK_GRID (editor);
-
- gtk_grid_set_row_spacing (grid, 6);
- gtk_grid_set_column_spacing (grid, 6);
-
- label_header = gtk_label_new_with_mnemonic (
- _("Currently _used categories:"));
- gtk_widget_set_halign (label_header, GTK_ALIGN_FILL);
- gtk_grid_attach (grid, label_header, 0, 0, 1, 1);
- gtk_label_set_justify (GTK_LABEL (label_header), GTK_JUSTIFY_CENTER);
- gtk_misc_set_alignment (GTK_MISC (label_header), 0, 0.5);
-
- entry_categories = gtk_entry_new ();
- gtk_widget_set_hexpand (entry_categories, TRUE);
- gtk_widget_set_halign (entry_categories, GTK_ALIGN_FILL);
- gtk_grid_attach (grid, entry_categories, 0, 1, 1, 1);
-
- label2 = gtk_label_new_with_mnemonic (_("_Available Categories:"));
- gtk_widget_set_halign (label2, GTK_ALIGN_FILL);
- gtk_grid_attach (grid, label2, 0, 2, 1, 1);
- gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_CENTER);
- gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5);
-
- scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
- g_object_set (G_OBJECT (scrolledwindow1),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_grid_attach (grid, scrolledwindow1, 0, 3, 1, 1);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (scrolledwindow1),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_SHADOW_IN);
-
- categories_list = GTK_WIDGET (e_categories_selector_new ());
- gtk_container_add (GTK_CONTAINER (scrolledwindow1), categories_list);
- gtk_widget_set_size_request (categories_list, -1, 350);
- gtk_tree_view_set_headers_visible (
- GTK_TREE_VIEW (categories_list), FALSE);
- gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (categories_list), TRUE);
- g_signal_connect (
- G_OBJECT (categories_list), "category-checked",
- G_CALLBACK (category_checked_cb), editor);
-
- hbuttonbox1 = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
- g_object_set (G_OBJECT (hbuttonbox1),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_grid_attach (grid, hbuttonbox1, 0, 4, 1, 1);
- gtk_box_set_spacing (GTK_BOX (hbuttonbox1), 6);
-
- button_new = gtk_button_new_from_stock (GTK_STOCK_NEW);
- gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_new);
- gtk_widget_set_can_default (button_new, TRUE);
-
- button_edit = gtk_button_new_from_stock (GTK_STOCK_EDIT);
- gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_edit);
- gtk_widget_set_can_default (button_edit, TRUE);
-
- button_delete = gtk_button_new_from_stock (GTK_STOCK_DELETE);
- gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_delete);
- gtk_widget_set_can_default (button_delete, TRUE);
-
- gtk_label_set_mnemonic_widget (
- GTK_LABEL (label_header), entry_categories);
- gtk_label_set_mnemonic_widget (
- GTK_LABEL (label2), categories_list);
-
- editor->priv = E_CATEGORIES_EDITOR_GET_PRIVATE (editor);
-
- editor->priv->categories_list = E_CATEGORIES_SELECTOR (categories_list);
- editor->priv->categories_entry = entry_categories;
- editor->priv->categories_entry_label = label_header;
-
- g_signal_connect_swapped (
- editor->priv->categories_list, "selection-changed",
- G_CALLBACK (categories_editor_selection_changed_cb), editor);
-
- completion = e_category_completion_new ();
- gtk_entry_set_completion (
- GTK_ENTRY (editor->priv->categories_entry), completion);
- g_object_unref (completion);
-
- editor->priv->new_button = button_new;
- g_signal_connect (
- editor->priv->new_button, "clicked",
- G_CALLBACK (new_button_clicked_cb), editor);
-
- editor->priv->edit_button = button_edit;
- g_signal_connect (
- editor->priv->edit_button, "clicked",
- G_CALLBACK (edit_button_clicked_cb), editor);
-
- editor->priv->delete_button = button_delete;
- g_signal_connect_swapped (
- editor->priv->delete_button, "clicked",
- G_CALLBACK (e_categories_selector_delete_selection),
- editor->priv->categories_list);
-
- g_signal_connect (
- editor->priv->categories_entry, "changed",
- G_CALLBACK (entry_changed_cb), editor);
-
- gtk_widget_show_all (GTK_WIDGET (editor));
-}
-
-/**
- * e_categories_editor_new:
- *
- * Creates a new #ECategoriesEditor widget.
- *
- * Returns: a new #ECategoriesEditor
- *
- * Since: 3.2
- **/
-GtkWidget *
-e_categories_editor_new (void)
-{
- return g_object_new (E_TYPE_CATEGORIES_EDITOR, NULL);
-}
-
-/**
- * e_categories_editor_get_categories:
- * @editor: an #ECategoriesEditor
- *
- * Gets a comma-separated list of the categories currently selected
- * in the editor.
- *
- * Returns: a comma-separated list of categories. Free returned
- * pointer with g_free().
- *
- * Since: 3.2
- **/
-gchar *
-e_categories_editor_get_categories (ECategoriesEditor *editor)
-{
- ECategoriesSelector *categories_list;
-
- g_return_val_if_fail (E_IS_CATEGORIES_EDITOR (editor), NULL);
-
- categories_list = editor->priv->categories_list;
-
- return e_categories_selector_get_checked (categories_list);
-}
-
-/**
- * e_categories_editor_set_categories:
- * @editor: an #ECategoriesEditor
- * @categories: comma-separated list of categories
- *
- * Sets the list of categories selected on the editor.
- *
- * Since: 3.2
- **/
-void
-e_categories_editor_set_categories (ECategoriesEditor *editor,
- const gchar *categories)
-{
- ECategoriesSelector *categories_list;
-
- g_return_if_fail (E_IS_CATEGORIES_EDITOR (editor));
-
- categories_list = editor->priv->categories_list;
-
- e_categories_selector_set_checked (categories_list, categories);
- category_checked_cb (categories_list, NULL, FALSE, editor);
-}
-
-/**
- * e_categories_editor_get_entry_visible:
- * @editor: an #ECategoriesEditor
- *
- * Return the visibility of the category input entry.
- *
- * Returns: whether the entry is visible
- *
- * Since: 3.2
- **/
-gboolean
-e_categories_editor_get_entry_visible (ECategoriesEditor *editor)
-{
- g_return_val_if_fail (E_IS_CATEGORIES_EDITOR (editor), TRUE);
-
- return gtk_widget_get_visible (editor->priv->categories_entry);
-}
-
-/**
- * e_categories_editor_set_entry_visible:
- * @editor: an #ECategoriesEditor
- * @entry_visible: whether to make the entry visible
- *
- * Sets the visibility of the category input entry.
- *
- * Since: 3.2
- **/
-void
-e_categories_editor_set_entry_visible (ECategoriesEditor *editor,
- gboolean entry_visible)
-{
- g_return_if_fail (E_IS_CATEGORIES_EDITOR (editor));
-
- if ((gtk_widget_get_visible (editor->priv->categories_entry) ? 1 : 0) ==
- (entry_visible ? 1 : 0))
- return;
-
- gtk_widget_set_visible (
- editor->priv->categories_entry, entry_visible);
- gtk_widget_set_visible (
- editor->priv->categories_entry_label, entry_visible);
- e_categories_selector_set_items_checkable (
- editor->priv->categories_list, entry_visible);
-
- g_object_notify (G_OBJECT (editor), "entry-visible");
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CATEGORIES_EDITOR_H
-#define E_CATEGORIES_EDITOR_H
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CATEGORIES_EDITOR \
- (e_categories_editor_get_type ())
-#define E_CATEGORIES_EDITOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CATEGORIES_EDITOR, ECategoriesEditor))
-#define E_CATEGORIES_EDITOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CATEGORIES_EDITOR, ECategoriesEditorClass))
-#define E_IS_CATEGORIES_EDITOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CATEGORIES_EDITOR))
-#define E_IS_CATEGORIES_EDITOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_CATEGORIES_EDITOR))
-#define E_CATEGORIES_EDITOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CATEGORIES_EDITOR, ECategoriesEditorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECategoriesEditor ECategoriesEditor;
-typedef struct _ECategoriesEditorClass ECategoriesEditorClass;
-typedef struct _ECategoriesEditorPrivate ECategoriesEditorPrivate;
-
-/**
- * ECategoriesEditor:
- *
- * Contains only private data that should be read and manipulated using the
- * functions below.
- *
- * Since: 3.2
- **/
-struct _ECategoriesEditor {
- GtkGrid parent;
- ECategoriesEditorPrivate *priv;
-};
-
-struct _ECategoriesEditorClass {
- GtkGridClass parent_class;
-
- void (*entry_changed) (GtkEntry *entry);
-};
-
-GType e_categories_editor_get_type (void);
-GtkWidget * e_categories_editor_new (void);
-gchar * e_categories_editor_get_categories
- (ECategoriesEditor *editor);
-void e_categories_editor_set_categories
- (ECategoriesEditor *editor,
- const gchar *categories);
-gboolean e_categories_editor_get_entry_visible
- (ECategoriesEditor *editor);
-void e_categories_editor_set_entry_visible
- (ECategoriesEditor *editor,
- gboolean entry_visible);
-
-G_END_DECLS
-
-#endif /* E_CATEGORIES_EDITOR_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <config.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserver/libedataserver.h>
-
-#include "e-categories-selector.h"
-#include "e-data-server-ui-marshal.h"
-
-#define E_CATEGORIES_SELECTOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CATEGORIES_SELECTOR, ECategoriesSelectorPrivate))
-
-struct _ECategoriesSelectorPrivate {
- gboolean checkable;
- GHashTable *selected_categories;
-
- gboolean ignore_category_changes;
-};
-
-enum {
- PROP_0,
- PROP_ITEMS_CHECKABLE
-};
-
-enum {
- CATEGORY_CHECKED,
- SELECTION_CHANGED,
- LAST_SIGNAL
-};
-
-enum {
- COLUMN_ACTIVE,
- COLUMN_ICON,
- COLUMN_CATEGORY,
- N_COLUMNS
-};
-
-static gint signals[LAST_SIGNAL] = {0};
-
-G_DEFINE_TYPE (
- ECategoriesSelector,
- e_categories_selector,
- GTK_TYPE_TREE_VIEW)
-
-static void
-categories_selector_build_model (ECategoriesSelector *selector)
-{
- GtkListStore *store;
- GList *list, *iter;
-
- store = gtk_list_store_new (
- N_COLUMNS, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING);
-
- gtk_tree_sortable_set_sort_column_id (
- GTK_TREE_SORTABLE (store),
- COLUMN_CATEGORY, GTK_SORT_ASCENDING);
-
- list = e_categories_get_list ();
- for (iter = list; iter != NULL; iter = iter->next) {
- const gchar *category_name = iter->data;
- const gchar *filename;
- GdkPixbuf *pixbuf = NULL;
- GtkTreeIter iter;
- gboolean active;
-
- /* Only add user-visible categories. */
- if (!e_categories_is_searchable (category_name))
- continue;
-
- active = (g_hash_table_lookup (
- selector->priv->selected_categories,
- category_name) != NULL);
-
- filename = e_categories_get_icon_file_for (category_name);
- if (filename != NULL)
- pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
-
- gtk_list_store_append (store, &iter);
-
- gtk_list_store_set (
- store, &iter,
- COLUMN_ACTIVE, active,
- COLUMN_ICON, pixbuf,
- COLUMN_CATEGORY, category_name,
- -1);
-
- if (pixbuf != NULL)
- g_object_unref (pixbuf);
- }
-
- gtk_tree_view_set_model (
- GTK_TREE_VIEW (selector), GTK_TREE_MODEL (store));
-
- /* This has to be reset everytime we install a new model */
- gtk_tree_view_set_search_column (
- GTK_TREE_VIEW (selector), COLUMN_CATEGORY);
-
- g_list_free (list);
- g_object_unref (store);
-}
-
-static void
-category_toggled_cb (GtkCellRenderer *renderer,
- const gchar *path,
- ECategoriesSelector *selector)
-{
- GtkTreeModel *model;
- GtkTreePath *tree_path;
- GtkTreeIter iter;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
- g_return_if_fail (model);
-
- tree_path = gtk_tree_path_new_from_string (path);
- g_return_if_fail (tree_path);
-
- if (gtk_tree_model_get_iter (model, &iter, tree_path)) {
- gchar *category;
- gboolean active;
-
- gtk_tree_model_get (
- model, &iter,
- COLUMN_ACTIVE, &active,
- COLUMN_CATEGORY, &category, -1);
-
- gtk_list_store_set (
- GTK_LIST_STORE (model), &iter,
- COLUMN_ACTIVE, !active, -1);
-
- if (active)
- g_hash_table_remove (
- selector->priv->selected_categories, category);
- else
- g_hash_table_insert (
- selector->priv->selected_categories,
- g_strdup (category), g_strdup (category));
-
- g_signal_emit (
- selector, signals[CATEGORY_CHECKED], 0,
- category, !active);
-
- g_free (category);
- }
-
- gtk_tree_path_free (tree_path);
-}
-
-static void
-categories_selector_listener_cb (gpointer useless_pointer,
- ECategoriesSelector *selector)
-{
- if (!selector->priv->ignore_category_changes)
- categories_selector_build_model (selector);
-}
-
-static gboolean
-categories_selector_key_press_event (ECategoriesSelector *selector,
- GdkEventKey *event)
-{
- if (event->keyval == GDK_KEY_Delete) {
- e_categories_selector_delete_selection (selector);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-categories_selector_selection_changed (GtkTreeSelection *selection,
- ECategoriesSelector *selector)
-{
- g_signal_emit (selector, signals[SELECTION_CHANGED], 0, selection);
-}
-
-static void
-categories_selector_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ITEMS_CHECKABLE:
- g_value_set_boolean (
- value,
- e_categories_selector_get_items_checkable (
- E_CATEGORIES_SELECTOR (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-categories_selector_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ITEMS_CHECKABLE:
- e_categories_selector_set_items_checkable (
- E_CATEGORIES_SELECTOR (object),
- g_value_get_boolean (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-categories_selector_dispose (GObject *object)
-{
- ECategoriesSelectorPrivate *priv;
-
- priv = E_CATEGORIES_SELECTOR_GET_PRIVATE (object);
-
- if (priv->selected_categories != NULL) {
- g_hash_table_destroy (priv->selected_categories);
- priv->selected_categories = NULL;
- }
-
- /* Chain up to parent's dispose() method.*/
- G_OBJECT_CLASS (e_categories_selector_parent_class)->dispose (object);
-}
-
-static void
-categories_selector_finalize (GObject *object)
-{
- e_categories_unregister_change_listener (
- G_CALLBACK (categories_selector_listener_cb), object);
-}
-
-static void
-e_categories_selector_class_init (ECategoriesSelectorClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ECategoriesSelectorPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = categories_selector_set_property;
- object_class->get_property = categories_selector_get_property;
- object_class->dispose = categories_selector_dispose;
- object_class->finalize = categories_selector_finalize;
-
- g_object_class_install_property (
- object_class,
- PROP_ITEMS_CHECKABLE,
- g_param_spec_boolean (
- "items-checkable",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE));
-
- signals[CATEGORY_CHECKED] = g_signal_new (
- "category-checked",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ECategoriesSelectorClass, category_checked),
- NULL, NULL,
- e_data_server_ui_marshal_VOID__STRING_BOOLEAN,
- G_TYPE_NONE, 2,
- G_TYPE_STRING,
- G_TYPE_BOOLEAN);
-
- signals[SELECTION_CHANGED] = g_signal_new (
- "selection-changed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ECategoriesSelectorClass, selection_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- GTK_TYPE_TREE_SELECTION);
-}
-
-static void
-e_categories_selector_init (ECategoriesSelector *selector)
-{
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
- GtkTreeSelection *selection;
-
- selector->priv = E_CATEGORIES_SELECTOR_GET_PRIVATE (selector);
-
- selector->priv->checkable = TRUE;
- selector->priv->selected_categories = g_hash_table_new_full (
- (GHashFunc) g_str_hash,
- (GEqualFunc) g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
- selector->priv->ignore_category_changes = FALSE;
-
- renderer = gtk_cell_renderer_toggle_new ();
- column = gtk_tree_view_column_new_with_attributes (
- "?", renderer, "active", COLUMN_ACTIVE, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (selector), column);
-
- g_signal_connect (
- renderer, "toggled",
- G_CALLBACK (category_toggled_cb), selector);
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- column = gtk_tree_view_column_new_with_attributes (
- _("Icon"), renderer, "pixbuf", COLUMN_ICON, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (selector), column);
-
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes (
- _("Category"), renderer, "text", COLUMN_CATEGORY, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (selector), column);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector));
- g_signal_connect (
- selection, "changed",
- G_CALLBACK (categories_selector_selection_changed), selector);
-
- g_signal_connect (
- selector, "key-press-event",
- G_CALLBACK (categories_selector_key_press_event), NULL);
-
- e_categories_register_change_listener (
- G_CALLBACK (categories_selector_listener_cb), selector);
-
- categories_selector_build_model (selector);
-}
-
-/**
- * e_categories_selector_new:
- *
- * Since: 3.2
- **/
-GtkWidget *
-e_categories_selector_new (void)
-{
- return g_object_new (
- E_TYPE_CATEGORIES_SELECTOR,
- "items-checkable", TRUE, NULL);
-}
-
-/**
- * e_categories_selector_get_items_checkable:
- *
- * Since: 3.2
- **/
-gboolean
-e_categories_selector_get_items_checkable (ECategoriesSelector *selector)
-{
- g_return_val_if_fail (E_IS_CATEGORIES_SELECTOR (selector), TRUE);
-
- return selector->priv->checkable;
-}
-
-/**
- * e_categories_selector_set_items_checkable:
- *
- * Since: 3.2
- **/
-void
-e_categories_selector_set_items_checkable (ECategoriesSelector *selector,
- gboolean checkable)
-{
- GtkTreeViewColumn *column;
-
- g_return_if_fail (E_IS_CATEGORIES_SELECTOR (selector));
-
- if ((selector->priv->checkable ? 1 : 0) == (checkable ? 1 : 0))
- return;
-
- selector->priv->checkable = checkable;
-
- column = gtk_tree_view_get_column (
- GTK_TREE_VIEW (selector), COLUMN_ACTIVE);
- gtk_tree_view_column_set_visible (column, checkable);
-
- g_object_notify (G_OBJECT (selector), "items-checkable");
-}
-
-/**
- * e_categories_selector_get_checked:
- *
- * Free returned pointer with g_free().
- *
- * Since: 3.2
- **/
-gchar *
-e_categories_selector_get_checked (ECategoriesSelector *selector)
-{
- GString *str;
- GList *list, *category;
-
- g_return_val_if_fail (E_IS_CATEGORIES_SELECTOR (selector), NULL);
-
- str = g_string_new ("");
- list = g_hash_table_get_values (selector->priv->selected_categories);
-
- /* to get them always in the same order */
- list = g_list_sort (list, (GCompareFunc) g_utf8_collate);
-
- for (category = list; category != NULL; category = category->next) {
- if (str->len > 0)
- g_string_append_printf (
- str, ",%s", (gchar *) category->data);
- else
- g_string_append (str, (gchar *) category->data);
- }
-
- g_list_free (list);
-
- return g_string_free (str, FALSE);
-}
-
-/**
- * e_categories_selector_set_checked:
- *
- * Since: 3.2
- **/
-void
-e_categories_selector_set_checked (ECategoriesSelector *selector,
- const gchar *categories)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- gchar **arr;
- gint i;
-
- g_return_if_fail (E_IS_CATEGORIES_SELECTOR (selector));
-
- /* Clean up table of selected categories. */
- g_hash_table_remove_all (selector->priv->selected_categories);
-
- arr = g_strsplit (categories, ",", 0);
- if (arr) {
- for (i = 0; arr[i] != NULL; i++) {
- g_strstrip (arr[i]);
- g_hash_table_insert (
- selector->priv->selected_categories,
- g_strdup (arr[i]), g_strdup (arr[i]));
- }
- g_strfreev (arr);
- }
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
- if (gtk_tree_model_get_iter_first (model, &iter)) {
- do {
- gchar *category_name;
- gboolean found;
-
- gtk_tree_model_get (
- model, &iter,
- COLUMN_CATEGORY, &category_name,
- -1);
- found = (g_hash_table_lookup (
- selector->priv->selected_categories,
- category_name) != NULL);
- gtk_list_store_set (
- GTK_LIST_STORE (model), &iter,
- COLUMN_ACTIVE, found, -1);
-
- g_free (category_name);
- } while (gtk_tree_model_iter_next (model, &iter));
- }
-}
-
-/**
- * e_categories_selector_delete_selection:
- *
- * Since: 3.2
- **/
-void
-e_categories_selector_delete_selection (ECategoriesSelector *selector)
-{
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GList *selected, *item;
-
- g_return_if_fail (E_IS_CATEGORIES_SELECTOR (selector));
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
- g_return_if_fail (model != NULL);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector));
- selected = gtk_tree_selection_get_selected_rows (selection, &model);
-
- /* Remove categories in reverse order to avoid invalidating
- * tree paths as we iterate over the list. Note, the list is
- * probably already sorted but we sort again just to be safe. */
- selected = g_list_reverse (g_list_sort (
- selected, (GCompareFunc) gtk_tree_path_compare));
-
- /* Prevent the model from being rebuilt every time we
- * remove a category, since we're already modifying it. */
- selector->priv->ignore_category_changes = TRUE;
-
- for (item = selected; item != NULL; item = item->next) {
- GtkTreePath *path = item->data;
- GtkTreeIter iter;
- gchar *category;
-
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (
- model, &iter,
- COLUMN_CATEGORY, &category, -1);
- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
- e_categories_remove (category);
- g_free (category);
- }
-
- selector->priv->ignore_category_changes = FALSE;
-
- /* If we only remove one category, try to select another */
- if (g_list_length (selected) == 1) {
- GtkTreePath *path = selected->data;
-
- gtk_tree_selection_select_path (selection, path);
- if (!gtk_tree_selection_path_is_selected (selection, path))
- if (gtk_tree_path_prev (path))
- gtk_tree_selection_select_path (selection, path);
- }
-
- g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
- g_list_free (selected);
-}
-
-/**
- * e_categories_selector_get_selected:
- *
- * Free returned pointer with g_free().
- *
- * Since: 3.2
- **/
-gchar *
-e_categories_selector_get_selected (ECategoriesSelector *selector)
-{
- GtkTreeModel *model;
- GtkTreeSelection *selection;
- GList *selected, *item;
- GString *str = g_string_new ("");
-
- g_return_val_if_fail (E_IS_CATEGORIES_SELECTOR (selector), NULL);
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
- g_return_val_if_fail (model != NULL, NULL);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector));
- selected = gtk_tree_selection_get_selected_rows (selection, &model);
-
- for (item = selected; item != NULL; item = item->next) {
- GtkTreePath *path = item->data;
- GtkTreeIter iter;
- gchar *category;
-
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (
- model, &iter,
- COLUMN_CATEGORY, &category, -1);
- if (str->len == 0)
- g_string_assign (str, category);
- else
- g_string_append_printf (str, ",%s", category);
-
- g_free (category);
- }
-
- g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
- g_list_free (selected);
-
- return g_string_free (str, FALSE);
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CATEGORIES_SELECTOR_H
-#define E_CATEGORIES_SELECTOR_H
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CATEGORIES_SELECTOR \
- (e_categories_selector_get_type ())
-#define E_CATEGORIES_SELECTOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CATEGORIES_SELECTOR, ECategoriesSelector))
-#define E_CATEGORIES_SELECTOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CATEGORIES_SELECTOR, ECategoriesSelectorClass))
-#define E_IS_CATEGORIES_SELECTOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CATEGORIES_SELECTOR))
-#define E_IS_CATEGORIES_SELECTOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_CATEGORIES_SELECTOR))
-#define E_CATEGORIES_SELECTOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CATEGORIES_SELECTOR, ECategoriesSelectorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECategoriesSelector ECategoriesSelector;
-typedef struct _ECategoriesSelectorClass ECategoriesSelectorClass;
-typedef struct _ECategoriesSelectorPrivate ECategoriesSelectorPrivate;
-
-/**
- * ECategoriesSelector:
- *
- * Contains only private data that should be read and manipulated using the
- * functions below.
- *
- * Since: 3.2
- **/
-struct _ECategoriesSelector {
- GtkTreeView parent;
- ECategoriesSelectorPrivate *priv;
-};
-
-struct _ECategoriesSelectorClass {
- GtkTreeViewClass parent_class;
-
- void (*category_checked) (ECategoriesSelector *selector,
- const gchar *category,
- gboolean checked);
-
- void (*selection_changed) (ECategoriesSelector *selector,
- GtkTreeSelection *selection);
-};
-
-GType e_categories_selector_get_type (void);
-GtkWidget * e_categories_selector_new (void);
-gchar * e_categories_selector_get_checked
- (ECategoriesSelector *selector);
-void e_categories_selector_set_checked
- (ECategoriesSelector *selector,
- const gchar *categories);
-gboolean e_categories_selector_get_items_checkable
- (ECategoriesSelector *selector);
-void e_categories_selector_set_items_checkable
- (ECategoriesSelector *selectr,
- gboolean checkable);
-void e_categories_selector_delete_selection
- (ECategoriesSelector *selector);
-gchar * e_categories_selector_get_selected
- (ECategoriesSelector *selector);
-
-G_END_DECLS
-
-#endif /* E_CATEGORIES_SELECTOR_H */
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- */
-
-#include "e-category-completion.h"
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserver/libedataserver.h>
-
-#define E_CATEGORY_COMPLETION_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CATEGORY_COMPLETION, ECategoryCompletionPrivate))
-
-struct _ECategoryCompletionPrivate {
- GtkWidget *last_known_entry;
- gchar *create;
- gchar *prefix;
-};
-
-enum {
- COLUMN_PIXBUF,
- COLUMN_CATEGORY,
- COLUMN_NORMALIZED,
- NUM_COLUMNS
-};
-
-G_DEFINE_TYPE (
- ECategoryCompletion,
- e_category_completion,
- GTK_TYPE_ENTRY_COMPLETION)
-
-/* Forward Declarations */
-
-static void
-category_completion_track_entry (GtkEntryCompletion *completion);
-
-static void
-category_completion_build_model (GtkEntryCompletion *completion)
-{
- GtkListStore *store;
- GList *list;
-
- store = gtk_list_store_new (
- NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
-
- list = e_categories_get_list ();
- while (list != NULL) {
- const gchar *category = list->data;
- const gchar *filename;
- gchar *normalized;
- gchar *casefolded;
- GdkPixbuf *pixbuf = NULL;
- GtkTreeIter iter;
-
- /* Only add user-visible categories. */
- if (!e_categories_is_searchable (category)) {
- list = g_list_delete_link (list, list);
- continue;
- }
-
- filename = e_categories_get_icon_file_for (category);
- if (filename != NULL && *filename != '\0')
- pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
-
- normalized = g_utf8_normalize (
- category, -1, G_NORMALIZE_DEFAULT);
- casefolded = g_utf8_casefold (normalized, -1);
-
- gtk_list_store_append (store, &iter);
-
- gtk_list_store_set (
- store, &iter, COLUMN_PIXBUF, pixbuf,
- COLUMN_CATEGORY, category, COLUMN_NORMALIZED,
- casefolded, -1);
-
- g_free (normalized);
- g_free (casefolded);
-
- if (pixbuf != NULL)
- g_object_unref (pixbuf);
-
- list = g_list_delete_link (list, list);
- }
-
- gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (store));
-}
-
-static void
-category_completion_categories_changed_cb (GObject *some_private_object,
- GtkEntryCompletion *completion)
-{
- category_completion_build_model (completion);
-}
-
-static void
-category_completion_complete (GtkEntryCompletion *completion,
- const gchar *category)
-{
- GtkEditable *editable;
- GtkWidget *entry;
- const gchar *text;
- const gchar *cp;
- gint start_pos;
- gint end_pos;
- glong offset;
-
- entry = gtk_entry_completion_get_entry (completion);
-
- editable = GTK_EDITABLE (entry);
- text = gtk_entry_get_text (GTK_ENTRY (entry));
-
- /* Get the cursor position as a character offset. */
- offset = gtk_editable_get_position (editable);
-
- /* Find the rightmost comma before the cursor. */
- cp = g_utf8_offset_to_pointer (text, offset);
- cp = g_utf8_strrchr (text, (gssize) (cp - text), ',');
-
- /* Calculate the selection start position as a character offset. */
- if (cp == NULL)
- offset = 0;
- else {
- cp = g_utf8_next_char (cp);
- if (g_unichar_isspace (g_utf8_get_char (cp)))
- cp = g_utf8_next_char (cp);
- offset = g_utf8_pointer_to_offset (text, cp);
- }
- start_pos = (gint) offset;
-
- /* Find the leftmost comma after the cursor. */
- cp = g_utf8_offset_to_pointer (text, offset);
- cp = g_utf8_strchr (cp, -1, ',');
-
- /* Calculate the selection end position as a character offset. */
- if (cp == NULL)
- offset = -1;
- else {
- cp = g_utf8_next_char (cp);
- if (g_unichar_isspace (g_utf8_get_char (cp)))
- cp = g_utf8_next_char (cp);
- offset = g_utf8_pointer_to_offset (text, cp);
- }
- end_pos = (gint) offset;
-
- /* Complete the partially typed category. */
- gtk_editable_delete_text (editable, start_pos, end_pos);
- gtk_editable_insert_text (editable, category, -1, &start_pos);
- gtk_editable_insert_text (editable, ",", 1, &start_pos);
- gtk_editable_set_position (editable, start_pos);
-}
-
-static gboolean
-category_completion_is_match (GtkEntryCompletion *completion,
- const gchar *key,
- GtkTreeIter *iter)
-{
- ECategoryCompletionPrivate *priv;
- GtkTreeModel *model;
- GtkWidget *entry;
- GValue value = { 0, };
- gboolean match;
-
- priv = E_CATEGORY_COMPLETION_GET_PRIVATE (completion);
- entry = gtk_entry_completion_get_entry (completion);
- model = gtk_entry_completion_get_model (completion);
-
- /* XXX This would be easier if GtkEntryCompletion had an 'entry'
- * property that we could listen to for notifications. */
- if (entry != priv->last_known_entry)
- category_completion_track_entry (completion);
-
- if (priv->prefix == NULL)
- return FALSE;
-
- gtk_tree_model_get_value (model, iter, COLUMN_NORMALIZED, &value);
- match = g_str_has_prefix (g_value_get_string (&value), priv->prefix);
- g_value_unset (&value);
-
- return match;
-}
-
-static void
-category_completion_update_prefix (GtkEntryCompletion *completion)
-{
- ECategoryCompletionPrivate *priv;
- GtkEditable *editable;
- GtkTreeModel *model;
- GtkWidget *entry;
- GtkTreeIter iter;
- const gchar *text;
- const gchar *start;
- const gchar *end;
- const gchar *cp;
- gboolean valid;
- gchar *input;
- glong offset;
-
- priv = E_CATEGORY_COMPLETION_GET_PRIVATE (completion);
- entry = gtk_entry_completion_get_entry (completion);
- model = gtk_entry_completion_get_model (completion);
-
- /* XXX This would be easier if GtkEntryCompletion had an 'entry'
- * property that we could listen to for notifications. */
- if (entry != priv->last_known_entry) {
- category_completion_track_entry (completion);
- return;
- }
-
- editable = GTK_EDITABLE (entry);
- text = gtk_entry_get_text (GTK_ENTRY (entry));
-
- /* Get the cursor position as a character offset. */
- offset = gtk_editable_get_position (editable);
-
- /* Find the rightmost comma before the cursor. */
- cp = g_utf8_offset_to_pointer (text, offset);
- cp = g_utf8_strrchr (text, (gsize) (cp - text), ',');
-
- /* Mark the start of the prefix. */
- if (cp == NULL)
- start = text;
- else {
- cp = g_utf8_next_char (cp);
- if (g_unichar_isspace (g_utf8_get_char (cp)))
- cp = g_utf8_next_char (cp);
- start = cp;
- }
-
- /* Find the leftmost comma after the cursor. */
- cp = g_utf8_offset_to_pointer (text, offset);
- cp = g_utf8_strchr (cp, -1, ',');
-
- /* Mark the end of the prefix. */
- if (cp == NULL)
- end = text + strlen (text);
- else
- end = cp;
-
- if (priv->create != NULL)
- gtk_entry_completion_delete_action (completion, 0);
-
- g_free (priv->create);
- priv->create = NULL;
-
- g_free (priv->prefix);
- priv->prefix = NULL;
-
- if (start == end)
- return;
-
- input = g_strstrip (g_strndup (start, end - start));
- priv->create = input;
-
- input = g_utf8_normalize (input, -1, G_NORMALIZE_DEFAULT);
- priv->prefix = g_utf8_casefold (input, -1);
- g_free (input);
-
- if (*priv->create == '\0') {
- g_free (priv->create);
- priv->create = NULL;
- return;
- }
-
- valid = gtk_tree_model_get_iter_first (model, &iter);
- while (valid) {
- GValue value = { 0, };
-
- gtk_tree_model_get_value (
- model, &iter, COLUMN_NORMALIZED, &value);
- if (strcmp (g_value_get_string (&value), priv->prefix) == 0) {
- g_value_unset (&value);
- g_free (priv->create);
- priv->create = NULL;
- return;
- }
- g_value_unset (&value);
-
- valid = gtk_tree_model_iter_next (model, &iter);
- }
-
- input = g_strdup_printf (_("Create category \"%s\""), priv->create);
- gtk_entry_completion_insert_action_text (completion, 0, input);
- g_free (input);
-}
-
-static gboolean
-category_completion_sanitize_suffix (GtkEntry *entry,
- GdkEventFocus *event,
- GtkEntryCompletion *completion)
-{
- const gchar *text;
-
- g_return_val_if_fail (entry != NULL, FALSE);
- g_return_val_if_fail (completion != NULL, FALSE);
-
- text = gtk_entry_get_text (entry);
- if (text) {
- gint len = strlen (text), old_len = len;
-
- while (len > 0 && (text[len -1] == ' ' || text[len - 1] == ','))
- len--;
-
- if (old_len != len) {
- gchar *tmp = g_strndup (text, len);
-
- gtk_entry_set_text (entry, tmp);
-
- g_free (tmp);
- }
- }
-
- return FALSE;
-}
-
-static void
-category_completion_track_entry (GtkEntryCompletion *completion)
-{
- ECategoryCompletionPrivate *priv;
-
- priv = E_CATEGORY_COMPLETION_GET_PRIVATE (completion);
-
- if (priv->last_known_entry != NULL) {
- g_signal_handlers_disconnect_matched (
- priv->last_known_entry, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, completion);
- g_object_unref (priv->last_known_entry);
- }
-
- g_free (priv->prefix);
- priv->prefix = NULL;
-
- priv->last_known_entry = gtk_entry_completion_get_entry (completion);
- if (priv->last_known_entry == NULL)
- return;
-
- g_object_ref (priv->last_known_entry);
-
- g_signal_connect_swapped (
- priv->last_known_entry, "notify::cursor-position",
- G_CALLBACK (category_completion_update_prefix), completion);
-
- g_signal_connect_swapped (
- priv->last_known_entry, "notify::text",
- G_CALLBACK (category_completion_update_prefix), completion);
-
- g_signal_connect (
- priv->last_known_entry, "focus-out-event",
- G_CALLBACK (category_completion_sanitize_suffix), completion);
-
- category_completion_update_prefix (completion);
-}
-
-static void
-category_completion_constructed (GObject *object)
-{
- GtkCellRenderer *renderer;
- GtkEntryCompletion *completion;
-
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_category_completion_parent_class)->constructed (object);
-
- completion = GTK_ENTRY_COMPLETION (object);
-
- gtk_entry_completion_set_match_func (
- completion, (GtkEntryCompletionMatchFunc)
- category_completion_is_match, NULL, NULL);
-
- gtk_entry_completion_set_text_column (completion, COLUMN_CATEGORY);
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_layout_pack_start (
- GTK_CELL_LAYOUT (completion), renderer, FALSE);
- gtk_cell_layout_add_attribute (
- GTK_CELL_LAYOUT (completion),
- renderer, "pixbuf", COLUMN_PIXBUF);
- gtk_cell_layout_reorder (
- GTK_CELL_LAYOUT (completion), renderer, 0);
-
- e_categories_register_change_listener (
- G_CALLBACK (category_completion_categories_changed_cb),
- completion);
-
- category_completion_build_model (completion);
-}
-
-static void
-category_completion_dispose (GObject *object)
-{
- ECategoryCompletionPrivate *priv;
-
- priv = E_CATEGORY_COMPLETION_GET_PRIVATE (object);
-
- if (priv->last_known_entry != NULL) {
- g_signal_handlers_disconnect_matched (
- priv->last_known_entry, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, object);
- g_object_unref (priv->last_known_entry);
- priv->last_known_entry = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_category_completion_parent_class)->dispose (object);
-}
-
-static void
-category_completion_finalize (GObject *object)
-{
- ECategoryCompletionPrivate *priv;
-
- priv = E_CATEGORY_COMPLETION_GET_PRIVATE (object);
-
- g_free (priv->create);
- g_free (priv->prefix);
-
- e_categories_unregister_change_listener (
- G_CALLBACK (category_completion_categories_changed_cb),
- object);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_category_completion_parent_class)->finalize (object);
-}
-
-static gboolean
-category_completion_match_selected (GtkEntryCompletion *completion,
- GtkTreeModel *model,
- GtkTreeIter *iter)
-{
- GValue value = { 0, };
-
- gtk_tree_model_get_value (model, iter, COLUMN_CATEGORY, &value);
- category_completion_complete (completion, g_value_get_string (&value));
- g_value_unset (&value);
-
- return TRUE;
-}
-
-static void
-category_completion_action_activated (GtkEntryCompletion *completion,
- gint index)
-{
- ECategoryCompletionPrivate *priv;
- gchar *category;
-
- priv = E_CATEGORY_COMPLETION_GET_PRIVATE (completion);
-
- category = g_strdup (priv->create);
- e_categories_add (category, NULL, NULL, TRUE);
- category_completion_complete (completion, category);
- g_free (category);
-}
-
-static void
-e_category_completion_class_init (ECategoryCompletionClass *class)
-{
- GObjectClass *object_class;
- GtkEntryCompletionClass *entry_completion_class;
-
- g_type_class_add_private (class, sizeof (ECategoryCompletionPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->constructed = category_completion_constructed;
- object_class->dispose = category_completion_dispose;
- object_class->finalize = category_completion_finalize;
-
- entry_completion_class = GTK_ENTRY_COMPLETION_CLASS (class);
- entry_completion_class->match_selected = category_completion_match_selected;
- entry_completion_class->action_activated = category_completion_action_activated;
-}
-
-static void
-e_category_completion_init (ECategoryCompletion *category_completion)
-{
- category_completion->priv =
- E_CATEGORY_COMPLETION_GET_PRIVATE (category_completion);
-}
-
-/**
- * e_category_completion_new:
- *
- * Since: 2.26
- **/
-GtkEntryCompletion *
-e_category_completion_new (void)
-{
- return g_object_new (E_TYPE_CATEGORY_COMPLETION, NULL);
-}
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CATEGORY_COMPLETION_H
-#define E_CATEGORY_COMPLETION_H
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CATEGORY_COMPLETION \
- (e_category_completion_get_type ())
-#define E_CATEGORY_COMPLETION(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CATEGORY_COMPLETION, ECategoryCompletion))
-#define E_CATEGORY_COMPLETION_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CATEGORY_COMPLETION, ECategoryCompletionClass))
-#define E_IS_CATEGORY_COMPLETION(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CATEGORY_COMPLETION))
-#define E_IS_CATEGORY_COMPLETION_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_CATEGORY_COMPLETION))
-#define E_CATEGORY_COMPLETION_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CATEGORY_COMPLETION, ECategoryCompletionClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECategoryCompletion ECategoryCompletion;
-typedef struct _ECategoryCompletionClass ECategoryCompletionClass;
-typedef struct _ECategoryCompletionPrivate ECategoryCompletionPrivate;
-
-/**
- * ECategoryCompletion:
- *
- * Since: 2.26
- **/
-struct _ECategoryCompletion {
- GtkEntryCompletion parent;
- ECategoryCompletionPrivate *priv;
-};
-
-struct _ECategoryCompletionClass {
- GtkEntryCompletionClass parent_class;
-};
-
-GType e_category_completion_get_type (void);
-GtkEntryCompletion *
- e_category_completion_new (void);
-
-G_END_DECLS
-
-#endif /* E_CATEGORY_COMPLETION_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserver/libedataserver.h>
-
-#include "e-category-editor.h"
-
-#define E_CATEGORY_EDITOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CATEGORY_EDITOR, ECategoryEditorPrivate))
-
-struct _ECategoryEditorPrivate {
- GtkWidget *category_name;
- GtkWidget *category_icon;
-};
-
-G_DEFINE_TYPE (ECategoryEditor, e_category_editor, GTK_TYPE_DIALOG)
-
-static void
-update_preview (GtkFileChooser *chooser,
- gpointer user_data)
-{
- GtkImage *image;
- gchar *filename;
-
- g_return_if_fail (chooser != NULL);
-
- image = GTK_IMAGE (gtk_file_chooser_get_preview_widget (chooser));
- g_return_if_fail (image != NULL);
-
- filename = gtk_file_chooser_get_preview_filename (chooser);
-
- gtk_image_set_from_file (image, filename);
- gtk_file_chooser_set_preview_widget_active (chooser, filename != NULL);
-
- g_free (filename);
-}
-
-static void
-file_chooser_response (GtkDialog *dialog,
- gint response_id,
- GtkFileChooser *button)
-{
- g_return_if_fail (button != NULL);
-
- if (response_id == GTK_RESPONSE_NO)
- gtk_file_chooser_unselect_all (button);
-}
-
-static void
-category_editor_category_name_changed (GtkEntry *category_name_entry,
- ECategoryEditor *editor)
-{
- gchar *name;
-
- g_return_if_fail (editor != NULL);
- g_return_if_fail (category_name_entry != NULL);
-
- name = g_strdup (gtk_entry_get_text (category_name_entry));
- if (name != NULL)
- name = g_strstrip (name);
-
- gtk_dialog_set_response_sensitive (
- GTK_DIALOG (editor), GTK_RESPONSE_OK, name && *name);
-
- g_free (name);
-}
-
-static gchar *
-check_category_name (const gchar *name)
-{
- GString *str = NULL;
- gchar *p = (gchar *) name;
-
- str = g_string_new ("");
- while (*p) {
- switch (*p) {
- case ',':
- break;
- default:
- str = g_string_append_c (str, *p);
- }
- p++;
- }
-
- p = g_strstrip (g_string_free (str, FALSE));
-
- return p;
-}
-
-static void
-e_category_editor_class_init (ECategoryEditorClass *class)
-{
- g_type_class_add_private (class, sizeof (ECategoryEditorPrivate));
-}
-
-static void
-e_category_editor_init (ECategoryEditor *editor)
-{
- GtkWidget *dialog_content;
- GtkWidget *dialog_action_area;
- GtkGrid *grid_category_properties;
- GtkWidget *label_name;
- GtkWidget *label_icon;
- GtkWidget *category_name;
- GtkWidget *chooser_button;
- GtkWidget *no_image_button;
- GtkWidget *chooser_dialog;
- GtkWidget *preview;
-
- editor->priv = E_CATEGORY_EDITOR_GET_PRIVATE (editor);
-
- chooser_dialog = gtk_file_chooser_dialog_new (
- _("Category Icon"),
- NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
-
- no_image_button = gtk_button_new_with_mnemonic (_("_No Image"));
- gtk_button_set_image (
- GTK_BUTTON (no_image_button),
- gtk_image_new_from_stock (
- GTK_STOCK_CLOSE, GTK_ICON_SIZE_BUTTON));
- gtk_dialog_add_action_widget (
- GTK_DIALOG (chooser_dialog),
- no_image_button, GTK_RESPONSE_NO);
- gtk_dialog_add_button (
- GTK_DIALOG (chooser_dialog),
- GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT);
- gtk_file_chooser_set_local_only (
- GTK_FILE_CHOOSER (chooser_dialog), TRUE);
- gtk_widget_show (no_image_button);
-
- g_signal_connect (
- chooser_dialog, "update-preview",
- G_CALLBACK (update_preview), NULL);
-
- preview = gtk_image_new ();
- gtk_file_chooser_set_preview_widget (
- GTK_FILE_CHOOSER (chooser_dialog), preview);
- gtk_file_chooser_set_preview_widget_active (
- GTK_FILE_CHOOSER (chooser_dialog), TRUE);
- gtk_widget_show_all (preview);
-
- dialog_content = gtk_dialog_get_content_area (GTK_DIALOG (editor));
-
- grid_category_properties = GTK_GRID (gtk_grid_new ());
- gtk_box_pack_start (
- GTK_BOX (dialog_content),
- GTK_WIDGET (grid_category_properties), TRUE, TRUE, 0);
- gtk_container_set_border_width (
- GTK_CONTAINER (grid_category_properties), 12);
- gtk_grid_set_row_spacing (grid_category_properties, 6);
- gtk_grid_set_column_spacing (grid_category_properties, 6);
-
- label_name = gtk_label_new_with_mnemonic (_("Category _Name"));
- gtk_widget_set_halign (label_name, GTK_ALIGN_FILL);
- gtk_misc_set_alignment (GTK_MISC (label_name), 0, 0.5);
- gtk_grid_attach (grid_category_properties, label_name, 0, 0, 1, 1);
-
- category_name = gtk_entry_new ();
- gtk_widget_set_hexpand (category_name, TRUE);
- gtk_widget_set_halign (category_name, GTK_ALIGN_FILL);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label_name), category_name);
- gtk_grid_attach (grid_category_properties, category_name, 1, 0, 1, 1);
- editor->priv->category_name = category_name;
-
- label_icon = gtk_label_new_with_mnemonic (_("Category _Icon"));
- gtk_widget_set_halign (label_icon, GTK_ALIGN_FILL);
- gtk_misc_set_alignment (GTK_MISC (label_icon), 0, 0.5);
- gtk_grid_attach (grid_category_properties, label_icon, 0, 1, 1, 1);
-
- chooser_button = GTK_WIDGET (
- gtk_file_chooser_button_new_with_dialog (chooser_dialog));
- gtk_widget_set_hexpand (chooser_button, TRUE);
- gtk_widget_set_halign (chooser_button, GTK_ALIGN_FILL);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label_icon), chooser_button);
- gtk_grid_attach (grid_category_properties, chooser_button, 1, 1, 1, 1);
- editor->priv->category_icon = chooser_button;
-
- g_signal_connect (
- chooser_dialog, "response",
- G_CALLBACK (file_chooser_response), chooser_button);
-
- dialog_action_area = gtk_dialog_get_action_area (GTK_DIALOG (editor));
- gtk_button_box_set_layout (
- GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
-
- gtk_dialog_add_buttons (
- GTK_DIALOG (editor),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (editor), GTK_RESPONSE_OK);
- gtk_window_set_title (GTK_WINDOW (editor), _("Category Properties"));
- gtk_window_set_type_hint (
- GTK_WINDOW (editor), GDK_WINDOW_TYPE_HINT_DIALOG);
-
- gtk_widget_show_all (dialog_content);
-
- g_signal_connect (
- category_name, "changed",
- G_CALLBACK (category_editor_category_name_changed), editor);
-
- category_editor_category_name_changed (
- GTK_ENTRY (category_name), editor);
-}
-
-/**
- * e_categort_editor_new:
- *
- * Creates a new #ECategoryEditor widget.
- *
- * Returns: a new #ECategoryEditor
- *
- * Since: 3.2
- **/
-ECategoryEditor *
-e_category_editor_new ()
-{
- return g_object_new (E_TYPE_CATEGORY_EDITOR, NULL);
-}
-
-/**
- * e_category_editor_create_category:
- *
- * Since: 3.2
- **/
-const gchar *
-e_category_editor_create_category (ECategoryEditor *editor)
-{
- GtkEntry *entry;
- GtkFileChooser *file_chooser;
-
- g_return_val_if_fail (E_IS_CATEGORY_EDITOR (editor), NULL);
-
- entry = GTK_ENTRY (editor->priv->category_name);
- file_chooser = GTK_FILE_CHOOSER (editor->priv->category_icon);
-
- do {
- const gchar *category_name;
- const gchar *correct_category_name;
-
- if (gtk_dialog_run (GTK_DIALOG (editor)) != GTK_RESPONSE_OK)
- return NULL;
-
- category_name = gtk_entry_get_text (entry);
- correct_category_name = check_category_name (category_name);
-
- if (e_categories_exist (correct_category_name)) {
- GtkWidget *error_dialog;
-
- error_dialog = gtk_message_dialog_new (
- GTK_WINDOW (editor),
- 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- _("There is already a category '%s' in the "
- "configuration. Please use another name"),
- category_name);
-
- gtk_dialog_run (GTK_DIALOG (error_dialog));
- gtk_widget_destroy (error_dialog);
-
- /* Now we loop and run the dialog again. */
-
- } else {
- gchar *category_icon;
-
- category_icon =
- gtk_file_chooser_get_filename (file_chooser);
- e_categories_add (
- correct_category_name, NULL,
- category_icon, TRUE);
- g_free (category_icon);
-
- return correct_category_name;
- }
-
- } while (TRUE);
-}
-
-/**
- * e_category_editor_edit_category:
- *
- * Since: 3.2
- **/
-gboolean
-e_category_editor_edit_category (ECategoryEditor *editor,
- const gchar *category)
-{
- GtkFileChooser *file_chooser;
- const gchar *icon_file;
-
- g_return_val_if_fail (E_IS_CATEGORY_EDITOR (editor), FALSE);
- g_return_val_if_fail (category != NULL, FALSE);
-
- file_chooser = GTK_FILE_CHOOSER (editor->priv->category_icon);
-
- gtk_entry_set_text (GTK_ENTRY (editor->priv->category_name), category);
- gtk_widget_set_sensitive (editor->priv->category_name, FALSE);
-
- icon_file = e_categories_get_icon_file_for (category);
- if (icon_file) {
- gtk_file_chooser_set_filename (file_chooser, icon_file);
- update_preview (file_chooser, NULL);
- }
-
- if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK) {
- gchar *category_icon;
-
- category_icon = gtk_file_chooser_get_filename (file_chooser);
- e_categories_set_icon_file_for (category, category_icon);
-
- gtk_dialog_set_response_sensitive (
- GTK_DIALOG (editor), GTK_RESPONSE_OK, TRUE);
-
- g_free (category_icon);
-
- return TRUE;
- }
-
- return FALSE;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CATEGORY_EDITOR_H
-#define E_CATEGORY_EDITOR_H
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CATEGORY_EDITOR \
- (e_category_editor_get_type ())
-#define E_CATEGORY_EDITOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CATEGORY_EDITOR, ECategoryEditor))
-#define E_CATEGORY_EDITOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CATEGORY_EDITOR, ECategoryEditorClass))
-#define E_IS_CATEGORY_EDITOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CATEGORY_EDITOR))
-#define E_IS_CATEGORY_EDITOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_CATEGORY_EDITOR))
-#define E_CATEGORY_EDITOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CATEGORY_EDITOR, ECategoryEditorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECategoryEditor ECategoryEditor;
-typedef struct _ECategoryEditorClass ECategoryEditorClass;
-typedef struct _ECategoryEditorPrivate ECategoryEditorPrivate;
-
-/**
- * ECategoryEditor:
- *
- * Contains only private data that should be read and manipulated using the
- * functions below.
- *
- * Since: 3.2
- **/
-struct _ECategoryEditor {
- GtkDialog parent;
- ECategoryEditorPrivate *priv;
-};
-
-struct _ECategoryEditorClass {
- GtkDialogClass parent_class;
-};
-
-GType e_category_editor_get_type (void);
-ECategoryEditor *
- e_category_editor_new (void);
-const gchar * e_category_editor_create_category
- (ECategoryEditor *editor);
-gboolean e_category_editor_edit_category (ECategoryEditor *editor,
- const gchar *category);
-
-G_END_DECLS
-
-#endif /* E_CATEGORY_EDITOR_H */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-cell-renderer-color.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 Lesser 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 Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-cell-renderer-color.h"
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-
-#define E_CELL_RENDERER_COLOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColorPrivate))
-
-enum {
- PROP_0,
- PROP_COLOR
-};
-
-struct _ECellRendererColorPrivate {
- GdkColor *color;
-};
-
-G_DEFINE_TYPE (
- ECellRendererColor,
- e_cell_renderer_color,
- GTK_TYPE_CELL_RENDERER)
-
-static void
-cell_renderer_color_get_size (GtkCellRenderer *cell,
- GtkWidget *widget,
- const GdkRectangle *cell_area,
- gint *x_offset,
- gint *y_offset,
- gint *width,
- gint *height)
-{
- gint color_width = 16;
- gint color_height = 16;
- gint calc_width;
- gint calc_height;
- gfloat xalign;
- gfloat yalign;
- guint xpad;
- guint ypad;
-
- g_object_get (
- cell, "xalign", &xalign, "yalign", &yalign,
- "xpad", &xpad, "ypad", &ypad, NULL);
-
- calc_width = (gint) xpad * 2 + color_width;
- calc_height = (gint) ypad * 2 + color_height;
-
- if (cell_area && color_width > 0 && color_height > 0) {
- if (x_offset) {
- *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
- (1.0 - xalign) : xalign) *
- (cell_area->width - calc_width));
- *x_offset = MAX (*x_offset, 0);
- }
-
- if (y_offset) {
- *y_offset =(yalign *
- (cell_area->height - calc_height));
- *y_offset = MAX (*y_offset, 0);
- }
- } else {
- if (x_offset) *x_offset = 0;
- if (y_offset) *y_offset = 0;
- }
-
- if (width)
- *width = calc_width;
-
- if (height)
- *height = calc_height;
-}
-
-static void
-cell_renderer_color_render (GtkCellRenderer *cell,
- cairo_t *cr,
- GtkWidget *widget,
- const GdkRectangle *background_area,
- const GdkRectangle *cell_area,
- GtkCellRendererState flags)
-{
- ECellRendererColorPrivate *priv;
- GdkRectangle pix_rect;
- GdkRectangle draw_rect;
- GdkRGBA rgba;
- guint xpad;
- guint ypad;
-
- priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (cell);
-
- if (priv->color == NULL)
- return;
-
- cell_renderer_color_get_size (
- cell, widget, cell_area,
- &pix_rect.x, &pix_rect.y,
- &pix_rect.width, &pix_rect.height);
-
- g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL);
-
- pix_rect.x += cell_area->x + xpad;
- pix_rect.y += cell_area->y + ypad;
- pix_rect.width -= xpad * 2;
- pix_rect.height -= ypad * 2;
-
- if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
- return;
-
- rgba.red = priv->color->red / 65535.0;
- rgba.green = priv->color->green / 65535.0;
- rgba.blue = priv->color->blue / 65535.0;
- rgba.alpha = 1.0;
-
- gdk_cairo_set_source_rgba (cr, &rgba);
- cairo_rectangle (cr, pix_rect.x, pix_rect.y, draw_rect.width, draw_rect.height);
-
- cairo_fill (cr);
-}
-
-static void
-cell_renderer_color_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ECellRendererColorPrivate *priv;
-
- priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (object);
-
- switch (property_id) {
- case PROP_COLOR:
- if (priv->color != NULL)
- gdk_color_free (priv->color);
- priv->color = g_value_dup_boxed (value);
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-cell_renderer_color_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ECellRendererColorPrivate *priv;
-
- priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (object);
-
- switch (property_id) {
- case PROP_COLOR:
- g_value_set_boxed (value, priv->color);
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-cell_renderer_color_finalize (GObject *object)
-{
- ECellRendererColorPrivate *priv;
-
- priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (object);
-
- if (priv->color != NULL)
- gdk_color_free (priv->color);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_cell_renderer_color_parent_class)->finalize (object);
-}
-
-static void
-e_cell_renderer_color_class_init (ECellRendererColorClass *class)
-{
- GObjectClass *object_class;
- GtkCellRendererClass *cell_class;
-
- g_type_class_add_private (class, sizeof (ECellRendererColorPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = cell_renderer_color_set_property;
- object_class->get_property = cell_renderer_color_get_property;
- object_class->finalize = cell_renderer_color_finalize;
-
- cell_class = GTK_CELL_RENDERER_CLASS (class);
- cell_class->get_size = cell_renderer_color_get_size;
- cell_class->render = cell_renderer_color_render;
-
- g_object_class_install_property (
- object_class,
- PROP_COLOR,
- g_param_spec_boxed (
- "color",
- "Color Info",
- "The color to render",
- GDK_TYPE_COLOR,
- G_PARAM_READWRITE));
-}
-
-static void
-e_cell_renderer_color_init (ECellRendererColor *cellcolor)
-{
- cellcolor->priv = E_CELL_RENDERER_COLOR_GET_PRIVATE (cellcolor);
-
- g_object_set (cellcolor, "xpad", 4, NULL);
-}
-
-/**
- * e_cell_renderer_color_new:
- *
- * Since: 2.22
- **/
-GtkCellRenderer *
-e_cell_renderer_color_new (void)
-{
- return g_object_new (E_TYPE_CELL_RENDERER_COLOR, NULL);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-cell-renderer-color.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 Lesser 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 Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef _E_CELL_RENDERER_COLOR_H_
-#define _E_CELL_RENDERER_COLOR_H_
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CELL_RENDERER_COLOR \
- (e_cell_renderer_color_get_type ())
-#define E_CELL_RENDERER_COLOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColor))
-#define E_CELL_RENDERER_COLOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColorClass))
-#define E_IS_CELL_RENDERER_COLOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CELL_RENDERER_COLOR))
-#define E_IS_CELL_RENDERER_COLOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE ((cls), E_TYPE_CELL_RENDERER_COLOR))
-#define E_CELL_RENDERER_COLOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CELL_RENDERER_COLOR, ECellRendererColorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ECellRendererColor ECellRendererColor;
-typedef struct _ECellRendererColorClass ECellRendererColorClass;
-typedef struct _ECellRendererColorPrivate ECellRendererColorPrivate;
-
-/**
- * ECellRendererColor:
- *
- * Since: 2.22
- **/
-struct _ECellRendererColor {
- GtkCellRenderer parent;
- ECellRendererColorPrivate *priv;
-};
-
-struct _ECellRendererColorClass {
- GtkCellRendererClass parent_class;
-
- /* Padding for future expansion */
- void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
-};
-
-GType e_cell_renderer_color_get_type (void);
-GtkCellRenderer *e_cell_renderer_color_new (void);
-
-G_END_DECLS
-
-#endif /* _E_CELL_RENDERER_COLOR_H_ */
+++ /dev/null
-/*
- * e-client-utils.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-
-#include <libebook/libebook.h>
-#include <libecal/libecal.h>
-
-#include <libedataserver/e-client-private.h>
-
-#include "e-passwords.h"
-#include "e-client-utils.h"
-
-/**
- * e_client_utils_new:
- *
- * Proxy function for e_book_client_utils_new() and e_cal_client_utils_new().
- *
- * Since: 3.2
- **/
-EClient *
-e_client_utils_new (ESource *source,
- EClientSourceType source_type,
- GError **error)
-{
- EClient *res = NULL;
-
- g_return_val_if_fail (source != NULL, NULL);
- g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-
- switch (source_type) {
- case E_CLIENT_SOURCE_TYPE_CONTACTS:
- res = E_CLIENT (e_book_client_new (source, error));
- break;
- case E_CLIENT_SOURCE_TYPE_EVENTS:
- res = E_CLIENT (e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, error));
- break;
- case E_CLIENT_SOURCE_TYPE_MEMOS:
- res = E_CLIENT (e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, error));
- break;
- case E_CLIENT_SOURCE_TYPE_TASKS:
- res = E_CLIENT (e_cal_client_new (source, E_CAL_CLIENT_SOURCE_TYPE_TASKS, error));
- break;
- default:
- g_return_val_if_reached (NULL);
- break;
- }
-
- return res;
-}
-
-typedef struct _EClientUtilsAsyncOpData {
- GAsyncReadyCallback callback;
- gpointer user_data;
- GCancellable *cancellable;
- ESource *source;
- EClient *client;
- gboolean open_finished;
- GError *opened_cb_error;
- guint retry_open_id;
- gboolean only_if_exists;
- guint pending_properties_count;
-} EClientUtilsAsyncOpData;
-
-static void
-free_client_utils_async_op_data (EClientUtilsAsyncOpData *async_data)
-{
- g_return_if_fail (async_data != NULL);
- g_return_if_fail (async_data->cancellable != NULL);
- g_return_if_fail (async_data->client != NULL);
-
- if (async_data->retry_open_id)
- g_source_remove (async_data->retry_open_id);
-
- g_signal_handlers_disconnect_matched (async_data->cancellable, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, async_data);
- g_signal_handlers_disconnect_matched (async_data->client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, async_data);
-
- if (async_data->opened_cb_error)
- g_error_free (async_data->opened_cb_error);
- g_object_unref (async_data->cancellable);
- g_object_unref (async_data->client);
- g_object_unref (async_data->source);
- g_free (async_data);
-}
-
-static gboolean
-complete_async_op_in_idle_cb (gpointer user_data)
-{
- GSimpleAsyncResult *simple = user_data;
- gint run_main_depth;
-
- g_return_val_if_fail (simple != NULL, FALSE);
-
- run_main_depth = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (simple), "run-main-depth"));
- if (run_main_depth < 1)
- run_main_depth = 1;
-
- /* do not receive in higher level than was initially run */
- if (g_main_depth () > run_main_depth) {
- return TRUE;
- }
-
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-
- return FALSE;
-}
-
-#define return_async_error_if_fail(expr, callback, user_data, src, source_tag) G_STMT_START { \
- if (G_LIKELY ((expr))) { } else { \
- GError *error; \
- \
- error = g_error_new (E_CLIENT_ERROR, E_CLIENT_ERROR_INVALID_ARG, \
- "%s: assertion '%s' failed", G_STRFUNC, #expr); \
- \
- return_async_error (error, callback, user_data, src, source_tag); \
- g_error_free (error); \
- return; \
- } \
- } G_STMT_END
-
-static void
-return_async_error (const GError *error,
- GAsyncReadyCallback callback,
- gpointer user_data,
- ESource *source,
- gpointer source_tag)
-{
- GSimpleAsyncResult *simple;
-
- g_return_if_fail (error != NULL);
- g_return_if_fail (source_tag != NULL);
-
- simple = g_simple_async_result_new (G_OBJECT (source), callback, user_data, source_tag);
- g_simple_async_result_set_from_error (simple, error);
-
- g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
- g_idle_add (complete_async_op_in_idle_cb, simple);
-}
-
-static void
-client_utils_get_backend_property_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- EClient *client = E_CLIENT (source_object);
- EClientUtilsAsyncOpData *async_data = user_data;
- GSimpleAsyncResult *simple;
-
- g_return_if_fail (async_data != NULL);
- g_return_if_fail (async_data->client != NULL);
- g_return_if_fail (async_data->client == client);
-
- if (result) {
- gchar *prop_value = NULL;
-
- if (e_client_get_backend_property_finish (client, result, &prop_value, NULL))
- g_free (prop_value);
-
- async_data->pending_properties_count--;
- if (async_data->pending_properties_count)
- return;
- }
-
- simple = g_simple_async_result_new (G_OBJECT (async_data->source), async_data->callback, async_data->user_data, e_client_utils_open_new);
- g_simple_async_result_set_op_res_gpointer (simple, g_object_ref (async_data->client), g_object_unref);
-
- g_object_set_data (G_OBJECT (simple), "run-main-depth", GINT_TO_POINTER (g_main_depth ()));
- g_idle_add (complete_async_op_in_idle_cb, simple);
-
- free_client_utils_async_op_data (async_data);
-}
-
-static void
-client_utils_capabilities_retrieved_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- EClient *client = E_CLIENT (source_object);
- EClientUtilsAsyncOpData *async_data = user_data;
- gchar *capabilities = NULL;
- gboolean caps_res;
-
- g_return_if_fail (async_data != NULL);
- g_return_if_fail (async_data->client != NULL);
- g_return_if_fail (async_data->client == client);
-
- caps_res = e_client_retrieve_capabilities_finish (client, result, &capabilities, NULL);
- g_free (capabilities);
-
- if (caps_res) {
- async_data->pending_properties_count = 1;
-
- /* precache backend properties */
- if (E_IS_CAL_CLIENT (client)) {
- async_data->pending_properties_count += 3;
-
- e_client_get_backend_property (async_data->client, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, async_data->cancellable, client_utils_get_backend_property_cb, async_data);
- e_client_get_backend_property (async_data->client, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, async_data->cancellable, client_utils_get_backend_property_cb, async_data);
- e_client_get_backend_property (async_data->client, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT, async_data->cancellable, client_utils_get_backend_property_cb, async_data);
- } else if (E_IS_BOOK_CLIENT (client)) {
- async_data->pending_properties_count += 2;
-
- e_client_get_backend_property (async_data->client, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS, async_data->cancellable, client_utils_get_backend_property_cb, async_data);
- e_client_get_backend_property (async_data->client, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, async_data->cancellable, client_utils_get_backend_property_cb, async_data);
- } else {
- g_warn_if_reached ();
- client_utils_get_backend_property_cb (source_object, NULL, async_data);
- return;
- }
-
- e_client_get_backend_property (async_data->client, CLIENT_BACKEND_PROPERTY_CACHE_DIR, async_data->cancellable, client_utils_get_backend_property_cb, async_data);
- } else {
- client_utils_get_backend_property_cb (source_object, NULL, async_data);
- }
-}
-
-static void
-client_utils_open_new_done (EClientUtilsAsyncOpData *async_data)
-{
- g_return_if_fail (async_data != NULL);
- g_return_if_fail (async_data->client != NULL);
-
- /* retrieve capabilities just to have them cached on #EClient for later use */
- e_client_retrieve_capabilities (async_data->client, async_data->cancellable, client_utils_capabilities_retrieved_cb, async_data);
-}
-
-static gboolean client_utils_retry_open_timeout_cb (gpointer user_data);
-static void client_utils_opened_cb (EClient *client, const GError *error, EClientUtilsAsyncOpData *async_data);
-
-static void
-finish_or_retry_open (EClientUtilsAsyncOpData *async_data,
- const GError *error)
-{
- g_return_if_fail (async_data != NULL);
-
- if (error && g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_BUSY)) {
- /* postpone for 1/2 of a second, backend is busy now */
- async_data->open_finished = FALSE;
- async_data->retry_open_id = g_timeout_add (500, client_utils_retry_open_timeout_cb, async_data);
- } else if (error) {
- return_async_error (error, async_data->callback, async_data->user_data, async_data->source, e_client_utils_open_new);
- free_client_utils_async_op_data (async_data);
- } else {
- client_utils_open_new_done (async_data);
- }
-}
-
-static void
-client_utils_opened_cb (EClient *client,
- const GError *error,
- EClientUtilsAsyncOpData *async_data)
-{
- g_return_if_fail (client != NULL);
- g_return_if_fail (async_data != NULL);
- g_return_if_fail (client == async_data->client);
-
- g_signal_handlers_disconnect_by_func (client, G_CALLBACK (client_utils_opened_cb), async_data);
-
- if (!async_data->open_finished) {
- /* there can happen that the "opened" signal is received
- * before the e_client_open () is finished, thus keep detailed
- * error for later use, if any */
- if (error)
- async_data->opened_cb_error = g_error_copy (error);
- } else {
- finish_or_retry_open (async_data, error);
- }
-}
-
-static void
-client_utils_open_new_async_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- EClientUtilsAsyncOpData *async_data = user_data;
- GError *error = NULL;
-
- g_return_if_fail (source_object != NULL);
- g_return_if_fail (result != NULL);
- g_return_if_fail (async_data != NULL);
- g_return_if_fail (async_data->callback != NULL);
- g_return_if_fail (async_data->client == E_CLIENT (source_object));
-
- async_data->open_finished = TRUE;
-
- if (!e_client_open_finish (E_CLIENT (source_object), result, &error)
- || g_cancellable_set_error_if_cancelled (async_data->cancellable, &error)) {
- finish_or_retry_open (async_data, error);
- g_error_free (error);
- return;
- }
-
- if (async_data->opened_cb_error) {
- finish_or_retry_open (async_data, async_data->opened_cb_error);
- return;
- }
-
- if (e_client_is_opened (async_data->client)) {
- client_utils_open_new_done (async_data);
- return;
- }
-
- /* wait for 'opened' signal, which is received in client_utils_opened_cb */
-}
-
-static gboolean
-client_utils_retry_open_timeout_cb (gpointer user_data)
-{
- EClientUtilsAsyncOpData *async_data = user_data;
-
- g_return_val_if_fail (async_data != NULL, FALSE);
-
- g_signal_handlers_disconnect_matched (async_data->cancellable, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, async_data);
-
- /* reconnect to the signal */
- g_signal_connect (async_data->client, "opened", G_CALLBACK (client_utils_opened_cb), async_data);
-
- e_client_open (async_data->client, async_data->only_if_exists, async_data->cancellable, client_utils_open_new_async_cb, async_data);
-
- async_data->retry_open_id = 0;
-
- return FALSE;
-}
-
-/**
- * e_client_utils_open_new:
- * @source: an #ESource to be opened
- * @source_type: an #EClientSourceType of the @source
- * @only_if_exists: if %TRUE, fail if this client doesn't already exist, otherwise create it first
- * @cancellable: a #GCancellable; can be %NULL
- * @callback: callback to call when a result is ready
- * @user_data: user data for the @callback
- *
- * Begins asynchronous opening of a new #EClient corresponding
- * to the @source of type @source_type. The resulting #EClient
- * is fully opened and authenticated client, ready to be used.
- * The opened client has also fetched capabilities.
- * This call is finished by e_client_utils_open_new_finish()
- * from the @callback.
- *
- * Since: 3.2
- **/
-void
-e_client_utils_open_new (ESource *source,
- EClientSourceType source_type,
- gboolean only_if_exists,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- EClient *client;
- GError *error = NULL;
- EClientUtilsAsyncOpData *async_data;
-
- g_return_if_fail (callback != NULL);
- return_async_error_if_fail (source != NULL, callback, user_data, source, e_client_utils_open_new);
- return_async_error_if_fail (E_IS_SOURCE (source), callback, user_data, source, e_client_utils_open_new);
-
- client = e_client_utils_new (source, source_type, &error);
- if (!client) {
- return_async_error (error, callback, user_data, source, e_client_utils_open_new);
- g_error_free (error);
- return;
- }
-
- async_data = g_new0 (EClientUtilsAsyncOpData, 1);
- async_data->callback = callback;
- async_data->user_data = user_data;
- async_data->source = g_object_ref (source);
- async_data->client = client;
- async_data->open_finished = FALSE;
- async_data->only_if_exists = only_if_exists;
- async_data->retry_open_id = 0;
-
- if (cancellable)
- async_data->cancellable = g_object_ref (cancellable);
- else
- async_data->cancellable = g_cancellable_new ();
-
- /* wait till backend notifies about its opened state */
- g_signal_connect (client, "opened", G_CALLBACK (client_utils_opened_cb), async_data);
-
- e_client_open (async_data->client, async_data->only_if_exists, async_data->cancellable, client_utils_open_new_async_cb, async_data);
-}
-
-/**
- * e_client_utils_open_new_finish:
- * @source: an #ESource on which the e_client_utils_open_new() was invoked
- * @result: a #GAsyncResult
- * @client: (out): Return value for an #EClient
- * @error: (out): a #GError to set an error, if any
- *
- * Finishes previous call of e_client_utils_open_new() and
- * sets @client to a fully opened and authenticated #EClient.
- * This @client, if not NULL, should be freed with g_object_unref().
- *
- * Returns: %TRUE if successful, %FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_client_utils_open_new_finish (ESource *source,
- GAsyncResult *result,
- EClient **client,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (source != NULL, FALSE);
- g_return_val_if_fail (result != NULL, FALSE);
- g_return_val_if_fail (client != NULL, FALSE);
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (source), e_client_utils_open_new), FALSE);
-
- *client = NULL;
- simple = G_SIMPLE_ASYNC_RESULT (result);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return FALSE;
-
- *client = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-
- return *client != NULL;
-}
+++ /dev/null
-/*
- * e-client-utils.h
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- *
- * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
- *
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CLIENT_UTILS_H
-#define E_CLIENT_UTILS_H
-
-#include <gtk/gtk.h>
-#include <libedataserver/libedataserver.h>
-
-G_BEGIN_DECLS
-
-/**
- * EClientSourceType:
- *
- * Since: 3.2
- **/
-typedef enum {
- E_CLIENT_SOURCE_TYPE_CONTACTS,
- E_CLIENT_SOURCE_TYPE_EVENTS,
- E_CLIENT_SOURCE_TYPE_MEMOS,
- E_CLIENT_SOURCE_TYPE_TASKS,
- E_CLIENT_SOURCE_TYPE_LAST
-} EClientSourceType;
-
-EClient * e_client_utils_new (ESource *source,
- EClientSourceType source_type,
- GError **error);
-
-void e_client_utils_open_new (ESource *source,
- EClientSourceType source_type,
- gboolean only_if_exists,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean e_client_utils_open_new_finish (ESource *source,
- GAsyncResult *result,
- EClient **client,
- GError **error);
-
-G_END_DECLS
-
-#endif /* E_CLIENT_UTILS_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-contact-store.c - Contacts store with GtkTreeModel interface.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-
-#include "e-contact-store.h"
-
-#define ITER_IS_VALID(contact_store, iter) \
- ((iter)->stamp == (contact_store)->priv->stamp)
-#define ITER_GET(iter) \
- GPOINTER_TO_INT (iter->user_data)
-#define ITER_SET(contact_store, iter, index) \
- G_STMT_START { \
- (iter)->stamp = (contact_store)->priv->stamp; \
- (iter)->user_data = GINT_TO_POINTER (index); \
- } G_STMT_END
-
-#define E_CONTACT_STORE_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CONTACT_STORE, EContactStorePrivate))
-
-struct _EContactStorePrivate {
- gint stamp;
- EBookQuery *query;
- GArray *contact_sources;
-};
-
-/* Signals */
-
-enum {
- START_CLIENT_VIEW,
- STOP_CLIENT_VIEW,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-static void e_contact_store_tree_model_init (GtkTreeModelIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (
- EContactStore, e_contact_store, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, e_contact_store_tree_model_init))
-
-static GtkTreeModelFlags e_contact_store_get_flags (GtkTreeModel *tree_model);
-static gint e_contact_store_get_n_columns (GtkTreeModel *tree_model);
-static GType e_contact_store_get_column_type (GtkTreeModel *tree_model,
- gint index);
-static gboolean e_contact_store_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path);
-static GtkTreePath *e_contact_store_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static void e_contact_store_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value);
-static gboolean e_contact_store_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean e_contact_store_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent);
-static gboolean e_contact_store_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gint e_contact_store_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean e_contact_store_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n);
-static gboolean e_contact_store_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child);
-
-typedef struct
-{
- EBookClient *book_client;
-
- EBookClientView *client_view;
- GPtrArray *contacts;
-
- EBookClientView *client_view_pending;
- GPtrArray *contacts_pending;
-}
-ContactSource;
-
-static void free_contact_ptrarray (GPtrArray *contacts);
-static void clear_contact_source (EContactStore *contact_store, ContactSource *source);
-static void stop_view (EContactStore *contact_store, EBookClientView *view);
-
-static void
-contact_store_dispose (GObject *object)
-{
- EContactStorePrivate *priv;
- gint ii;
-
- priv = E_CONTACT_STORE_GET_PRIVATE (object);
-
- /* Free sources and cached contacts */
- for (ii = 0; ii < priv->contact_sources->len; ii++) {
- ContactSource *source;
-
- /* clear from back, because clear_contact_source can later access freed memory */
- source = &g_array_index (
- priv->contact_sources, ContactSource, priv->contact_sources->len - ii - 1);
-
- clear_contact_source (E_CONTACT_STORE (object), source);
- free_contact_ptrarray (source->contacts);
- g_object_unref (source->book_client);
- }
- g_array_set_size (priv->contact_sources, 0);
-
- if (priv->query != NULL) {
- e_book_query_unref (priv->query);
- priv->query = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_contact_store_parent_class)->dispose (object);
-}
-
-static void
-contact_store_finalize (GObject *object)
-{
- EContactStorePrivate *priv;
-
- priv = E_CONTACT_STORE_GET_PRIVATE (object);
-
- g_array_free (priv->contact_sources, TRUE);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_contact_store_parent_class)->finalize (object);
-}
-
-static void
-e_contact_store_class_init (EContactStoreClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (EContactStorePrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->dispose = contact_store_dispose;
- object_class->finalize = contact_store_finalize;
-
- signals[START_CLIENT_VIEW] = g_signal_new (
- "start-client-view",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EContactStoreClass, start_client_view),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- E_TYPE_BOOK_CLIENT_VIEW);
-
- signals[STOP_CLIENT_VIEW] = g_signal_new (
- "stop-client-view",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EContactStoreClass, stop_client_view),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- E_TYPE_BOOK_CLIENT_VIEW);
-}
-
-static void
-e_contact_store_tree_model_init (GtkTreeModelIface *iface)
-{
- iface->get_flags = e_contact_store_get_flags;
- iface->get_n_columns = e_contact_store_get_n_columns;
- iface->get_column_type = e_contact_store_get_column_type;
- iface->get_iter = e_contact_store_get_iter;
- iface->get_path = e_contact_store_get_path;
- iface->get_value = e_contact_store_get_value;
- iface->iter_next = e_contact_store_iter_next;
- iface->iter_children = e_contact_store_iter_children;
- iface->iter_has_child = e_contact_store_iter_has_child;
- iface->iter_n_children = e_contact_store_iter_n_children;
- iface->iter_nth_child = e_contact_store_iter_nth_child;
- iface->iter_parent = e_contact_store_iter_parent;
-}
-
-static void
-e_contact_store_init (EContactStore *contact_store)
-{
- GArray *contact_sources;
-
- contact_sources = g_array_new (FALSE, FALSE, sizeof (ContactSource));
-
- contact_store->priv = E_CONTACT_STORE_GET_PRIVATE (contact_store);
- contact_store->priv->stamp = g_random_int ();
- contact_store->priv->contact_sources = contact_sources;
-}
-
-/**
- * e_contact_store_new:
- *
- * Creates a new #EContactStore.
- *
- * Returns: A new #EContactStore.
- **/
-EContactStore *
-e_contact_store_new (void)
-{
- return g_object_new (E_TYPE_CONTACT_STORE, NULL);
-}
-
-/* ------------------ *
- * Row update helpers *
- * ------------------ */
-
-static void
-row_deleted (EContactStore *contact_store,
- gint n)
-{
- GtkTreePath *path;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, n);
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (contact_store), path);
- gtk_tree_path_free (path);
-}
-
-static void
-row_inserted (EContactStore *contact_store,
- gint n)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, n);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (contact_store), &iter, path))
- gtk_tree_model_row_inserted (GTK_TREE_MODEL (contact_store), path, &iter);
-
- gtk_tree_path_free (path);
-}
-
-static void
-row_changed (EContactStore *contact_store,
- gint n)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, n);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (contact_store), &iter, path))
- gtk_tree_model_row_changed (GTK_TREE_MODEL (contact_store), path, &iter);
-
- gtk_tree_path_free (path);
-}
-
-/* ---------------------- *
- * Contact source helpers *
- * ---------------------- */
-
-static gint
-find_contact_source_by_client (EContactStore *contact_store,
- EBookClient *book_client)
-{
- GArray *array;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- for (i = 0; i < array->len; i++) {
- ContactSource *source;
-
- source = &g_array_index (array, ContactSource, i);
- if (source->book_client == book_client)
- return i;
- }
-
- return -1;
-}
-
-static gint
-find_contact_source_by_view (EContactStore *contact_store,
- EBookClientView *client_view)
-{
- GArray *array;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- for (i = 0; i < array->len; i++) {
- ContactSource *source;
-
- source = &g_array_index (array, ContactSource, i);
- if (source->client_view == client_view ||
- source->client_view_pending == client_view)
- return i;
- }
-
- return -1;
-}
-
-static gint
-find_contact_source_by_offset (EContactStore *contact_store,
- gint offset)
-{
- GArray *array;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- for (i = 0; i < array->len; i++) {
- ContactSource *source;
-
- source = &g_array_index (array, ContactSource, i);
- if (source->contacts->len > offset)
- return i;
-
- offset -= source->contacts->len;
- }
-
- return -1;
-}
-
-static gint
-find_contact_source_by_pointer (EContactStore *contact_store,
- ContactSource *source)
-{
- GArray *array;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- i = ((gchar *) source - (gchar *) array->data) / sizeof (ContactSource);
-
- if (i < 0 || i >= array->len)
- return -1;
-
- return i;
-}
-
-static gint
-get_contact_source_offset (EContactStore *contact_store,
- gint contact_source_index)
-{
- GArray *array;
- gint offset = 0;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- g_assert (contact_source_index < array->len);
-
- for (i = 0; i < contact_source_index; i++) {
- ContactSource *source;
-
- source = &g_array_index (array, ContactSource, i);
- offset += source->contacts->len;
- }
-
- return offset;
-}
-
-static gint
-count_contacts (EContactStore *contact_store)
-{
- GArray *array;
- gint count = 0;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- for (i = 0; i < array->len; i++) {
- ContactSource *source;
-
- source = &g_array_index (array, ContactSource, i);
- count += source->contacts->len;
- }
-
- return count;
-}
-
-static gint
-find_contact_by_view_and_uid (EContactStore *contact_store,
- EBookClientView *find_view,
- const gchar *find_uid)
-{
- GArray *array;
- ContactSource *source;
- GPtrArray *contacts;
- gint source_index;
- gint i;
-
- g_return_val_if_fail (find_uid != NULL, -1);
-
- source_index = find_contact_source_by_view (contact_store, find_view);
- if (source_index < 0)
- return -1;
-
- array = contact_store->priv->contact_sources;
- source = &g_array_index (array, ContactSource, source_index);
-
- if (find_view == source->client_view)
- contacts = source->contacts; /* Current view */
- else
- contacts = source->contacts_pending; /* Pending view */
-
- for (i = 0; i < contacts->len; i++) {
- EContact *contact = g_ptr_array_index (contacts, i);
- const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
-
- if (uid && !strcmp (find_uid, uid))
- return i;
- }
-
- return -1;
-}
-
-static gint
-find_contact_by_uid (EContactStore *contact_store,
- const gchar *find_uid)
-{
- GArray *array;
- gint i;
-
- array = contact_store->priv->contact_sources;
-
- for (i = 0; i < array->len; i++) {
- ContactSource *source = &g_array_index (array, ContactSource, i);
- gint j;
-
- for (j = 0; j < source->contacts->len; j++) {
- EContact *contact = g_ptr_array_index (source->contacts, j);
- const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
-
- if (!strcmp (find_uid, uid))
- return get_contact_source_offset (contact_store, i) + j;
- }
- }
-
- return -1;
-}
-
-static EBookClient *
-get_book_at_row (EContactStore *contact_store,
- gint row)
-{
- GArray *array;
- ContactSource *source;
- gint source_index;
-
- source_index = find_contact_source_by_offset (contact_store, row);
- if (source_index < 0)
- return NULL;
-
- array = contact_store->priv->contact_sources;
- source = &g_array_index (array, ContactSource, source_index);
-
- return source->book_client;
-}
-
-static EContact *
-get_contact_at_row (EContactStore *contact_store,
- gint row)
-{
- GArray *array;
- ContactSource *source;
- gint source_index;
- gint offset;
-
- source_index = find_contact_source_by_offset (contact_store, row);
- if (source_index < 0)
- return NULL;
-
- array = contact_store->priv->contact_sources;
- source = &g_array_index (array, ContactSource, source_index);
- offset = get_contact_source_offset (contact_store, source_index);
- row -= offset;
-
- g_assert (row < source->contacts->len);
-
- return g_ptr_array_index (source->contacts, row);
-}
-
-static gboolean
-find_contact_source_details_by_view (EContactStore *contact_store,
- EBookClientView *client_view,
- ContactSource **contact_source,
- gint *offset)
-{
- GArray *array;
- gint source_index;
-
- source_index = find_contact_source_by_view (contact_store, client_view);
- if (source_index < 0)
- return FALSE;
-
- array = contact_store->priv->contact_sources;
- *contact_source = &g_array_index (array, ContactSource, source_index);
- *offset = get_contact_source_offset (contact_store, source_index);
-
- return TRUE;
-}
-
-/* ------------------------- *
- * EBookView signal handlers *
- * ------------------------- */
-
-static void
-view_contacts_added (EContactStore *contact_store,
- const GSList *contacts,
- EBookClientView *client_view)
-{
- ContactSource *source;
- gint offset;
- const GSList *l;
-
- if (!find_contact_source_details_by_view (contact_store, client_view, &source, &offset)) {
- g_warning ("EContactStore got 'contacts_added' signal from unknown EBookView!");
- return;
- }
-
- for (l = contacts; l; l = g_slist_next (l)) {
- EContact *contact = l->data;
-
- g_object_ref (contact);
-
- if (client_view == source->client_view) {
- /* Current view */
- g_ptr_array_add (source->contacts, contact);
- row_inserted (contact_store, offset + source->contacts->len - 1);
- } else {
- /* Pending view */
- g_ptr_array_add (source->contacts_pending, contact);
- }
- }
-}
-
-static void
-view_contacts_removed (EContactStore *contact_store,
- const GSList *uids,
- EBookClientView *client_view)
-{
- ContactSource *source;
- gint offset;
- const GSList *l;
-
- if (!find_contact_source_details_by_view (contact_store, client_view, &source, &offset)) {
- g_warning ("EContactStore got 'contacts_removed' signal from unknown EBookView!");
- return;
- }
-
- for (l = uids; l; l = g_slist_next (l)) {
- const gchar *uid = l->data;
- gint n = find_contact_by_view_and_uid (contact_store, client_view, uid);
- EContact *contact;
-
- if (n < 0) {
- g_warning ("EContactStore got 'contacts_removed' on unknown contact!");
- continue;
- }
-
- if (client_view == source->client_view) {
- /* Current view */
- contact = g_ptr_array_index (source->contacts, n);
- g_object_unref (contact);
- g_ptr_array_remove_index (source->contacts, n);
- row_deleted (contact_store, offset + n);
- } else {
- /* Pending view */
- contact = g_ptr_array_index (source->contacts_pending, n);
- g_object_unref (contact);
- g_ptr_array_remove_index (source->contacts_pending, n);
- }
- }
-}
-
-static void
-view_contacts_modified (EContactStore *contact_store,
- const GSList *contacts,
- EBookClientView *client_view)
-{
- GPtrArray *cached_contacts;
- ContactSource *source;
- gint offset;
- const GSList *l;
-
- if (!find_contact_source_details_by_view (contact_store, client_view, &source, &offset)) {
- g_warning ("EContactStore got 'contacts_changed' signal from unknown EBookView!");
- return;
- }
-
- if (client_view == source->client_view)
- cached_contacts = source->contacts;
- else
- cached_contacts = source->contacts_pending;
-
- for (l = contacts; l; l = g_slist_next (l)) {
- EContact *cached_contact;
- EContact *contact = l->data;
- const gchar *uid = e_contact_get_const (contact, E_CONTACT_UID);
- gint n = find_contact_by_view_and_uid (contact_store, client_view, uid);
-
- if (n < 0) {
- g_warning ("EContactStore got change notification on unknown contact!");
- continue;
- }
-
- cached_contact = g_ptr_array_index (cached_contacts, n);
-
- /* Update cached contact */
- if (cached_contact != contact) {
- g_object_unref (cached_contact);
- cached_contacts->pdata[n] = g_object_ref (contact);
- }
-
- /* Emit changes for current view only */
- if (client_view == source->client_view)
- row_changed (contact_store, offset + n);
- }
-}
-
-static void
-view_complete (EContactStore *contact_store,
- const GError *error,
- EBookClientView *client_view)
-{
- ContactSource *source;
- gint offset;
- gint i;
-
- if (!find_contact_source_details_by_view (contact_store, client_view, &source, &offset)) {
- g_warning ("EContactStore got 'complete' signal from unknown EBookClientView!");
- return;
- }
-
- /* If current view finished, do nothing */
- if (client_view == source->client_view) {
- stop_view (contact_store, source->client_view);
- return;
- }
-
- g_assert (client_view == source->client_view_pending);
-
- /* However, if it was a pending view, calculate and emit the differences between that
- * and the current view, and move the pending view up to current.
- *
- * This is O(m * n), and can be sped up with a temporary hash table if needed. */
-
- /* Deletions */
- for (i = 0; i < source->contacts->len; i++) {
- EContact *old_contact = g_ptr_array_index (source->contacts, i);
- const gchar *old_uid = e_contact_get_const (old_contact, E_CONTACT_UID);
- gint result;
-
- result = find_contact_by_view_and_uid (contact_store, source->client_view_pending, old_uid);
- if (result < 0) {
- /* Contact is not in new view; removed */
- g_object_unref (old_contact);
- g_ptr_array_remove_index (source->contacts, i);
- row_deleted (contact_store, offset + i);
- i--; /* Stay in place */
- }
- }
-
- /* Insertions */
- for (i = 0; i < source->contacts_pending->len; i++) {
- EContact *new_contact = g_ptr_array_index (source->contacts_pending, i);
- const gchar *new_uid = e_contact_get_const (new_contact, E_CONTACT_UID);
- gint result;
-
- result = find_contact_by_view_and_uid (contact_store, source->client_view, new_uid);
- if (result < 0) {
- /* Contact is not in old view; inserted */
- g_ptr_array_add (source->contacts, new_contact);
- row_inserted (contact_store, offset + source->contacts->len - 1);
- } else {
- /* Contact already in old view; drop the new one */
- g_object_unref (new_contact);
- }
- }
-
- /* Move pending view up to current */
- stop_view (contact_store, source->client_view);
- g_object_unref (source->client_view);
- source->client_view = source->client_view_pending;
- source->client_view_pending = NULL;
-
- /* Free array of pending contacts (members have been either moved or unreffed) */
- g_ptr_array_free (source->contacts_pending, TRUE);
- source->contacts_pending = NULL;
-}
-
-/* --------------------- *
- * View/Query management *
- * --------------------- */
-
-static void
-start_view (EContactStore *contact_store,
- EBookClientView *view)
-{
- g_signal_emit (contact_store, signals[START_CLIENT_VIEW], 0, view);
-
- g_signal_connect_swapped (
- view, "objects-added",
- G_CALLBACK (view_contacts_added), contact_store);
- g_signal_connect_swapped (
- view, "objects-removed",
- G_CALLBACK (view_contacts_removed), contact_store);
- g_signal_connect_swapped (
- view, "objects-modified",
- G_CALLBACK (view_contacts_modified), contact_store);
- g_signal_connect_swapped (
- view, "complete",
- G_CALLBACK (view_complete), contact_store);
-
- e_book_client_view_start (view, NULL);
-}
-
-static void
-stop_view (EContactStore *contact_store,
- EBookClientView *view)
-{
- e_book_client_view_stop (view, NULL);
-
- g_signal_handlers_disconnect_matched (
- view, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, contact_store);
-
- g_signal_emit (contact_store, signals[STOP_CLIENT_VIEW], 0, view);
-}
-
-static void
-clear_contact_ptrarray (GPtrArray *contacts)
-{
- gint i;
-
- for (i = 0; i < contacts->len; i++) {
- EContact *contact = g_ptr_array_index (contacts, i);
- g_object_unref (contact);
- }
-
- g_ptr_array_set_size (contacts, 0);
-}
-
-static void
-free_contact_ptrarray (GPtrArray *contacts)
-{
- clear_contact_ptrarray (contacts);
- g_ptr_array_free (contacts, TRUE);
-}
-
-static void
-clear_contact_source (EContactStore *contact_store,
- ContactSource *source)
-{
- gint source_index;
- gint offset;
-
- source_index = find_contact_source_by_pointer (contact_store, source);
- g_assert (source_index >= 0);
-
- offset = get_contact_source_offset (contact_store, source_index);
- g_assert (offset >= 0);
-
- /* Inform listeners that contacts went away */
-
- if (source->contacts && source->contacts->len > 0) {
- GtkTreePath *path = gtk_tree_path_new ();
- gint i;
-
- gtk_tree_path_append_index (path, source->contacts->len);
-
- for (i = source->contacts->len - 1; i >= 0; i--) {
- EContact *contact = g_ptr_array_index (source->contacts, i);
-
- g_object_unref (contact);
- g_ptr_array_remove_index_fast (source->contacts, i);
-
- gtk_tree_path_prev (path);
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (contact_store), path);
- }
-
- gtk_tree_path_free (path);
- }
-
- /* Free main and pending views, clear cached contacts */
-
- if (source->client_view) {
- stop_view (contact_store, source->client_view);
- g_object_unref (source->client_view);
-
- source->client_view = NULL;
- }
-
- if (source->client_view_pending) {
- stop_view (contact_store, source->client_view_pending);
- g_object_unref (source->client_view_pending);
- free_contact_ptrarray (source->contacts_pending);
-
- source->client_view_pending = NULL;
- source->contacts_pending = NULL;
- }
-}
-
-static void
-client_view_ready_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- EContactStore *contact_store = user_data;
- gint source_idx;
- EBookClient *book_client;
- EBookClientView *client_view = NULL;
-
- g_return_if_fail (contact_store != NULL);
- g_return_if_fail (source_object != NULL);
-
- book_client = E_BOOK_CLIENT (source_object);
- g_return_if_fail (book_client != NULL);
-
- if (!e_book_client_get_view_finish (book_client, result, &client_view, NULL))
- client_view = NULL;
-
- source_idx = find_contact_source_by_client (contact_store, book_client);
- if (source_idx >= 0) {
- ContactSource *source;
-
- source = &g_array_index (contact_store->priv->contact_sources, ContactSource, source_idx);
-
- if (source->client_view) {
- if (source->client_view_pending) {
- stop_view (contact_store, source->client_view_pending);
- g_object_unref (source->client_view_pending);
- free_contact_ptrarray (source->contacts_pending);
- }
-
- source->client_view_pending = client_view;
-
- if (source->client_view_pending) {
- source->contacts_pending = g_ptr_array_new ();
- start_view (contact_store, client_view);
- } else {
- source->contacts_pending = NULL;
- }
- } else {
- source->client_view = client_view;
-
- if (source->client_view) {
- start_view (contact_store, client_view);
- }
- }
- }
-
- g_object_unref (contact_store);
-}
-
-static void
-query_contact_source (EContactStore *contact_store,
- ContactSource *source)
-{
- gboolean is_opened;
-
- g_assert (source->book_client != NULL);
-
- if (!contact_store->priv->query) {
- clear_contact_source (contact_store, source);
- return;
- }
-
- is_opened = e_client_is_opened (E_CLIENT (source->book_client));
-
- if (source->client_view) {
- if (source->client_view_pending) {
- stop_view (contact_store, source->client_view_pending);
- g_object_unref (source->client_view_pending);
- free_contact_ptrarray (source->contacts_pending);
- source->client_view_pending = NULL;
- source->contacts_pending = NULL;
- }
- }
-
- if (is_opened) {
- gchar *query_str;
-
- query_str = e_book_query_to_string (contact_store->priv->query);
- e_book_client_get_view (source->book_client, query_str, NULL, client_view_ready_cb, g_object_ref (contact_store));
- g_free (query_str);
- }
-}
-
-/* ----------------- *
- * EContactStore API *
- * ----------------- */
-
-/**
- * e_contact_store_get_client:
- * @contact_store: an #EContactStore
- * @iter: a #GtkTreeIter from @contact_store
- *
- * Gets the #EBookClient that provided the contact at @iter.
- *
- * Returns: An #EBookClient.
- *
- * Since: 3.2
- **/
-EBookClient *
-e_contact_store_get_client (EContactStore *contact_store,
- GtkTreeIter *iter)
-{
- gint index;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (contact_store), NULL);
- g_return_val_if_fail (ITER_IS_VALID (contact_store, iter), NULL);
-
- index = ITER_GET (iter);
-
- return get_book_at_row (contact_store, index);
-}
-
-/**
- * e_contact_store_get_contact:
- * @contact_store: an #EContactStore
- * @iter: a #GtkTreeIter from @contact_store
- *
- * Gets the #EContact at @iter.
- *
- * Returns: An #EContact.
- **/
-EContact *
-e_contact_store_get_contact (EContactStore *contact_store,
- GtkTreeIter *iter)
-{
- gint index;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (contact_store), NULL);
- g_return_val_if_fail (ITER_IS_VALID (contact_store, iter), NULL);
-
- index = ITER_GET (iter);
-
- return get_contact_at_row (contact_store, index);
-}
-
-/**
- * e_contact_store_find_contact:
- * @contact_store: an #EContactStore
- * @uid: a unique contact identifier
- * @iter: a destination #GtkTreeIter to set
- *
- * Sets @iter to point to the contact row matching @uid.
- *
- * Returns: %TRUE if the contact was found, and @iter was set. %FALSE otherwise.
- **/
-gboolean
-e_contact_store_find_contact (EContactStore *contact_store,
- const gchar *uid,
- GtkTreeIter *iter)
-{
- gint index;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (contact_store), FALSE);
- g_return_val_if_fail (uid != NULL, FALSE);
-
- index = find_contact_by_uid (contact_store, uid);
- if (index < 0)
- return FALSE;
-
- ITER_SET (contact_store, iter, index);
- return TRUE;
-}
-
-/**
- * e_contact_store_get_clients:
- * @contact_store: an #EContactStore
- *
- * Gets the list of book clients that provide contacts for @contact_store.
- *
- * Returns: A #GSList of pointers to #EBookClient. The caller owns the list,
- * but not the book clients.
- *
- * Since: 3.2
- **/
-GSList *
-e_contact_store_get_clients (EContactStore *contact_store)
-{
- GArray *array;
- GSList *client_list = NULL;
- gint i;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (contact_store), NULL);
-
- array = contact_store->priv->contact_sources;
-
- for (i = 0; i < array->len; i++) {
- ContactSource *source;
-
- source = &g_array_index (array, ContactSource, i);
- client_list = g_slist_prepend (client_list, source->book_client);
- }
-
- return client_list;
-}
-
-/**
- * e_contact_store_add_client:
- * @contact_store: an #EContactStore
- * @book_client: an #EBookClient
- *
- * Adds @book_client to the list of book clients that provide contacts for @contact_store.
- * The @contact_store adds a reference to @book_client, if added.
- *
- * Since: 3.2
- **/
-void
-e_contact_store_add_client (EContactStore *contact_store,
- EBookClient *book_client)
-{
- GArray *array;
- ContactSource source;
- ContactSource *indexed_source;
-
- g_return_if_fail (E_IS_CONTACT_STORE (contact_store));
- g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
-
- if (find_contact_source_by_client (contact_store, book_client) >= 0) {
- g_warning ("Same book client added more than once to EContactStore!");
- return;
- }
-
- array = contact_store->priv->contact_sources;
-
- memset (&source, 0, sizeof (ContactSource));
- source.book_client = g_object_ref (book_client);
- source.contacts = g_ptr_array_new ();
- g_array_append_val (array, source);
-
- indexed_source = &g_array_index (array, ContactSource, array->len - 1);
-
- query_contact_source (contact_store, indexed_source);
-}
-
-/**
- * e_contact_store_remove_client:
- * @contact_store: an #EContactStore
- * @book_client: an #EBookClient
- *
- * Removes @book from the list of book clients that provide contacts for @contact_store.
- *
- * Since: 3.2
- **/
-void
-e_contact_store_remove_client (EContactStore *contact_store,
- EBookClient *book_client)
-{
- GArray *array;
- ContactSource *source;
- gint source_index;
-
- g_return_if_fail (E_IS_CONTACT_STORE (contact_store));
- g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
-
- source_index = find_contact_source_by_client (contact_store, book_client);
- if (source_index < 0) {
- g_warning ("Tried to remove unknown book client from EContactStore!");
- return;
- }
-
- array = contact_store->priv->contact_sources;
-
- source = &g_array_index (array, ContactSource, source_index);
- clear_contact_source (contact_store, source);
- free_contact_ptrarray (source->contacts);
- g_object_unref (book_client);
-
- g_array_remove_index (array, source_index); /* Preserve order */
-}
-
-/**
- * e_contact_store_set_query:
- * @contact_store: an #EContactStore
- * @book_query: an #EBookQuery
- *
- * Sets @book_query to be the query used to fetch contacts from the books
- * assigned to @contact_store.
- **/
-void
-e_contact_store_set_query (EContactStore *contact_store,
- EBookQuery *book_query)
-{
- GArray *array;
- gint i;
-
- g_return_if_fail (E_IS_CONTACT_STORE (contact_store));
-
- if (book_query == contact_store->priv->query)
- return;
-
- if (contact_store->priv->query)
- e_book_query_unref (contact_store->priv->query);
-
- contact_store->priv->query = book_query;
- if (book_query)
- e_book_query_ref (book_query);
-
- /* Query books */
- array = contact_store->priv->contact_sources;
- for (i = 0; i < array->len; i++) {
- ContactSource *contact_source;
-
- contact_source = &g_array_index (array, ContactSource, i);
- query_contact_source (contact_store, contact_source);
- }
-}
-
-/**
- * e_contact_store_peek_query:
- * @contact_store: an #EContactStore
- *
- * Gets the query that's being used to fetch contacts from the books
- * assigned to @contact_store.
- *
- * Returns: The #EBookQuery being used.
- **/
-EBookQuery *
-e_contact_store_peek_query (EContactStore *contact_store)
-{
- g_return_val_if_fail (E_IS_CONTACT_STORE (contact_store), NULL);
-
- return contact_store->priv->query;
-}
-
-/* ---------------- *
- * GtkTreeModel API *
- * ---------------- */
-
-static GtkTreeModelFlags
-e_contact_store_get_flags (GtkTreeModel *tree_model)
-{
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), 0);
-
- return GTK_TREE_MODEL_LIST_ONLY;
-}
-
-static gint
-e_contact_store_get_n_columns (GtkTreeModel *tree_model)
-{
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), 0);
-
- return E_CONTACT_FIELD_LAST;
-}
-
-static GType
-get_column_type (EContactStore *contact_store,
- gint column)
-{
- const gchar *field_name;
- GObjectClass *contact_class;
- GParamSpec *param_spec;
- GType value_type;
-
- /* Silently suppress requests for columns lower than the first EContactField.
- * GtkTreeView automatically queries the type of all columns up to the maximum
- * provided, and we have to return a valid value type, so let it be a generic
- * pointer. */
- if (column < E_CONTACT_FIELD_FIRST) {
- return G_TYPE_POINTER;
- }
-
- field_name = e_contact_field_name (column);
- contact_class = g_type_class_ref (E_TYPE_CONTACT);
- param_spec = g_object_class_find_property (contact_class, field_name);
- value_type = G_PARAM_SPEC_VALUE_TYPE (param_spec);
- g_type_class_unref (contact_class);
-
- return value_type;
-}
-
-static GType
-e_contact_store_get_column_type (GtkTreeModel *tree_model,
- gint index)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), G_TYPE_INVALID);
- g_return_val_if_fail (index >= 0 && index < E_CONTACT_FIELD_LAST, G_TYPE_INVALID);
-
- return get_column_type (contact_store, index);
-}
-
-static gboolean
-e_contact_store_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
- gint index;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
- g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
-
- index = gtk_tree_path_get_indices (path)[0];
- if (index >= count_contacts (contact_store))
- return FALSE;
-
- ITER_SET (contact_store, iter, index);
- return TRUE;
-}
-
-static GtkTreePath *
-e_contact_store_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
- GtkTreePath *path;
- gint index;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), NULL);
- g_return_val_if_fail (ITER_IS_VALID (contact_store, iter), NULL);
-
- index = ITER_GET (iter);
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, index);
-
- return path;
-}
-
-static gboolean
-e_contact_store_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
- gint index;
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
- g_return_val_if_fail (ITER_IS_VALID (contact_store, iter), FALSE);
-
- index = ITER_GET (iter);
-
- if (index + 1 < count_contacts (contact_store)) {
- ITER_SET (contact_store, iter, index + 1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-e_contact_store_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
-
- /* This is a list, nodes have no children. */
- if (parent)
- return FALSE;
-
- /* But if parent == NULL we return the list itself as children of the root. */
- if (count_contacts (contact_store) <= 0)
- return FALSE;
-
- ITER_SET (contact_store, iter, 0);
- return TRUE;
-}
-
-static gboolean
-e_contact_store_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
-
- if (iter == NULL)
- return TRUE;
-
- return FALSE;
-}
-
-static gint
-e_contact_store_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), -1);
-
- if (iter == NULL)
- return count_contacts (contact_store);
-
- g_return_val_if_fail (ITER_IS_VALID (contact_store, iter), -1);
- return 0;
-}
-
-static gboolean
-e_contact_store_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_CONTACT_STORE (tree_model), FALSE);
-
- if (parent)
- return FALSE;
-
- if (n < count_contacts (contact_store)) {
- ITER_SET (contact_store, iter, n);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-e_contact_store_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child)
-{
- return FALSE;
-}
-
-static void
-e_contact_store_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value)
-{
- EContactStore *contact_store = E_CONTACT_STORE (tree_model);
- EContact *contact;
- const gchar *field_name;
- gint row;
-
- g_return_if_fail (E_IS_CONTACT_STORE (tree_model));
- g_return_if_fail (column < E_CONTACT_FIELD_LAST);
- g_return_if_fail (ITER_IS_VALID (contact_store, iter));
-
- g_value_init (value, get_column_type (contact_store, column));
-
- row = ITER_GET (iter);
- contact = get_contact_at_row (contact_store, row);
- if (!contact || column < E_CONTACT_FIELD_FIRST)
- return;
-
- field_name = e_contact_field_name (column);
- g_object_get_property (G_OBJECT (contact), field_name, value);
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-contact-store.h - Contacts store with GtkTreeModel interface.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_CONTACT_STORE_H
-#define E_CONTACT_STORE_H
-
-#include <gtk/gtk.h>
-#include <libebook/libebook.h>
-
-/* Standard GObject macros */
-#define E_TYPE_CONTACT_STORE \
- (e_contact_store_get_type ())
-#define E_CONTACT_STORE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_CONTACT_STORE, EContactStore))
-#define E_CONTACT_STORE_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_CONTACT_STORE, EContactStoreClass))
-#define E_IS_CONTACT_STORE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_CONTACT_STORE))
-#define E_IS_CONTACT_STORE_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_CONTACT_STORE))
-#define E_CONTACT_STORE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_CONTACT_STORE, EContactStoreClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EContactStore EContactStore;
-typedef struct _EContactStoreClass EContactStoreClass;
-typedef struct _EContactStorePrivate EContactStorePrivate;
-
-struct _EContactStore {
- GObject parent;
- EContactStorePrivate *priv;
-};
-
-struct _EContactStoreClass {
- GObjectClass parent_class;
-
- /* signals */
- void (*start_client_view) (EContactStore *contact_store, EBookClientView *client_view);
- void (*stop_client_view) (EContactStore *contact_store, EBookClientView *client_view);
-};
-
-GType e_contact_store_get_type (void);
-EContactStore * e_contact_store_new (void);
-
-EBookClient * e_contact_store_get_client (EContactStore *contact_store,
- GtkTreeIter *iter);
-EContact * e_contact_store_get_contact (EContactStore *contact_store,
- GtkTreeIter *iter);
-gboolean e_contact_store_find_contact (EContactStore *contact_store,
- const gchar *uid,
- GtkTreeIter *iter);
-
-/* Returns a shallow copy; free the list when done, but don't unref elements */
-GSList * e_contact_store_get_clients (EContactStore *contact_store);
-void e_contact_store_add_client (EContactStore *contact_store,
- EBookClient *book_client);
-void e_contact_store_remove_client (EContactStore *contact_store,
- EBookClient *book_client);
-void e_contact_store_set_query (EContactStore *contact_store,
- EBookQuery *book_query);
-EBookQuery * e_contact_store_peek_query (EContactStore *contact_store);
-
-G_END_DECLS
-
-#endif /* E_CONTACT_STORE_H */
+++ /dev/null
-BOOLEAN:OBJECT,BOXED
-BOOLEAN:BOXED,OBJECT,FLAGS,UINT
-NONE:STRING,BOOLEAN
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-destination-store.c - EDestination store with GtkTreeModel interface.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-
-#include "e-destination-store.h"
-
-#define ITER_IS_VALID(destination_store, iter) \
- ((iter)->stamp == (destination_store)->priv->stamp)
-#define ITER_GET(iter) \
- GPOINTER_TO_INT (iter->user_data)
-#define ITER_SET(destination_store, iter, index) \
- G_STMT_START { \
- (iter)->stamp = (destination_store)->priv->stamp; \
- (iter)->user_data = GINT_TO_POINTER (index); \
- } G_STMT_END
-
-#define E_DESTINATION_STORE_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_DESTINATION_STORE, EDestinationStorePrivate))
-
-struct _EDestinationStorePrivate {
- GPtrArray *destinations;
- gint stamp;
-};
-
-static GType column_types[E_DESTINATION_STORE_NUM_COLUMNS];
-
-static void e_destination_store_tree_model_init (GtkTreeModelIface *iface);
-
-G_DEFINE_TYPE_EXTENDED (
- EDestinationStore, e_destination_store, G_TYPE_OBJECT, 0,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, e_destination_store_tree_model_init);
- column_types[E_DESTINATION_STORE_COLUMN_NAME] = G_TYPE_STRING;
- column_types[E_DESTINATION_STORE_COLUMN_EMAIL] = G_TYPE_STRING;
- column_types[E_DESTINATION_STORE_COLUMN_ADDRESS] = G_TYPE_STRING;
-)
-
-static GtkTreeModelFlags e_destination_store_get_flags (GtkTreeModel *tree_model);
-static gint e_destination_store_get_n_columns (GtkTreeModel *tree_model);
-static GType e_destination_store_get_column_type (GtkTreeModel *tree_model,
- gint index);
-static gboolean e_destination_store_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path);
-static void e_destination_store_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value);
-static gboolean e_destination_store_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean e_destination_store_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent);
-static gboolean e_destination_store_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gint e_destination_store_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean e_destination_store_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n);
-static gboolean e_destination_store_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child);
-
-static void destination_changed (EDestinationStore *destination_store, EDestination *destination);
-static void stop_destination (EDestinationStore *destination_store, EDestination *destination);
-
-static void
-destination_store_dispose (GObject *object)
-{
- EDestinationStorePrivate *priv;
- gint ii;
-
- priv = E_DESTINATION_STORE_GET_PRIVATE (object);
-
- for (ii = 0; ii < priv->destinations->len; ii++) {
- EDestination *destination;
-
- destination = g_ptr_array_index (priv->destinations, ii);
- stop_destination (E_DESTINATION_STORE (object), destination);
- g_object_unref (destination);
- }
- g_ptr_array_set_size (priv->destinations, 0);
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_destination_store_parent_class)->dispose (object);
-}
-
-static void
-destination_store_finalize (GObject *object)
-{
- EDestinationStorePrivate *priv;
-
- priv = E_DESTINATION_STORE_GET_PRIVATE (object);
-
- g_ptr_array_free (priv->destinations, TRUE);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_destination_store_parent_class)->finalize (object);
-}
-
-static void
-e_destination_store_class_init (EDestinationStoreClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (EDestinationStorePrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->dispose = destination_store_dispose;
- object_class->finalize = destination_store_finalize;
-}
-
-static void
-e_destination_store_tree_model_init (GtkTreeModelIface *iface)
-{
- iface->get_flags = e_destination_store_get_flags;
- iface->get_n_columns = e_destination_store_get_n_columns;
- iface->get_column_type = e_destination_store_get_column_type;
- iface->get_iter = e_destination_store_get_iter;
- iface->get_path = e_destination_store_get_path;
- iface->get_value = e_destination_store_get_value;
- iface->iter_next = e_destination_store_iter_next;
- iface->iter_children = e_destination_store_iter_children;
- iface->iter_has_child = e_destination_store_iter_has_child;
- iface->iter_n_children = e_destination_store_iter_n_children;
- iface->iter_nth_child = e_destination_store_iter_nth_child;
- iface->iter_parent = e_destination_store_iter_parent;
-}
-
-static void
-e_destination_store_init (EDestinationStore *destination_store)
-{
- destination_store->priv =
- E_DESTINATION_STORE_GET_PRIVATE (destination_store);
-
- destination_store->priv->destinations = g_ptr_array_new ();
- destination_store->priv->stamp = g_random_int ();
-}
-
-/**
- * e_destination_store_new:
- *
- * Creates a new #EDestinationStore.
- *
- * Returns: A new #EDestinationStore.
- **/
-EDestinationStore *
-e_destination_store_new (void)
-{
- return g_object_new (E_TYPE_DESTINATION_STORE, NULL);
-}
-
-/* ------------------ *
- * Row update helpers *
- * ------------------ */
-
-static void
-row_deleted (EDestinationStore *destination_store,
- gint n)
-{
- GtkTreePath *path;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, n);
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (destination_store), path);
- gtk_tree_path_free (path);
-}
-
-static void
-row_inserted (EDestinationStore *destination_store,
- gint n)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, n);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (destination_store), &iter, path))
- gtk_tree_model_row_inserted (GTK_TREE_MODEL (destination_store), path, &iter);
-
- gtk_tree_path_free (path);
-}
-
-static void
-row_changed (EDestinationStore *destination_store,
- gint n)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, n);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (destination_store), &iter, path))
- gtk_tree_model_row_changed (GTK_TREE_MODEL (destination_store), path, &iter);
-
- gtk_tree_path_free (path);
-}
-
-/* ------------------- *
- * Destination helpers *
- * ------------------- */
-
-static gint
-find_destination_by_pointer (EDestinationStore *destination_store,
- EDestination *destination)
-{
- GPtrArray *array;
- gint i;
-
- array = destination_store->priv->destinations;
-
- for (i = 0; i < array->len; i++) {
- EDestination *destination_here;
-
- destination_here = g_ptr_array_index (array, i);
-
- if (destination_here == destination)
- return i;
- }
-
- return -1;
-}
-
-static gint
-find_destination_by_email (EDestinationStore *destination_store,
- EDestination *destination)
-{
- GPtrArray *array;
- gint i;
- const gchar *e_mail = e_destination_get_email (destination);
-
- array = destination_store->priv->destinations;
-
- for (i = 0; i < array->len; i++) {
- EDestination *destination_here;
- const gchar *mail;
-
- destination_here = g_ptr_array_index (array, i);
- mail = e_destination_get_email (destination_here);
-
- if (g_str_equal (e_mail, mail))
- return i;
- }
-
- return -1;
-}
-
-static void
-start_destination (EDestinationStore *destination_store,
- EDestination *destination)
-{
- g_signal_connect_swapped (
- destination, "changed",
- G_CALLBACK (destination_changed), destination_store);
-}
-
-static void
-stop_destination (EDestinationStore *destination_store,
- EDestination *destination)
-{
- g_signal_handlers_disconnect_matched (
- destination, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, destination_store);
-}
-
-/* --------------- *
- * Signal handlers *
- * --------------- */
-
-static void
-destination_changed (EDestinationStore *destination_store,
- EDestination *destination)
-{
- gint n;
-
- n = find_destination_by_pointer (destination_store, destination);
- if (n < 0) {
- g_warning ("EDestinationStore got change from unknown EDestination!");
- return;
- }
-
- row_changed (destination_store, n);
-}
-
-/* --------------------- *
- * EDestinationStore API *
- * --------------------- */
-
-/**
- * e_destination_store_get_destination:
- * @destination_store: an #EDestinationStore
- * @iter: a #GtkTreeIter
- *
- * Gets the #EDestination from @destination_store at @iter.
- *
- * Returns: An #EDestination.
- **/
-EDestination *
-e_destination_store_get_destination (EDestinationStore *destination_store,
- GtkTreeIter *iter)
-{
- GPtrArray *array;
- gint index;
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (destination_store), NULL);
- g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), NULL);
-
- array = destination_store->priv->destinations;
- index = ITER_GET (iter);
-
- return g_ptr_array_index (array, index);
-}
-
-/**
- * e_destination_store_list_destinations:
- * @destination_store: an #EDestinationStore
- *
- * Gets a list of all the #EDestinations in @destination_store.
- *
- * Returns: A #GList of pointers to #EDestination. The list is owned
- * by the caller, but the #EDestination elements aren't.
- **/
-GList *
-e_destination_store_list_destinations (EDestinationStore *destination_store)
-{
- GList *destination_list = NULL;
- GPtrArray *array;
- gint i;
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (destination_store), NULL);
-
- array = destination_store->priv->destinations;
-
- for (i = 0; i < array->len; i++) {
- EDestination *destination;
-
- destination = g_ptr_array_index (array, i);
- destination_list = g_list_prepend (destination_list, destination);
- }
-
- destination_list = g_list_reverse (destination_list);
-
- return destination_list;
-}
-
-/**
- * e_destination_store_insert_destination:
- * @destination_store: an #EDestinationStore
- * @index: the index at which to insert
- * @destination: an #EDestination to insert
- *
- * Inserts @destination into @destination_store at the position
- * indicated by @index. @destination_store will ref @destination.
- **/
-void
-e_destination_store_insert_destination (EDestinationStore *destination_store,
- gint index,
- EDestination *destination)
-{
- GPtrArray *array;
-
- g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
- g_return_if_fail (index >= 0);
-
- if (find_destination_by_pointer (destination_store, destination) >= 0) {
- g_warning ("Same destination added more than once to EDestinationStore!");
- return;
- }
-
- g_object_ref (destination);
-
- array = destination_store->priv->destinations;
- index = MIN (index, array->len);
-
- g_ptr_array_set_size (array, array->len + 1);
-
- if (array->len - 1 - index > 0) {
- memmove (
- array->pdata + index + 1,
- array->pdata + index,
- (array->len - 1 - index) * sizeof (gpointer));
- }
-
- array->pdata[index] = destination;
- start_destination (destination_store, destination);
- row_inserted (destination_store, index);
-}
-
-/**
- * e_destination_store_append_destination:
- * @destination_store: an #EDestinationStore
- * @destination: an #EDestination
- *
- * Appends @destination to the list of destinations in @destination_store.
- * @destination_store will ref @destination.
- **/
-void
-e_destination_store_append_destination (EDestinationStore *destination_store,
- EDestination *destination)
-{
- GPtrArray *array;
-
- g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
-
- if (find_destination_by_email (destination_store, destination) >= 0 && !e_destination_is_evolution_list (destination)) {
- g_warning ("Same destination added more than once to EDestinationStore!");
- return;
- }
-
- array = destination_store->priv->destinations;
- g_object_ref (destination);
-
- g_ptr_array_add (array, destination);
- start_destination (destination_store, destination);
- row_inserted (destination_store, array->len - 1);
-}
-
-/**
- * e_destination_store_remove_destination:
- * @destination_store: an #EDestinationStore
- * @destination: an #EDestination to remove
- *
- * Removes @destination from @destination_store. @destination_store will
- * unref @destination.
- **/
-void
-e_destination_store_remove_destination (EDestinationStore *destination_store,
- EDestination *destination)
-{
- GPtrArray *array;
- gint n;
-
- g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
-
- n = find_destination_by_pointer (destination_store, destination);
- if (n < 0) {
- g_warning ("Tried to remove unknown destination from EDestinationStore!");
- return;
- }
-
- stop_destination (destination_store, destination);
- g_object_unref (destination);
-
- array = destination_store->priv->destinations;
- g_ptr_array_remove_index (array, n);
- row_deleted (destination_store, n);
-}
-
-void
-e_destination_store_remove_destination_nth (EDestinationStore *destination_store,
- gint n)
-{
- EDestination *destination;
- GPtrArray *array;
-
- g_return_if_fail (n >= 0);
-
- array = destination_store->priv->destinations;
- destination = g_ptr_array_index (array, n);
- stop_destination (destination_store, destination);
- g_object_unref (destination);
-
- g_ptr_array_remove_index (array, n);
- row_deleted (destination_store, n);
-}
-
-guint
-e_destination_store_get_destination_count (EDestinationStore *destination_store)
-{
- return destination_store->priv->destinations->len;
-}
-
-/* ---------------- *
- * GtkTreeModel API *
- * ---------------- */
-
-static GtkTreeModelFlags
-e_destination_store_get_flags (GtkTreeModel *tree_model)
-{
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), 0);
-
- return GTK_TREE_MODEL_LIST_ONLY;
-}
-
-static gint
-e_destination_store_get_n_columns (GtkTreeModel *tree_model)
-{
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), 0);
-
- return E_CONTACT_FIELD_LAST;
-}
-
-static GType
-e_destination_store_get_column_type (GtkTreeModel *tree_model,
- gint index)
-{
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), G_TYPE_INVALID);
- g_return_val_if_fail (index >= 0 && index < E_DESTINATION_STORE_NUM_COLUMNS, G_TYPE_INVALID);
-
- return column_types[index];
-}
-
-static gboolean
-e_destination_store_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path)
-{
- EDestinationStore *destination_store;
- GPtrArray *array;
- gint index;
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
- g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
-
- destination_store = E_DESTINATION_STORE (tree_model);
-
- index = gtk_tree_path_get_indices (path)[0];
- array = destination_store->priv->destinations;
-
- if (index >= array->len)
- return FALSE;
-
- ITER_SET (destination_store, iter, index);
- return TRUE;
-}
-
-GtkTreePath *
-e_destination_store_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
- GtkTreePath *path;
- gint index;
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), NULL);
- g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), NULL);
-
- index = ITER_GET (iter);
- path = gtk_tree_path_new ();
- gtk_tree_path_append_index (path, index);
-
- return path;
-}
-
-static gboolean
-e_destination_store_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
- gint index;
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
- g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), FALSE);
-
- index = ITER_GET (iter);
-
- if (index + 1 < destination_store->priv->destinations->len) {
- ITER_SET (destination_store, iter, index + 1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-e_destination_store_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
-
- /* This is a list, nodes have no children. */
- if (parent)
- return FALSE;
-
- /* But if parent == NULL we return the list itself as children of the root. */
- if (destination_store->priv->destinations->len <= 0)
- return FALSE;
-
- ITER_SET (destination_store, iter, 0);
- return TRUE;
-}
-
-static gboolean
-e_destination_store_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
-
- if (iter == NULL)
- return TRUE;
-
- return FALSE;
-}
-
-static gint
-e_destination_store_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), -1);
-
- if (iter == NULL)
- return destination_store->priv->destinations->len;
-
- g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), -1);
- return 0;
-}
-
-static gboolean
-e_destination_store_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
-
- g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
-
- if (parent)
- return FALSE;
-
- if (n < destination_store->priv->destinations->len) {
- ITER_SET (destination_store, iter, n);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-e_destination_store_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child)
-{
- return FALSE;
-}
-
-static void
-e_destination_store_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
- EDestination *destination;
- GString *string_new;
- EContact *contact;
- GPtrArray *array;
- const gchar *string;
- gint row;
-
- g_return_if_fail (E_IS_DESTINATION_STORE (tree_model));
- g_return_if_fail (column < E_DESTINATION_STORE_NUM_COLUMNS);
- g_return_if_fail (ITER_IS_VALID (destination_store, iter));
-
- g_value_init (value, column_types[column]);
-
- array = destination_store->priv->destinations;
-
- row = ITER_GET (iter);
- if (row >= array->len)
- return;
-
- destination = g_ptr_array_index (array, row);
- g_assert (destination);
-
- switch (column) {
- case E_DESTINATION_STORE_COLUMN_NAME:
- string = e_destination_get_name (destination);
- g_value_set_string (value, string);
- break;
-
- case E_DESTINATION_STORE_COLUMN_EMAIL:
- string = e_destination_get_email (destination);
- g_value_set_string (value, string);
- break;
-
- case E_DESTINATION_STORE_COLUMN_ADDRESS:
- contact = e_destination_get_contact (destination);
- if (contact && E_IS_CONTACT (contact)) {
- if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
- string = e_destination_get_name (destination);
- string_new = g_string_new (string);
- string_new = g_string_append (string_new, " mailing list");
- g_value_set_string (value, string_new->str);
- g_string_free (string_new, TRUE);
- }
- else {
- string = e_destination_get_address (destination);
- g_value_set_string (value, string);
- }
- }
- else {
- string = e_destination_get_address (destination);
- g_value_set_string (value, string);
-
- }
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-/**
- * e_destination_store_get_stamp:
- * @destination_store: an #EDestinationStore
- *
- * Since: 2.32
- **/
-gint
-e_destination_store_get_stamp (EDestinationStore *destination_store)
-{
- g_return_val_if_fail (E_IS_DESTINATION_STORE (destination_store), 0);
-
- return destination_store->priv->stamp;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-destination-store.h - EDestination store with GtkTreeModel interface.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_DESTINATION_STORE_H
-#define E_DESTINATION_STORE_H
-
-#include <gtk/gtk.h>
-#include <libebook/libebook.h>
-
-/* Standard GObject macros */
-#define E_TYPE_DESTINATION_STORE \
- (e_destination_store_get_type ())
-#define E_DESTINATION_STORE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_DESTINATION_STORE, EDestinationStore))
-#define E_DESTINATION_STORE_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_DESTINATION_STORE, EDestinationStoreClass))
-#define E_IS_DESTINATION_STORE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_DESTINATION_STORE))
-#define E_IS_DESTINATION_STORE_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_DESTINATION_STORE))
-#define E_DESTINATION_STORE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_DESTINATION_STORE, EDestinationStoreClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EDestinationStore EDestinationStore;
-typedef struct _EDestinationStoreClass EDestinationStoreClass;
-typedef struct _EDestinationStorePrivate EDestinationStorePrivate;
-
-struct _EDestinationStore {
- GObject parent;
- EDestinationStorePrivate *priv;
-};
-
-struct _EDestinationStoreClass {
- GObjectClass parent_class;
-};
-
-typedef enum {
- E_DESTINATION_STORE_COLUMN_NAME,
- E_DESTINATION_STORE_COLUMN_EMAIL,
- E_DESTINATION_STORE_COLUMN_ADDRESS,
- E_DESTINATION_STORE_NUM_COLUMNS
-} EDestinationStoreColumnType;
-
-GType e_destination_store_get_type (void);
-EDestinationStore *
- e_destination_store_new (void);
-EDestination * e_destination_store_get_destination
- (EDestinationStore *destination_store,
- GtkTreeIter *iter);
-
-/* Returns a shallow copy; free the list when done, but don't unref elements */
-GList * e_destination_store_list_destinations
- (EDestinationStore *destination_store);
-
-void e_destination_store_insert_destination
- (EDestinationStore *destination_store,
- gint index,
- EDestination *destination);
-void e_destination_store_append_destination
- (EDestinationStore *destination_store,
- EDestination *destination);
-void e_destination_store_remove_destination
- (EDestinationStore *destination_store,
- EDestination *destination);
-void e_destination_store_remove_destination_nth
- (EDestinationStore *destination_store,
- gint n);
-guint e_destination_store_get_destination_count
- (EDestinationStore *destination_store);
-GtkTreePath * e_destination_store_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-gint e_destination_store_get_stamp (EDestinationStore *destination_store);
-
-G_END_DECLS
-
-#endif /* E_DESTINATION_STORE_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector-dialog.c - Dialog that lets user pick EDestinations.
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Hans Petter Jansson <hpj@novell.com>
- */
-
-#ifdef GTK_DISABLE_DEPRECATED
-#undef GTK_DISABLE_DEPRECATED
-#endif
-
-#include <config.h>
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-#include <glib/gi18n-lib.h>
-
-#include <libebook/libebook.h>
-#include <libebackend/libebackend.h>
-
-#include "e-source-combo-box.h"
-#include "e-destination-store.h"
-#include "e-contact-store.h"
-#include "e-client-utils.h"
-#include "e-name-selector-dialog.h"
-#include "e-name-selector-entry.h"
-
-#define E_NAME_SELECTOR_DIALOG_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_NAME_SELECTOR_DIALOG, ENameSelectorDialogPrivate))
-
-typedef struct {
- gchar *name;
-
- GtkGrid *section_grid;
- GtkLabel *label;
- GtkButton *transfer_button;
- GtkButton *remove_button;
- GtkTreeView *destination_view;
-}
-Section;
-
-typedef struct {
- GtkTreeView *view;
- GtkButton *button;
- ENameSelectorDialog *dlg_ptr;
-} SelData;
-
-struct _ENameSelectorDialogPrivate {
- ESourceRegistry *registry;
- ENameSelectorModel *name_selector_model;
- GtkTreeModelSort *contact_sort;
- GCancellable *cancellable;
-
- GtkTreeView *contact_view;
- GtkLabel *status_label;
- GtkGrid *destination_vgrid;
- GtkEntry *search_entry;
- GtkSizeGroup *button_size_group;
- GtkWidget *category_combobox;
- GtkWidget *contact_window;
-
- GArray *sections;
-
- guint destination_index;
- GSList *user_query_fields;
- GtkSizeGroup *dest_label_size_group;
-};
-
-enum {
- PROP_0,
- PROP_REGISTRY
-};
-
-static void search_changed (ENameSelectorDialog *name_selector_dialog);
-static void source_changed (ENameSelectorDialog *name_selector_dialog, ESourceComboBox *source_combo_box);
-static void transfer_button_clicked (ENameSelectorDialog *name_selector_dialog, GtkButton *transfer_button);
-static void contact_selection_changed (ENameSelectorDialog *name_selector_dialog);
-static void setup_name_selector_model (ENameSelectorDialog *name_selector_dialog);
-static void shutdown_name_selector_model (ENameSelectorDialog *name_selector_dialog);
-static void contact_activated (ENameSelectorDialog *name_selector_dialog, GtkTreePath *path);
-static void destination_activated (ENameSelectorDialog *name_selector_dialog, GtkTreePath *path,
- GtkTreeViewColumn *column, GtkTreeView *tree_view);
-static gboolean destination_key_press (ENameSelectorDialog *name_selector_dialog, GdkEventKey *event, GtkTreeView *tree_view);
-static void remove_button_clicked (GtkButton *button, SelData *data);
-static void remove_books (ENameSelectorDialog *name_selector_dialog);
-static void contact_column_formatter (GtkTreeViewColumn *column, GtkCellRenderer *cell,
- GtkTreeModel *model, GtkTreeIter *iter,
- ENameSelectorDialog *name_selector_dialog);
-static void destination_column_formatter (GtkTreeViewColumn *column, GtkCellRenderer *cell,
- GtkTreeModel *model, GtkTreeIter *iter,
- ENameSelectorDialog *name_selector_dialog);
-
-/* ------------------ *
- * Class/object setup *
- * ------------------ */
-
-G_DEFINE_TYPE_WITH_CODE (
- ENameSelectorDialog,
- e_name_selector_dialog,
- GTK_TYPE_DIALOG,
- G_IMPLEMENT_INTERFACE (
- E_TYPE_EXTENSIBLE, NULL))
-
-static void
-name_selector_dialog_populate_categories (ENameSelectorDialog *name_selector_dialog)
-{
- GtkWidget *combo_box;
- GList *category_list, *iter;
-
- /* "Any Category" is preloaded. */
- combo_box = name_selector_dialog->priv->category_combobox;
- if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box)) == -1)
- gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
-
- /* Categories are already sorted. */
- category_list = e_categories_get_list ();
- for (iter = category_list; iter != NULL; iter = iter->next) {
- /* Only add user-visible categories. */
- if (!e_categories_is_searchable (iter->data))
- continue;
-
- gtk_combo_box_text_append_text (
- GTK_COMBO_BOX_TEXT (combo_box), iter->data);
- }
-
- g_list_free (category_list);
-
- g_signal_connect_swapped (
- combo_box, "changed",
- G_CALLBACK (search_changed), name_selector_dialog);
-}
-
-static void
-name_selector_dialog_set_registry (ENameSelectorDialog *name_selector_dialog,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_return_if_fail (name_selector_dialog->priv->registry == NULL);
-
- name_selector_dialog->priv->registry = g_object_ref (registry);
-}
-
-static void
-name_selector_dialog_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- name_selector_dialog_set_registry (
- E_NAME_SELECTOR_DIALOG (object),
- g_value_get_object (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-name_selector_dialog_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_name_selector_dialog_get_registry (
- E_NAME_SELECTOR_DIALOG (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-name_selector_dialog_dispose (GObject *object)
-{
- ENameSelectorDialogPrivate *priv;
-
- priv = E_NAME_SELECTOR_DIALOG_GET_PRIVATE (object);
-
- remove_books (E_NAME_SELECTOR_DIALOG (object));
- shutdown_name_selector_model (E_NAME_SELECTOR_DIALOG (object));
-
- if (priv->registry != NULL) {
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_name_selector_dialog_parent_class)->dispose (object);
-}
-
-static void
-name_selector_dialog_finalize (GObject *object)
-{
- ENameSelectorDialogPrivate *priv;
-
- priv = E_NAME_SELECTOR_DIALOG_GET_PRIVATE (object);
-
- g_slist_foreach (priv->user_query_fields, (GFunc) g_free, NULL);
- g_slist_free (priv->user_query_fields);
-
- g_array_free (priv->sections, TRUE);
- g_object_unref (priv->button_size_group);
- g_object_unref (priv->dest_label_size_group);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_name_selector_dialog_parent_class)->finalize (object);
-}
-
-static void
-name_selector_dialog_constructed (GObject *object)
-{
- ENameSelectorDialogPrivate *priv;
- GtkTreeSelection *contact_selection;
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell_renderer;
- GtkTreeSelection *selection;
- ESource *source;
- gchar *tmp_str;
- GtkWidget *name_selector_grid;
- GtkWidget *show_contacts_label;
- GtkWidget *hgrid;
- GtkWidget *label;
- GtkWidget *show_contacts_grid;
- GtkWidget *AddressBookLabel;
- GtkWidget *label_category;
- GtkWidget *search;
- AtkObject *atko;
- GtkWidget *label_search;
- GtkWidget *source_menu_hgrid;
- GtkWidget *combobox_category;
- GtkWidget *label_contacts;
- GtkWidget *scrolledwindow0;
- GtkWidget *scrolledwindow1;
- AtkRelationSet *tmp_relation_set;
- AtkRelationType tmp_relationship;
- AtkRelation *tmp_relation;
- AtkObject *scrolledwindow1_relation_targets[1];
- GtkWidget *source_tree_view;
- GtkWidget *destination_vgrid;
- GtkWidget *status_message;
- GtkWidget *source_combo;
- const gchar *extension_name;
-
- priv = E_NAME_SELECTOR_DIALOG_GET_PRIVATE (object);
-
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_name_selector_dialog_parent_class)->constructed (object);
-
- name_selector_grid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", FALSE,
- "row-spacing", 6,
- NULL);
- gtk_widget_show (name_selector_grid);
- gtk_container_set_border_width (GTK_CONTAINER (name_selector_grid), 0);
-
- tmp_str = g_strconcat ("<b>", _("Show Contacts"), "</b>", NULL);
- show_contacts_label = gtk_label_new (tmp_str);
- gtk_widget_show (show_contacts_label);
- gtk_container_add (GTK_CONTAINER (name_selector_grid), show_contacts_label);
- gtk_label_set_use_markup (GTK_LABEL (show_contacts_label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (show_contacts_label), 0, 0.5);
- g_free (tmp_str);
-
- hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 12,
- NULL);
- gtk_widget_show (hgrid);
- gtk_container_add (GTK_CONTAINER (name_selector_grid), hgrid);
-
- label = gtk_label_new ("");
- gtk_widget_show (label);
- gtk_container_add (GTK_CONTAINER (hgrid), label);
-
- show_contacts_grid = gtk_grid_new ();
- gtk_widget_show (show_contacts_grid);
- gtk_container_add (GTK_CONTAINER (hgrid), show_contacts_grid);
- g_object_set (G_OBJECT (show_contacts_grid),
- "column-spacing", 12,
- "row-spacing", 6,
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
-
- AddressBookLabel = gtk_label_new_with_mnemonic (_("Address B_ook:"));
- gtk_widget_show (AddressBookLabel);
- gtk_grid_attach (GTK_GRID (show_contacts_grid), AddressBookLabel, 0, 0, 1, 1);
- gtk_widget_set_halign (AddressBookLabel, GTK_ALIGN_FILL);
- gtk_label_set_justify (GTK_LABEL (AddressBookLabel), GTK_JUSTIFY_CENTER);
- gtk_misc_set_alignment (GTK_MISC (AddressBookLabel), 0, 0.5);
-
- label_category = gtk_label_new_with_mnemonic (_("Cat_egory:"));
- gtk_widget_show (label_category);
- gtk_grid_attach (GTK_GRID (show_contacts_grid), label_category, 0, 1, 1, 1);
- gtk_widget_set_halign (label_category, GTK_ALIGN_FILL);
- gtk_label_set_justify (GTK_LABEL (label_category), GTK_JUSTIFY_CENTER);
- gtk_misc_set_alignment (GTK_MISC (label_category), 0, 0.5);
-
- hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 12,
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (hgrid);
- gtk_grid_attach (GTK_GRID (show_contacts_grid), hgrid, 1, 2, 1, 1);
-
- search = gtk_entry_new ();
- gtk_widget_show (search);
- gtk_widget_set_hexpand (search, TRUE);
- gtk_widget_set_halign (search, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (hgrid), search);
-
- label_search = gtk_label_new_with_mnemonic (_("_Search:"));
- gtk_widget_show (label_search);
- gtk_grid_attach (GTK_GRID (show_contacts_grid), label_search, 0, 2, 1, 1);
- gtk_widget_set_halign (label_search, GTK_ALIGN_FILL);
- gtk_misc_set_alignment (GTK_MISC (label_search), 0, 0.5);
-
- source_menu_hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 0,
- "halign", GTK_ALIGN_FILL,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (source_menu_hgrid);
- gtk_grid_attach (GTK_GRID (show_contacts_grid), source_menu_hgrid, 1, 0, 1, 1);
-
- combobox_category = gtk_combo_box_text_new ();
- gtk_widget_show (combobox_category);
- g_object_set (G_OBJECT (combobox_category),
- "halign", GTK_ALIGN_FILL,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_grid_attach (GTK_GRID (show_contacts_grid), combobox_category, 1, 1, 1, 1);
- gtk_combo_box_text_append_text (
- GTK_COMBO_BOX_TEXT (combobox_category), _("Any Category"));
-
- tmp_str = g_strconcat ("<b>", _("Co_ntacts"), "</b>", NULL);
- label_contacts = gtk_label_new_with_mnemonic (tmp_str);
- gtk_widget_show (label_contacts);
- gtk_container_add (GTK_CONTAINER (name_selector_grid), label_contacts);
- gtk_label_set_use_markup (GTK_LABEL (label_contacts), TRUE);
- gtk_misc_set_alignment (GTK_MISC (label_contacts), 0, 0.5);
- g_free (tmp_str);
-
- scrolledwindow0 = gtk_scrolled_window_new (NULL, NULL);
- priv->contact_window = scrolledwindow0;
- gtk_widget_show (scrolledwindow0);
- gtk_widget_set_vexpand (scrolledwindow0, TRUE);
- gtk_widget_set_valign (scrolledwindow0, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (name_selector_grid), scrolledwindow0);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (scrolledwindow0),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 12,
- NULL);
- gtk_widget_show (hgrid);
- gtk_scrolled_window_add_with_viewport (
- GTK_SCROLLED_WINDOW (scrolledwindow0), hgrid);
-
- label = gtk_label_new ("");
- gtk_widget_show (label);
- gtk_container_add (GTK_CONTAINER (hgrid), label);
-
- scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
- gtk_widget_show (scrolledwindow1);
- gtk_container_add (GTK_CONTAINER (hgrid), scrolledwindow1);
- gtk_widget_set_hexpand (scrolledwindow1, TRUE);
- gtk_widget_set_halign (scrolledwindow1, GTK_ALIGN_FILL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (scrolledwindow1),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_SHADOW_IN);
-
- source_tree_view = gtk_tree_view_new ();
- gtk_widget_show (source_tree_view);
- gtk_container_add (GTK_CONTAINER (scrolledwindow1), source_tree_view);
- gtk_tree_view_set_headers_visible (
- GTK_TREE_VIEW (source_tree_view), FALSE);
- gtk_tree_view_set_enable_search (
- GTK_TREE_VIEW (source_tree_view), FALSE);
-
- destination_vgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", TRUE,
- "row-spacing", 6,
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (destination_vgrid);
- gtk_container_add (GTK_CONTAINER (hgrid), destination_vgrid);
-
- status_message = gtk_label_new ("");
- gtk_widget_show (status_message);
- gtk_container_add (GTK_CONTAINER (name_selector_grid), status_message);
- gtk_label_set_use_markup (GTK_LABEL (status_message), TRUE);
- gtk_misc_set_alignment (GTK_MISC (status_message), 0, 0.5);
- gtk_misc_set_padding (GTK_MISC (status_message), 0, 3);
-
- gtk_label_set_mnemonic_widget (GTK_LABEL (AddressBookLabel), source_menu_hgrid);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label_category), combobox_category);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label_search), search);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label_contacts), source_tree_view);
-
- atko = gtk_widget_get_accessible (search);
- atk_object_set_name (atko, _("Search"));
-
- atko = gtk_widget_get_accessible (source_menu_hgrid);
- atk_object_set_name (atko, _("Address Book"));
-
- atko = gtk_widget_get_accessible (scrolledwindow1);
- atk_object_set_name (atko, _("Contacts"));
- tmp_relation_set = atk_object_ref_relation_set (atko);
- scrolledwindow1_relation_targets[0] = gtk_widget_get_accessible (label_contacts);
- tmp_relationship = atk_relation_type_for_name ("labelled-by");
- tmp_relation = atk_relation_new (scrolledwindow1_relation_targets, 1, tmp_relationship);
- atk_relation_set_add (tmp_relation_set, tmp_relation);
- g_object_unref (G_OBJECT (tmp_relation));
- g_object_unref (G_OBJECT (tmp_relation_set));
-
- gtk_box_pack_start (
- GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (object))),
- name_selector_grid, TRUE, TRUE, 0);
-
- /* Store pointers to relevant widgets */
-
- priv->contact_view = GTK_TREE_VIEW (source_tree_view);
- priv->status_label = GTK_LABEL (status_message);
- priv->destination_vgrid = GTK_GRID (destination_vgrid);
- priv->search_entry = GTK_ENTRY (search);
- priv->category_combobox = combobox_category;
-
- /* Create size group for transfer buttons */
-
- priv->button_size_group =
- gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
-
- /* Create size group for destination labels */
-
- priv->dest_label_size_group =
- gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
-
- /* Set up contacts view */
-
- column = gtk_tree_view_column_new ();
- cell_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
- gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
- gtk_tree_view_column_set_cell_data_func (
- column, cell_renderer, (GtkTreeCellDataFunc)
- contact_column_formatter, object, NULL);
-
- selection = gtk_tree_view_get_selection (priv->contact_view);
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
- gtk_tree_view_append_column (priv->contact_view, column);
- g_signal_connect_swapped (
- priv->contact_view, "row-activated",
- G_CALLBACK (contact_activated), object);
-
- /* Listen for changes to the contact selection */
-
- contact_selection = gtk_tree_view_get_selection (priv->contact_view);
- g_signal_connect_swapped (
- contact_selection, "changed",
- G_CALLBACK (contact_selection_changed), object);
-
- /* Set up our data structures */
-
- priv->name_selector_model = e_name_selector_model_new ();
- priv->sections = g_array_new (FALSE, FALSE, sizeof (Section));
-
- setup_name_selector_model (E_NAME_SELECTOR_DIALOG (object));
-
- /* Create source menu */
-
- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
- source_combo = e_source_combo_box_new (priv->registry, extension_name);
- g_signal_connect_swapped (
- source_combo, "changed",
- G_CALLBACK (source_changed), object);
-
- source_changed (E_NAME_SELECTOR_DIALOG (object), E_SOURCE_COMBO_BOX (source_combo));
-
- gtk_label_set_mnemonic_widget (GTK_LABEL (AddressBookLabel), source_combo);
- gtk_widget_show (source_combo);
- gtk_widget_set_hexpand (source_combo, TRUE);
- gtk_widget_set_halign (source_combo, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (source_menu_hgrid), source_combo);
-
- name_selector_dialog_populate_categories (
- E_NAME_SELECTOR_DIALOG (object));
-
- /* Set up search-as-you-type signal */
-
- g_signal_connect_swapped (
- search, "changed",
- G_CALLBACK (search_changed), object);
-
- /* Display initial source */
-
- source = e_source_registry_ref_default_address_book (priv->registry);
- e_source_combo_box_set_active (
- E_SOURCE_COMBO_BOX (source_combo), source);
- g_object_unref (source);
-
- /* Set up dialog defaults */
-
- gtk_dialog_add_buttons (
- GTK_DIALOG (object),
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
- NULL);
-
- /* Try to figure out a sane default size for the dialog. We used to hard
- * code this to 512 so keep using 512 if the screen is big enough,
- * otherwise use -1 (use as little as possible, use the
- * GtkScrolledWindow's scrollbars).
- *
- * This should allow scrolling on tiny netbook resolutions and let
- * others see as much of the dialog as possible.
- *
- * 600 pixels seems to be a good lower bound resolution to allow room
- * above or below for other UI (window manager's?)
- */
- gtk_window_set_default_size (
- GTK_WINDOW (object), 700,
- gdk_screen_height () >= 600 ? 512 : -1);
-
- gtk_dialog_set_default_response (
- GTK_DIALOG (object), GTK_RESPONSE_CLOSE);
- gtk_window_set_modal (GTK_WINDOW (object), TRUE);
- gtk_window_set_resizable (GTK_WINDOW (object), TRUE);
- gtk_container_set_border_width (GTK_CONTAINER (object), 4);
- gtk_window_set_title (
- GTK_WINDOW (object),
- _("Select Contacts from Address Book"));
- gtk_widget_grab_focus (search);
-
- e_extensible_load_extensions (E_EXTENSIBLE (object));
-}
-
-static void
-e_name_selector_dialog_class_init (ENameSelectorDialogClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ENameSelectorDialogPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = name_selector_dialog_set_property;
- object_class->get_property = name_selector_dialog_get_property;
- object_class->dispose = name_selector_dialog_dispose;
- object_class->finalize = name_selector_dialog_finalize;
- object_class->constructed = name_selector_dialog_constructed;
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- "Registry",
- "Data source registry",
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-}
-
-static void
-e_name_selector_dialog_init (ENameSelectorDialog *name_selector_dialog)
-{
- name_selector_dialog->priv =
- E_NAME_SELECTOR_DIALOG_GET_PRIVATE (name_selector_dialog);
-}
-
-/**
- * e_name_selector_dialog_new:
- * @registry: an #ESourceRegistry
- *
- * Creates a new #ENameSelectorDialog.
- *
- * Returns: A new #ENameSelectorDialog.
- **/
-ENameSelectorDialog *
-e_name_selector_dialog_new (ESourceRegistry *registry)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
-
- return g_object_new (
- E_TYPE_NAME_SELECTOR_DIALOG,
- "registry", registry, NULL);
-}
-
-/**
- * e_name_selector_dialog_get_registry:
- * @name_selector_dialog: an #ENameSelectorDialog
- *
- * Returns the #ESourceRegistry that was passed to
- * e_name_selector_dialog_new().
- *
- * Returns: the #ESourceRegistry
- *
- * Since: 3.6
- **/
-ESourceRegistry *
-e_name_selector_dialog_get_registry (ENameSelectorDialog *name_selector_dialog)
-{
- g_return_val_if_fail (
- E_IS_NAME_SELECTOR_DIALOG (name_selector_dialog), NULL);
-
- return name_selector_dialog->priv->registry;
-}
-
-/* --------- *
- * Utilities *
- * --------- */
-
-static gchar *
-escape_sexp_string (const gchar *string)
-{
- GString *gstring;
- gchar *encoded_string;
-
- gstring = g_string_new ("");
- e_sexp_encode_string (gstring, string);
-
- encoded_string = gstring->str;
- g_string_free (gstring, FALSE);
-
- return encoded_string;
-}
-
-static void
-sort_iter_to_contact_store_iter (ENameSelectorDialog *name_selector_dialog,
- GtkTreeIter *iter,
- gint *email_n)
-{
- ETreeModelGenerator *contact_filter;
- GtkTreeIter child_iter;
- gint email_n_local;
-
- contact_filter = e_name_selector_model_peek_contact_filter (
- name_selector_dialog->priv->name_selector_model);
-
- gtk_tree_model_sort_convert_iter_to_child_iter (
- name_selector_dialog->priv->contact_sort, &child_iter, iter);
- e_tree_model_generator_convert_iter_to_child_iter (
- contact_filter, iter, &email_n_local, &child_iter);
-
- if (email_n)
- *email_n = email_n_local;
-}
-
-static void
-add_destination (ENameSelectorModel *name_selector_model,
- EDestinationStore *destination_store,
- EContact *contact,
- gint email_n,
- EBookClient *client)
-{
- EDestination *destination;
- GList *email_list, *nth;
-
- /* get the correct index of an email in the contact */
- email_list = e_name_selector_model_get_contact_emails_without_used (name_selector_model, contact, FALSE);
- while (nth = g_list_nth (email_list, email_n), nth && nth->data == NULL) {
- email_n++;
- }
- e_name_selector_model_free_emails_list (email_list);
-
- /* Transfer (actually, copy into a destination and let the model filter out the
- * source automatically) */
-
- destination = e_destination_new ();
- e_destination_set_contact (destination, contact, email_n);
- if (client)
- e_destination_set_client (destination, client);
- e_destination_store_append_destination (destination_store, destination);
- g_object_unref (destination);
-}
-
-static void
-remove_books (ENameSelectorDialog *name_selector_dialog)
-{
- EContactStore *contact_store;
- GSList *clients, *l;
-
- if (!name_selector_dialog->priv->name_selector_model)
- return;
-
- contact_store = e_name_selector_model_peek_contact_store (
- name_selector_dialog->priv->name_selector_model);
-
- /* Remove books (should be just one) being viewed */
- clients = e_contact_store_get_clients (contact_store);
- for (l = clients; l; l = g_slist_next (l)) {
- EBookClient *client = l->data;
- e_contact_store_remove_client (contact_store, client);
- }
- g_slist_free (clients);
-
- /* See if we have a book pending; stop loading it if so */
- if (name_selector_dialog->priv->cancellable != NULL) {
- g_cancellable_cancel (name_selector_dialog->priv->cancellable);
- g_object_unref (name_selector_dialog->priv->cancellable);
- name_selector_dialog->priv->cancellable = NULL;
- }
-}
-
-/* ------------------ *
- * Section management *
- * ------------------ */
-
-static gint
-find_section_by_transfer_button (ENameSelectorDialog *name_selector_dialog,
- GtkButton *transfer_button)
-{
- gint i;
-
- for (i = 0; i < name_selector_dialog->priv->sections->len; i++) {
- Section *section = &g_array_index (
- name_selector_dialog->priv->sections, Section, i);
-
- if (section->transfer_button == transfer_button)
- return i;
- }
-
- return -1;
-}
-
-static gint
-find_section_by_tree_view (ENameSelectorDialog *name_selector_dialog,
- GtkTreeView *tree_view)
-{
- gint i;
-
- for (i = 0; i < name_selector_dialog->priv->sections->len; i++) {
- Section *section = &g_array_index (
- name_selector_dialog->priv->sections, Section, i);
-
- if (section->destination_view == tree_view)
- return i;
- }
-
- return -1;
-}
-
-static gint
-find_section_by_name (ENameSelectorDialog *name_selector_dialog,
- const gchar *name)
-{
- gint i;
-
- for (i = 0; i < name_selector_dialog->priv->sections->len; i++) {
- Section *section = &g_array_index (
- name_selector_dialog->priv->sections, Section, i);
-
- if (!strcmp (name, section->name))
- return i;
- }
-
- return -1;
-}
-
-static void
-selection_changed (GtkTreeSelection *selection,
- SelData *data)
-{
- GtkTreeSelection *contact_selection;
- gboolean have_selection = FALSE;
-
- contact_selection = gtk_tree_view_get_selection (data->view);
- if (gtk_tree_selection_count_selected_rows (contact_selection) > 0)
- have_selection = TRUE;
- gtk_widget_set_sensitive (GTK_WIDGET (data->button), have_selection);
-}
-
-static GtkTreeView *
-make_tree_view_for_section (ENameSelectorDialog *name_selector_dialog,
- EDestinationStore *destination_store)
-{
- GtkTreeView *tree_view;
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell_renderer;
-
- tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
-
- column = gtk_tree_view_column_new ();
- cell_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
- gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
- gtk_tree_view_column_set_cell_data_func (
- column, cell_renderer,
- (GtkTreeCellDataFunc) destination_column_formatter,
- name_selector_dialog, NULL);
- gtk_tree_view_append_column (tree_view, column);
- gtk_tree_view_set_headers_visible (tree_view, FALSE);
- gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (destination_store));
-
- return tree_view;
-}
-
-static void
-setup_section_button (ENameSelectorDialog *name_selector_dialog,
- GtkButton *button,
- double halign,
- const gchar *label_text,
- const gchar *icon_name,
- gboolean icon_before_label)
-{
- GtkWidget *alignment;
- GtkWidget *hgrid;
- GtkWidget *label;
- GtkWidget *image;
-
- gtk_size_group_add_widget (
- name_selector_dialog->priv->button_size_group,
- GTK_WIDGET (button));
-
- alignment = gtk_alignment_new (halign, 0.5, 0.0, 0.0);
- gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (alignment));
-
- hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 2,
- NULL);
- gtk_widget_show (hgrid);
- gtk_container_add (GTK_CONTAINER (alignment), hgrid);
-
- label = gtk_label_new_with_mnemonic (label_text);
- gtk_widget_show (label);
-
- image = gtk_image_new_from_stock (icon_name, GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (image);
-
- if (icon_before_label) {
- gtk_container_add (GTK_CONTAINER (hgrid), image);
- gtk_container_add (GTK_CONTAINER (hgrid), label);
- } else {
- gtk_container_add (GTK_CONTAINER (hgrid), label);
- gtk_container_add (GTK_CONTAINER (hgrid), image);
- }
-}
-
-static gint
-add_section (ENameSelectorDialog *name_selector_dialog,
- const gchar *name,
- const gchar *pretty_name,
- EDestinationStore *destination_store)
-{
- ENameSelectorDialogPrivate *priv;
- Section section;
- GtkWidget *vgrid;
- GtkWidget *alignment;
- GtkWidget *scrollwin;
- SelData *data;
- GtkTreeSelection *selection;
- gchar *text;
- GtkWidget *hgrid;
-
- g_assert (name != NULL);
- g_assert (pretty_name != NULL);
- g_assert (E_IS_DESTINATION_STORE (destination_store));
-
- priv = E_NAME_SELECTOR_DIALOG_GET_PRIVATE (name_selector_dialog);
-
- memset (§ion, 0, sizeof (Section));
-
- section.name = g_strdup (name);
- section.section_grid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 12,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- section.label = GTK_LABEL (gtk_label_new_with_mnemonic (pretty_name));
- section.transfer_button = GTK_BUTTON (gtk_button_new ());
- section.remove_button = GTK_BUTTON (gtk_button_new ());
- section.destination_view = make_tree_view_for_section (name_selector_dialog, destination_store);
-
- gtk_label_set_mnemonic_widget (GTK_LABEL (section.label), GTK_WIDGET (section.destination_view));
-
- if (pango_parse_markup (pretty_name, -1, '_', NULL,
- &text, NULL, NULL)) {
- atk_object_set_name (gtk_widget_get_accessible (
- GTK_WIDGET (section.destination_view)), text);
- g_free (text);
- }
-
- /* Set up transfer button */
- g_signal_connect_swapped (
- section.transfer_button, "clicked",
- G_CALLBACK (transfer_button_clicked), name_selector_dialog);
-
- /*data for the remove callback*/
- data = g_malloc0 (sizeof (SelData));
- data->view = section.destination_view;
- data->dlg_ptr = name_selector_dialog;
-
- /*Associate to an object destroy so that it gets freed*/
- g_object_set_data_full ((GObject *) section.destination_view, "sel-remove-data", data, g_free);
-
- g_signal_connect (
- section.remove_button, "clicked",
- G_CALLBACK (remove_button_clicked), data);
-
- /* Alignment and vgrid for the add/remove buttons */
-
- alignment = gtk_alignment_new (0.5, 0.0, 0.0, 0.0);
- gtk_container_add (GTK_CONTAINER (section.section_grid), alignment);
-
- vgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", TRUE,
- "row-spacing", 6,
- NULL);
-
- gtk_container_add (GTK_CONTAINER (alignment), vgrid);
-
- /* "Add" button */
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (section.transfer_button));
- setup_section_button (name_selector_dialog, section.transfer_button, 0.7, _("_Add"), "gtk-go-forward", FALSE);
-
- /* "Remove" button */
- gtk_container_add (GTK_CONTAINER (vgrid), GTK_WIDGET (section.remove_button));
- setup_section_button (name_selector_dialog, section.remove_button, 0.5, _("_Remove"), "gtk-go-back", TRUE);
- gtk_widget_set_sensitive (GTK_WIDGET (section.remove_button), FALSE);
-
- /* hgrid for label and scrolled window. This is a separate hgrid, instead
- * of just using the section.section_grid directly, as it has a different
- * spacing.
- */
-
- hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 6,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_container_add (GTK_CONTAINER (section.section_grid), hgrid);
-
- /* Title label */
-
- gtk_size_group_add_widget (priv->dest_label_size_group, GTK_WIDGET (section.label));
-
- gtk_misc_set_alignment (GTK_MISC (section.label), 0.0, 0.0);
- gtk_container_add (GTK_CONTAINER (hgrid), GTK_WIDGET (section.label));
-
- /* Treeview in a scrolled window */
- scrollwin = gtk_scrolled_window_new (NULL, NULL);
- gtk_container_add (GTK_CONTAINER (hgrid), scrollwin);
- gtk_widget_set_hexpand (scrollwin, TRUE);
- gtk_widget_set_halign (scrollwin, GTK_ALIGN_FILL);
- gtk_widget_set_vexpand (scrollwin, TRUE);
- gtk_widget_set_valign (scrollwin, GTK_ALIGN_FILL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_IN);
- gtk_container_add (GTK_CONTAINER (scrollwin), GTK_WIDGET (section.destination_view));
-
- /*data for 'changed' callback*/
- data = g_malloc0 (sizeof (SelData));
- data->view = section.destination_view;
- data->button = section.remove_button;
- g_object_set_data_full ((GObject *) section.destination_view, "sel-change-data", data, g_free);
- selection = gtk_tree_view_get_selection (section.destination_view);
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
-
- g_signal_connect (
- selection, "changed",
- G_CALLBACK (selection_changed), data);
-
- g_signal_connect_swapped (
- section.destination_view, "row-activated",
- G_CALLBACK (destination_activated), name_selector_dialog);
- g_signal_connect_swapped (
- section.destination_view, "key-press-event",
- G_CALLBACK (destination_key_press), name_selector_dialog);
-
- /* Done! */
-
- gtk_widget_show_all (GTK_WIDGET (section.section_grid));
-
- /* Pack this section's box into the dialog */
- gtk_container_add (GTK_CONTAINER (name_selector_dialog->priv->destination_vgrid), GTK_WIDGET (section.section_grid));
- g_object_set (G_OBJECT (section.section_grid),
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
-
- g_array_append_val (name_selector_dialog->priv->sections, section);
-
- /* Make sure UI is consistent */
- contact_selection_changed (name_selector_dialog);
-
- return name_selector_dialog->priv->sections->len - 1;
-}
-
-static void
-free_section (ENameSelectorDialog *name_selector_dialog,
- gint n)
-{
- Section *section;
-
- g_assert (n >= 0);
- g_assert (n < name_selector_dialog->priv->sections->len);
-
- section = &g_array_index (
- name_selector_dialog->priv->sections, Section, n);
-
- g_free (section->name);
- gtk_widget_destroy (GTK_WIDGET (section->section_grid));
-}
-
-static void
-model_section_added (ENameSelectorDialog *name_selector_dialog,
- const gchar *name)
-{
- gchar *pretty_name;
- EDestinationStore *destination_store;
-
- e_name_selector_model_peek_section (
- name_selector_dialog->priv->name_selector_model,
- name, &pretty_name, &destination_store);
- add_section (name_selector_dialog, name, pretty_name, destination_store);
- g_free (pretty_name);
-}
-
-static void
-model_section_removed (ENameSelectorDialog *name_selector_dialog,
- const gchar *name)
-{
- gint section_index;
-
- section_index = find_section_by_name (name_selector_dialog, name);
- g_assert (section_index >= 0);
-
- free_section (name_selector_dialog, section_index);
- g_array_remove_index (
- name_selector_dialog->priv->sections, section_index);
-}
-
-/* -------------------- *
- * Addressbook selector *
- * -------------------- */
-
-static void
-view_progress (EBookClientView *view,
- guint percent,
- const gchar *message,
- ENameSelectorDialog *dialog)
-{
- if (message == NULL)
- gtk_label_set_text (dialog->priv->status_label, "");
- else
- gtk_label_set_text (dialog->priv->status_label, message);
-}
-
-static void
-view_complete (EBookClientView *view,
- const GError *error,
- ENameSelectorDialog *dialog)
-{
- view_progress (view, -1, NULL, dialog);
-}
-
-static void
-start_client_view_cb (EContactStore *store,
- EBookClientView *client_view,
- ENameSelectorDialog *name_selector_dialog)
-{
- g_signal_connect (
- client_view, "progress",
- G_CALLBACK (view_progress), name_selector_dialog);
-
- g_signal_connect (
- client_view, "complete",
- G_CALLBACK (view_complete), name_selector_dialog);
-}
-
-static void
-stop_client_view_cb (EContactStore *store,
- EBookClientView *client_view,
- ENameSelectorDialog *name_selector_dialog)
-{
- g_signal_handlers_disconnect_by_func (client_view, view_progress, name_selector_dialog);
- g_signal_handlers_disconnect_by_func (client_view, view_complete, name_selector_dialog);
-}
-
-static void
-book_loaded_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- ENameSelectorDialog *name_selector_dialog = user_data;
- EClient *client = NULL;
- EBookClient *book_client;
- EContactStore *store;
- ENameSelectorModel *model;
- GError *error = NULL;
-
- e_client_utils_open_new_finish (E_SOURCE (source_object), result, &client, &error);
-
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- g_warn_if_fail (client == NULL);
- g_error_free (error);
- goto exit;
- }
-
- if (error != NULL) {
- gchar *message;
-
- message = g_strdup_printf (
- _("Error loading address book: %s"), error->message);
- gtk_label_set_text (
- name_selector_dialog->priv->status_label, message);
- g_free (message);
-
- g_warn_if_fail (client == NULL);
- g_error_free (error);
- goto exit;
- }
-
- book_client = E_BOOK_CLIENT (client);
- if (!book_client) {
- g_warn_if_fail (book_client != NULL);
- goto exit;
- }
-
- model = name_selector_dialog->priv->name_selector_model;
- store = e_name_selector_model_peek_contact_store (model);
- e_contact_store_add_client (store, book_client);
- g_object_unref (book_client);
-
- exit:
- g_object_unref (name_selector_dialog);
-}
-
-static void
-source_changed (ENameSelectorDialog *name_selector_dialog,
- ESourceComboBox *source_combo_box)
-{
- GCancellable *cancellable;
- ESource *source;
- gpointer parent;
-
- source = e_source_combo_box_ref_active (source_combo_box);
-
- parent = gtk_widget_get_toplevel (GTK_WIDGET (name_selector_dialog));
- parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
-
- /* Remove any previous books being shown or loaded */
- remove_books (name_selector_dialog);
-
- if (source == NULL)
- return;
-
- cancellable = g_cancellable_new ();
- name_selector_dialog->priv->cancellable = cancellable;
-
- /* Start loading selected book */
- e_client_utils_open_new (
- source, E_CLIENT_SOURCE_TYPE_CONTACTS, TRUE, cancellable,
- book_loaded_cb, g_object_ref (name_selector_dialog));
-
- g_object_unref (source);
-}
-
-/* --------------- *
- * Other UI events *
- * --------------- */
-
-static void
-search_changed (ENameSelectorDialog *name_selector_dialog)
-{
- ENameSelectorDialogPrivate *priv = E_NAME_SELECTOR_DIALOG_GET_PRIVATE (name_selector_dialog);
- EContactStore *contact_store;
- EBookQuery *book_query;
- GtkWidget *combo_box;
- const gchar *text;
- gchar *text_escaped;
- gchar *query_string;
- gchar *category;
- gchar *category_escaped;
- gchar *user_fields_str;
-
- combo_box = priv->category_combobox;
- if (gtk_combo_box_get_active (GTK_COMBO_BOX (combo_box)) == -1)
- gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
-
- category = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo_box));
- category_escaped = escape_sexp_string (category);
-
- text = gtk_entry_get_text (name_selector_dialog->priv->search_entry);
- text_escaped = escape_sexp_string (text);
-
- user_fields_str = ens_util_populate_user_query_fields (priv->user_query_fields, text, text_escaped);
-
- if (g_strcmp0 (category, _("Any Category")) == 0)
- query_string = g_strdup_printf (
- "(or (beginswith \"file_as\" %s) "
- " (beginswith \"full_name\" %s) "
- " (beginswith \"email\" %s) "
- " (beginswith \"nickname\" %s)%s))",
- text_escaped, text_escaped,
- text_escaped, text_escaped,
- user_fields_str ? user_fields_str : "");
- else
- query_string = g_strdup_printf (
- "(and (is \"category_list\" %s) "
- "(or (beginswith \"file_as\" %s) "
- " (beginswith \"full_name\" %s) "
- " (beginswith \"email\" %s) "
- " (beginswith \"nickname\" %s)%s))",
- category_escaped, text_escaped, text_escaped,
- text_escaped, text_escaped,
- user_fields_str ? user_fields_str : "");
-
- book_query = e_book_query_from_string (query_string);
-
- contact_store = e_name_selector_model_peek_contact_store (
- name_selector_dialog->priv->name_selector_model);
- e_contact_store_set_query (contact_store, book_query);
- e_book_query_unref (book_query);
-
- g_free (query_string);
- g_free (text_escaped);
- g_free (category_escaped);
- g_free (category);
- g_free (user_fields_str);
-}
-
-static void
-contact_selection_changed (ENameSelectorDialog *name_selector_dialog)
-{
- GtkTreeSelection *contact_selection;
- gboolean have_selection = FALSE;
- gint i;
-
- contact_selection = gtk_tree_view_get_selection (
- name_selector_dialog->priv->contact_view);
- if (gtk_tree_selection_count_selected_rows (contact_selection))
- have_selection = TRUE;
-
- for (i = 0; i < name_selector_dialog->priv->sections->len; i++) {
- Section *section = &g_array_index (
- name_selector_dialog->priv->sections, Section, i);
- gtk_widget_set_sensitive (GTK_WIDGET (section->transfer_button), have_selection);
- }
-}
-
-static void
-contact_activated (ENameSelectorDialog *name_selector_dialog,
- GtkTreePath *path)
-{
- EContactStore *contact_store;
- EDestinationStore *destination_store;
- EContact *contact;
- GtkTreeIter iter;
- Section *section;
- gint email_n;
-
- /* When a contact is activated, we transfer it to the first destination on our list */
-
- contact_store = e_name_selector_model_peek_contact_store (
- name_selector_dialog->priv->name_selector_model);
-
- /* If we have no sections, we can't transfer */
- if (name_selector_dialog->priv->sections->len == 0)
- return;
-
- /* Get the contact to be transferred */
-
- if (!gtk_tree_model_get_iter (
- GTK_TREE_MODEL (name_selector_dialog->priv->contact_sort),
- &iter, path))
- g_assert_not_reached ();
-
- sort_iter_to_contact_store_iter (name_selector_dialog, &iter, &email_n);
-
- contact = e_contact_store_get_contact (contact_store, &iter);
- if (!contact) {
- g_warning ("ENameSelectorDialog could not get selected contact!");
- return;
- }
-
- section = &g_array_index (
- name_selector_dialog->priv->sections,
- Section, name_selector_dialog->priv->destination_index);
- if (!e_name_selector_model_peek_section (
- name_selector_dialog->priv->name_selector_model,
- section->name, NULL, &destination_store)) {
- g_warning ("ENameSelectorDialog has a section unknown to the model!");
- return;
- }
-
- add_destination (
- name_selector_dialog->priv->name_selector_model,
- destination_store, contact, email_n,
- e_contact_store_get_client (contact_store, &iter));
-}
-
-static void
-destination_activated (ENameSelectorDialog *name_selector_dialog,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- GtkTreeView *tree_view)
-{
- gint section_index;
- EDestinationStore *destination_store;
- EDestination *destination;
- Section *section;
- GtkTreeIter iter;
-
- /* When a destination is activated, we remove it from the section */
-
- section_index = find_section_by_tree_view (
- name_selector_dialog, tree_view);
- if (section_index < 0) {
- g_warning ("ENameSelectorDialog got activation from unknown view!");
- return;
- }
-
- section = &g_array_index (
- name_selector_dialog->priv->sections, Section, section_index);
- if (!e_name_selector_model_peek_section (
- name_selector_dialog->priv->name_selector_model,
- section->name, NULL, &destination_store)) {
- g_warning ("ENameSelectorDialog has a section unknown to the model!");
- return;
- }
-
- if (!gtk_tree_model_get_iter (
- GTK_TREE_MODEL (destination_store), &iter, path))
- g_assert_not_reached ();
-
- destination = e_destination_store_get_destination (
- destination_store, &iter);
- g_assert (destination);
-
- e_destination_store_remove_destination (
- destination_store, destination);
-}
-
-static gboolean
-remove_selection (ENameSelectorDialog *name_selector_dialog,
- GtkTreeView *tree_view)
-{
- gint section_index;
- EDestinationStore *destination_store;
- EDestination *destination;
- Section *section;
- GtkTreeSelection *selection;
- GList *rows, *l;
-
- section_index = find_section_by_tree_view (
- name_selector_dialog, tree_view);
- if (section_index < 0) {
- g_warning ("ENameSelectorDialog got key press from unknown view!");
- return FALSE;
- }
-
- section = &g_array_index (
- name_selector_dialog->priv->sections, Section, section_index);
- if (!e_name_selector_model_peek_section (
- name_selector_dialog->priv->name_selector_model,
- section->name, NULL, &destination_store)) {
- g_warning ("ENameSelectorDialog has a section unknown to the model!");
- return FALSE;
- }
-
- selection = gtk_tree_view_get_selection (tree_view);
- if (!gtk_tree_selection_count_selected_rows (selection)) {
- g_warning ("ENameSelectorDialog remove button clicked, but no selection!");
- return FALSE;
- }
-
- rows = gtk_tree_selection_get_selected_rows (selection, NULL);
- rows = g_list_reverse (rows);
-
- for (l = rows; l; l = g_list_next (l)) {
- GtkTreeIter iter;
- GtkTreePath *path = l->data;
-
- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (destination_store),
- &iter, path))
- g_assert_not_reached ();
-
- gtk_tree_path_free (path);
-
- destination = e_destination_store_get_destination (
- destination_store, &iter);
- g_assert (destination);
-
- e_destination_store_remove_destination (
- destination_store, destination);
- }
- g_list_free (rows);
-
- return TRUE;
-}
-
-static void
-remove_button_clicked (GtkButton *button,
- SelData *data)
-{
- GtkTreeView *view;
- ENameSelectorDialog *name_selector_dialog;
-
- view = data->view;
- name_selector_dialog = data->dlg_ptr;
- remove_selection (name_selector_dialog, view);
-}
-
-static gboolean
-destination_key_press (ENameSelectorDialog *name_selector_dialog,
- GdkEventKey *event,
- GtkTreeView *tree_view)
-{
-
- /* we only care about DEL key */
- if (event->keyval != GDK_KEY_Delete)
- return FALSE;
- return remove_selection (name_selector_dialog, tree_view);
-
-}
-
-static void
-transfer_button_clicked (ENameSelectorDialog *name_selector_dialog,
- GtkButton *transfer_button)
-{
- EContactStore *contact_store;
- EDestinationStore *destination_store;
- GtkTreeSelection *selection;
- EContact *contact;
- gint section_index;
- Section *section;
- gint email_n;
- GList *rows, *l;
-
- /* Get the contact to be transferred */
-
- contact_store = e_name_selector_model_peek_contact_store (
- name_selector_dialog->priv->name_selector_model);
- selection = gtk_tree_view_get_selection (
- name_selector_dialog->priv->contact_view);
-
- if (!gtk_tree_selection_count_selected_rows (selection)) {
- g_warning ("ENameSelectorDialog transfer button clicked, but no selection!");
- return;
- }
-
- /* Get the target section */
- section_index = find_section_by_transfer_button (
- name_selector_dialog, transfer_button);
- if (section_index < 0) {
- g_warning ("ENameSelectorDialog got click from unknown button!");
- return;
- }
-
- section = &g_array_index (
- name_selector_dialog->priv->sections, Section, section_index);
- if (!e_name_selector_model_peek_section (
- name_selector_dialog->priv->name_selector_model,
- section->name, NULL, &destination_store)) {
- g_warning ("ENameSelectorDialog has a section unknown to the model!");
- return;
- }
-
- rows = gtk_tree_selection_get_selected_rows (selection, NULL);
- rows = g_list_reverse (rows);
-
- for (l = rows; l; l = g_list_next (l)) {
- GtkTreeIter iter;
- GtkTreePath *path = l->data;
-
- if (!gtk_tree_model_get_iter (
- GTK_TREE_MODEL (name_selector_dialog->priv->contact_sort),
- &iter, path)) {
- gtk_tree_path_free (path);
- return;
- }
-
- gtk_tree_path_free (path);
- sort_iter_to_contact_store_iter (name_selector_dialog, &iter, &email_n);
-
- contact = e_contact_store_get_contact (contact_store, &iter);
- if (!contact) {
- g_warning ("ENameSelectorDialog could not get selected contact!");
- g_list_free (rows);
- return;
- }
-
- add_destination (
- name_selector_dialog->priv->name_selector_model,
- destination_store, contact, email_n,
- e_contact_store_get_client (contact_store, &iter));
- }
- g_list_free (rows);
-}
-
-/* --------------------- *
- * Main model management *
- * --------------------- */
-
-static void
-setup_name_selector_model (ENameSelectorDialog *name_selector_dialog)
-{
- ETreeModelGenerator *contact_filter;
- EContactStore *contact_store;
- GList *new_sections;
- GList *l;
-
- /* Create new destination sections in UI */
-
- new_sections = e_name_selector_model_list_sections (
- name_selector_dialog->priv->name_selector_model);
-
- for (l = new_sections; l; l = g_list_next (l)) {
- gchar *name = l->data;
- gchar *pretty_name;
- EDestinationStore *destination_store;
-
- e_name_selector_model_peek_section (
- name_selector_dialog->priv->name_selector_model,
- name, &pretty_name, &destination_store);
-
- add_section (name_selector_dialog, name, pretty_name, destination_store);
-
- g_free (pretty_name);
- g_free (name);
- }
-
- g_list_free (new_sections);
-
- /* Connect to section add/remove signals */
-
- g_signal_connect_swapped (
- name_selector_dialog->priv->name_selector_model, "section-added",
- G_CALLBACK (model_section_added), name_selector_dialog);
- g_signal_connect_swapped (
- name_selector_dialog->priv->name_selector_model, "section-removed",
- G_CALLBACK (model_section_removed), name_selector_dialog);
-
- /* Get contact store and its filter wrapper */
-
- contact_filter = e_name_selector_model_peek_contact_filter (
- name_selector_dialog->priv->name_selector_model);
-
- /* Create sorting model on top of filter, assign it to view */
-
- name_selector_dialog->priv->contact_sort = GTK_TREE_MODEL_SORT (
- gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (contact_filter)));
-
- /* sort on full name as we display full name in name selector dialog */
- gtk_tree_sortable_set_sort_column_id (
- GTK_TREE_SORTABLE (name_selector_dialog->priv->contact_sort),
- E_CONTACT_FULL_NAME, GTK_SORT_ASCENDING);
-
- gtk_tree_view_set_model (
- name_selector_dialog->priv->contact_view,
- GTK_TREE_MODEL (name_selector_dialog->priv->contact_sort));
-
- contact_store = e_name_selector_model_peek_contact_store (name_selector_dialog->priv->name_selector_model);
- if (contact_store) {
- g_signal_connect (contact_store, "start-client-view", G_CALLBACK (start_client_view_cb), name_selector_dialog);
- g_signal_connect (contact_store, "stop-client-view", G_CALLBACK (stop_client_view_cb), name_selector_dialog);
- }
-
- /* Make sure UI is consistent */
-
- search_changed (name_selector_dialog);
- contact_selection_changed (name_selector_dialog);
-}
-
-static void
-shutdown_name_selector_model (ENameSelectorDialog *name_selector_dialog)
-{
- gint i;
-
- /* Rid UI of previous destination sections */
-
- for (i = 0; i < name_selector_dialog->priv->sections->len; i++)
- free_section (name_selector_dialog, i);
-
- g_array_set_size (name_selector_dialog->priv->sections, 0);
-
- /* Free sorting model */
-
- if (name_selector_dialog->priv->contact_sort) {
- g_object_unref (name_selector_dialog->priv->contact_sort);
- name_selector_dialog->priv->contact_sort = NULL;
- }
-
- /* Free backend model */
-
- if (name_selector_dialog->priv->name_selector_model) {
- EContactStore *contact_store;
-
- contact_store = e_name_selector_model_peek_contact_store (name_selector_dialog->priv->name_selector_model);
- if (contact_store) {
- g_signal_handlers_disconnect_by_func (contact_store, start_client_view_cb, name_selector_dialog);
- g_signal_handlers_disconnect_by_func (contact_store, stop_client_view_cb, name_selector_dialog);
- }
-
- g_signal_handlers_disconnect_matched (
- name_selector_dialog->priv->name_selector_model,
- G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_dialog);
-
- g_object_unref (name_selector_dialog->priv->name_selector_model);
- name_selector_dialog->priv->name_selector_model = NULL;
- }
-}
-
-static void
-contact_column_formatter (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- ENameSelectorDialog *name_selector_dialog)
-{
- EContactStore *contact_store;
- EContact *contact;
- GtkTreeIter contact_store_iter;
- GList *email_list;
- gchar *string;
- gchar *full_name_str;
- gchar *email_str;
- gint email_n;
-
- contact_store_iter = *iter;
- sort_iter_to_contact_store_iter (
- name_selector_dialog, &contact_store_iter, &email_n);
-
- contact_store = e_name_selector_model_peek_contact_store (
- name_selector_dialog->priv->name_selector_model);
- contact = e_contact_store_get_contact (
- contact_store, &contact_store_iter);
- email_list = e_name_selector_model_get_contact_emails_without_used (
- name_selector_dialog->priv->name_selector_model, contact, TRUE);
- email_str = g_list_nth_data (email_list, email_n);
- full_name_str = e_contact_get (contact, E_CONTACT_FULL_NAME);
-
- if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
- if (!full_name_str)
- full_name_str = e_contact_get (contact, E_CONTACT_FILE_AS);
- string = g_strdup_printf ("%s", full_name_str ? full_name_str : "?");
- } else {
- string = g_strdup_printf (
- "%s%s<%s>", full_name_str ? full_name_str : "",
- full_name_str ? " " : "",
- email_str ? email_str : "");
- }
-
- g_free (full_name_str);
- e_name_selector_model_free_emails_list (email_list);
-
- g_object_set (cell, "text", string, NULL);
- g_free (string);
-}
-
-static void
-destination_column_formatter (GtkTreeViewColumn *column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- ENameSelectorDialog *name_selector_dialog)
-{
- EDestinationStore *destination_store = E_DESTINATION_STORE (model);
- EDestination *destination;
- GString *buffer;
-
- destination = e_destination_store_get_destination (destination_store, iter);
- g_assert (destination);
-
- buffer = g_string_new (e_destination_get_name (destination));
-
- if (!e_destination_is_evolution_list (destination)) {
- const gchar *email;
-
- email = e_destination_get_email (destination);
- if (email == NULL || *email == '\0')
- email = "?";
- g_string_append_printf (buffer, " <%s>", email);
- }
-
- g_object_set (cell, "text", buffer->str, NULL);
- g_string_free (buffer, TRUE);
-}
-
-/* ----------------------- *
- * ENameSelectorDialog API *
- * ----------------------- */
-
-/**
- * e_name_selector_dialog_peek_model:
- * @name_selector_dialog: an #ENameSelectorDialog
- *
- * Gets the #ENameSelectorModel used by @name_selector_model.
- *
- * Returns: The #ENameSelectorModel being used.
- **/
-ENameSelectorModel *
-e_name_selector_dialog_peek_model (ENameSelectorDialog *name_selector_dialog)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_DIALOG (name_selector_dialog), NULL);
-
- return name_selector_dialog->priv->name_selector_model;
-}
-
-/**
- * e_name_selector_dialog_set_model:
- * @name_selector_dialog: an #ENameSelectorDialog
- * @model: an #ENameSelectorModel
- *
- * Sets the model being used by @name_selector_dialog to @model.
- **/
-void
-e_name_selector_dialog_set_model (ENameSelectorDialog *name_selector_dialog,
- ENameSelectorModel *model)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_DIALOG (name_selector_dialog));
- g_return_if_fail (E_IS_NAME_SELECTOR_MODEL (model));
-
- if (model == name_selector_dialog->priv->name_selector_model)
- return;
-
- shutdown_name_selector_model (name_selector_dialog);
- name_selector_dialog->priv->name_selector_model = g_object_ref (model);
-
- setup_name_selector_model (name_selector_dialog);
-}
-
-/**
- * e_name_selector_dialog_set_destination_index:
- * @name_selector_dialog: an #ENameSelectorDialog
- * @index: index of the destination section, starting from 0.
- *
- * Sets the index number of the destination section.
- **/
-void
-e_name_selector_dialog_set_destination_index (ENameSelectorDialog *name_selector_dialog,
- guint index)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_DIALOG (name_selector_dialog));
-
- if (index >= name_selector_dialog->priv->sections->len)
- return;
-
- name_selector_dialog->priv->destination_index = index;
-}
-
-/**
- * e_name_selector_dialog_set_scrolling_policy:
- * @name_selector_dialog: an #ENameSelectorDialog
- * @hscrollbar_policy: scrolling policy for horizontal bar of the contacts window.
- * @vscrollbar_policy: scrolling policy for vertical bar of the contacts window.
- *
- * Sets the scrolling policy for the contacts section.
- *
- * Since: 3.2
- **/
-void
-e_name_selector_dialog_set_scrolling_policy (ENameSelectorDialog *name_selector_dialog,
- GtkPolicyType hscrollbar_policy,
- GtkPolicyType vscrollbar_policy)
-{
- GtkScrolledWindow *win = GTK_SCROLLED_WINDOW (name_selector_dialog->priv->contact_window);
-
- gtk_scrolled_window_set_policy (win, hscrollbar_policy, vscrollbar_policy);
-}
-
-/**
- * e_name_selector_dialog_get_section_visible:
- * @name_selector_dialog: an #ENameSelectorDialog
- * @name: name of the section
- *
- * Returns: whether section named @name is visible in the dialog.
- *
- * Since: 3.8
- **/
-gboolean
-e_name_selector_dialog_get_section_visible (ENameSelectorDialog *name_selector_dialog,
- const gchar *name)
-{
- Section *section;
- gint index;
-
- g_return_val_if_fail (E_IS_NAME_SELECTOR_DIALOG (name_selector_dialog), FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- index = find_section_by_name (name_selector_dialog, name);
- g_return_val_if_fail (index != -1, FALSE);
-
- section = &g_array_index (name_selector_dialog->priv->sections, Section, index);
- return gtk_widget_get_visible (GTK_WIDGET (section->section_grid));
-}
-
-/**
- * e_name_selector_dialog_set_section_visible:
- * @name_selector_dialog: an #ENameSelectorDialog
- * @name: name of the section
- * @visible: whether to show or hide the section
- *
- * Shows or hides section named @name in the dialog.
- *
- * Since: 3.8
- **/
-void
-e_name_selector_dialog_set_section_visible (ENameSelectorDialog *name_selector_dialog,
- const gchar *name,
- gboolean visible)
-{
- Section *section;
- gint index;
-
- g_return_if_fail (E_IS_NAME_SELECTOR_DIALOG (name_selector_dialog));
- g_return_if_fail (name != NULL);
-
- index = find_section_by_name (name_selector_dialog, name);
- g_return_if_fail (index != -1);
-
- section = &g_array_index (name_selector_dialog->priv->sections, Section, index);
-
- if (visible)
- gtk_widget_show (GTK_WIDGET (section->section_grid));
- else
- gtk_widget_hide (GTK_WIDGET (section->section_grid));
-}
-
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector-dialog.c - Dialog that lets user pick EDestinations.
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_NAME_SELECTOR_DIALOG_H
-#define E_NAME_SELECTOR_DIALOG_H
-
-#include <gtk/gtk.h>
-#include <libedataserver/libedataserver.h>
-
-#include <libedataserverui/e-contact-store.h>
-#include <libedataserverui/e-name-selector-model.h>
-
-/* Standard GObject macros */
-#define E_TYPE_NAME_SELECTOR_DIALOG \
- (e_name_selector_dialog_get_type ())
-#define E_NAME_SELECTOR_DIALOG(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_NAME_SELECTOR_DIALOG, ENameSelectorDialog))
-#define E_NAME_SELECTOR_DIALOG_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_NAME_SELECTOR_DIALOG, ENameSelectorDialogClass))
-#define E_IS_NAME_SELECTOR_DIALOG(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- (obj, E_TYPE_NAME_SELECTOR_DIALOG))
-#define E_IS_NAME_SELECTOR_DIALOG_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_NAME_SELECTOR_DIALOG))
-#define E_NAME_SELECTOR_DIALOG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_NAME_SELECTOR_DIALOG, ENameSelectorDialogClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ENameSelectorDialog ENameSelectorDialog;
-typedef struct _ENameSelectorDialogClass ENameSelectorDialogClass;
-typedef struct _ENameSelectorDialogPrivate ENameSelectorDialogPrivate;
-
-struct _ENameSelectorDialog {
- GtkDialog parent;
- ENameSelectorDialogPrivate *priv;
-};
-
-struct _ENameSelectorDialogClass {
- GtkDialogClass parent_class;
-};
-
-GType e_name_selector_dialog_get_type (void);
-ENameSelectorDialog *
- e_name_selector_dialog_new (ESourceRegistry *registry);
-ESourceRegistry *
- e_name_selector_dialog_get_registry
- (ENameSelectorDialog *name_selector_dialog);
-ENameSelectorModel *
- e_name_selector_dialog_peek_model
- (ENameSelectorDialog *name_selector_dialog);
-void e_name_selector_dialog_set_model
- (ENameSelectorDialog *name_selector_dialog,
- ENameSelectorModel *model);
-void e_name_selector_dialog_set_destination_index
- (ENameSelectorDialog *name_selector_dialog,
- guint index);
-void e_name_selector_dialog_set_scrolling_policy
- (ENameSelectorDialog *name_selector_dialog,
- GtkPolicyType hscrollbar_policy,
- GtkPolicyType vscrollbar_policy);
-gboolean e_name_selector_dialog_get_section_visible
- (ENameSelectorDialog *name_selector_dialog,
- const gchar *name);
-void e_name_selector_dialog_set_section_visible
- (ENameSelectorDialog *name_selector_dialog,
- const gchar *name,
- gboolean visible);
-
-G_END_DECLS
-
-#endif /* E_NAME_SELECTOR_DIALOG_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector-entry.c - Single-line text entry widget for EDestinations.
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#include <config.h>
-#include <string.h>
-#include <glib/gi18n-lib.h>
-
-#include <camel/camel.h>
-#include <libebackend/libebackend.h>
-
-#include <libedataserverui/e-client-utils.h>
-
-#include "e-name-selector-entry.h"
-
-#define E_NAME_SELECTOR_ENTRY_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_NAME_SELECTOR_ENTRY, ENameSelectorEntryPrivate))
-
-struct _ENameSelectorEntryPrivate {
-
- ESourceRegistry *registry;
- gint minimum_query_length;
- gboolean show_address;
-
- PangoAttrList *attr_list;
- EContactStore *contact_store;
- ETreeModelGenerator *email_generator;
- EDestinationStore *destination_store;
- GtkEntryCompletion *entry_completion;
-
- guint type_ahead_complete_cb_id;
- guint update_completions_cb_id;
-
- EDestination *popup_destination;
-
- gpointer (*contact_editor_func) (EBookClient *,
- EContact *,
- gboolean,
- gboolean);
- gpointer (*contact_list_editor_func)
- (EBookClient *,
- EContact *,
- gboolean,
- gboolean);
-
- gboolean is_completing;
- GSList *user_query_fields;
-
- /* For asynchronous operations. */
- GQueue cancellables;
-};
-
-enum {
- PROP_0,
- PROP_REGISTRY,
- PROP_MINIMUM_QUERY_LENGTH,
- PROP_SHOW_ADDRESS
-};
-
-enum {
- UPDATED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-#define ENS_DEBUG(x)
-
-G_DEFINE_TYPE_WITH_CODE (
- ENameSelectorEntry,
- e_name_selector_entry,
- GTK_TYPE_ENTRY,
- G_IMPLEMENT_INTERFACE (
- E_TYPE_EXTENSIBLE, NULL))
-
-/* 1/3 of the second to wait until invoking autocomplete lookup */
-#define AUTOCOMPLETE_TIMEOUT 333
-
-#define re_set_timeout(id,func,ptr) \
- if (id) \
- g_source_remove (id); \
- id = g_timeout_add (AUTOCOMPLETE_TIMEOUT, \
- (GSourceFunc) func, ptr);
-
-static void destination_row_inserted (ENameSelectorEntry *name_selector_entry, GtkTreePath *path, GtkTreeIter *iter);
-static void destination_row_changed (ENameSelectorEntry *name_selector_entry, GtkTreePath *path, GtkTreeIter *iter);
-static void destination_row_deleted (ENameSelectorEntry *name_selector_entry, GtkTreePath *path);
-
-static void user_insert_text (ENameSelectorEntry *name_selector_entry, gchar *new_text, gint new_text_length, gint *position, gpointer user_data);
-static void user_delete_text (ENameSelectorEntry *name_selector_entry, gint start_pos, gint end_pos, gpointer user_data);
-
-static void setup_default_contact_store (ENameSelectorEntry *name_selector_entry);
-static void deep_free_list (GList *list);
-
-static void
-name_selector_entry_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- e_name_selector_entry_set_registry (
- E_NAME_SELECTOR_ENTRY (object),
- g_value_get_object (value));
- return;
-
- case PROP_MINIMUM_QUERY_LENGTH:
- e_name_selector_entry_set_minimum_query_length (
- E_NAME_SELECTOR_ENTRY (object),
- g_value_get_int (value));
- return;
-
- case PROP_SHOW_ADDRESS:
- e_name_selector_entry_set_show_address (
- E_NAME_SELECTOR_ENTRY (object),
- g_value_get_boolean (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-name_selector_entry_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_name_selector_entry_get_registry (
- E_NAME_SELECTOR_ENTRY (object)));
- return;
-
- case PROP_MINIMUM_QUERY_LENGTH:
- g_value_set_int (
- value,
- e_name_selector_entry_get_minimum_query_length (
- E_NAME_SELECTOR_ENTRY (object)));
- return;
-
- case PROP_SHOW_ADDRESS:
- g_value_set_boolean (
- value,
- e_name_selector_entry_get_show_address (
- E_NAME_SELECTOR_ENTRY (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-name_selector_entry_dispose (GObject *object)
-{
- ENameSelectorEntryPrivate *priv;
-
- priv = E_NAME_SELECTOR_ENTRY_GET_PRIVATE (object);
-
- if (priv->registry != NULL) {
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- if (priv->attr_list != NULL) {
- pango_attr_list_unref (priv->attr_list);
- priv->attr_list = NULL;
- }
-
- if (priv->entry_completion) {
- g_object_unref (priv->entry_completion);
- priv->entry_completion = NULL;
- }
-
- if (priv->destination_store) {
- g_object_unref (priv->destination_store);
- priv->destination_store = NULL;
- }
-
- if (priv->email_generator) {
- g_object_unref (priv->email_generator);
- priv->email_generator = NULL;
- }
-
- if (priv->contact_store) {
- g_object_unref (priv->contact_store);
- priv->contact_store = NULL;
- }
-
- g_slist_foreach (priv->user_query_fields, (GFunc) g_free, NULL);
- g_slist_free (priv->user_query_fields);
- priv->user_query_fields = NULL;
-
- /* Cancel any stuck book loading operations. */
- while (!g_queue_is_empty (&priv->cancellables)) {
- GCancellable *cancellable;
-
- cancellable = g_queue_pop_head (&priv->cancellables);
- g_cancellable_cancel (cancellable);
- g_object_unref (cancellable);
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_name_selector_entry_parent_class)->dispose (object);
-}
-
-static void
-name_selector_entry_constructed (GObject *object)
-{
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_name_selector_entry_parent_class)->
- constructed (object);
-
- e_extensible_load_extensions (E_EXTENSIBLE (object));
-}
-
-static void
-name_selector_entry_realize (GtkWidget *widget)
-{
- ENameSelectorEntryPrivate *priv;
-
- priv = E_NAME_SELECTOR_ENTRY_GET_PRIVATE (widget);
-
- /* Chain up to parent's realize() method. */
- GTK_WIDGET_CLASS (e_name_selector_entry_parent_class)->realize (widget);
-
- if (priv->contact_store == NULL)
- setup_default_contact_store (E_NAME_SELECTOR_ENTRY (widget));
-}
-
-static void
-name_selector_entry_drag_data_received (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection_data,
- guint info,
- guint time)
-{
- CamelInternetAddress *address;
- gint n_addresses = 0;
- gchar *text;
-
- address = camel_internet_address_new ();
- text = (gchar *) gtk_selection_data_get_text (selection_data);
-
- /* See if Camel can parse a valid email address from the text. */
- if (text != NULL && *text != '\0') {
- camel_url_decode (text);
- if (g_ascii_strncasecmp (text, "mailto:", 7) == 0)
- n_addresses = camel_address_decode (
- CAMEL_ADDRESS (address), text + 7);
- else
- n_addresses = camel_address_decode (
- CAMEL_ADDRESS (address), text);
- }
-
- if (n_addresses > 0) {
- GtkEditable *editable;
- GdkDragAction action;
- gboolean delete;
- gint position;
-
- editable = GTK_EDITABLE (widget);
- gtk_editable_set_position (editable, -1);
- position = gtk_editable_get_position (editable);
-
- g_free (text);
-
- text = camel_address_format (CAMEL_ADDRESS (address));
- gtk_editable_insert_text (editable, text, -1, &position);
-
- action = gdk_drag_context_get_selected_action (context);
- delete = (action == GDK_ACTION_MOVE);
- gtk_drag_finish (context, TRUE, delete, time);
- }
-
- g_object_unref (address);
- g_free (text);
-
- if (n_addresses <= 0)
- /* Chain up to parent's drag_data_received() method. */
- GTK_WIDGET_CLASS (e_name_selector_entry_parent_class)->
- drag_data_received (
- widget, context, x, y,
- selection_data, info, time);
-}
-
-static void
-e_name_selector_entry_class_init (ENameSelectorEntryClass *class)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
-
- g_type_class_add_private (class, sizeof (ENameSelectorEntryPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = name_selector_entry_set_property;
- object_class->get_property = name_selector_entry_get_property;
- object_class->dispose = name_selector_entry_dispose;
- object_class->constructed = name_selector_entry_constructed;
-
- widget_class = GTK_WIDGET_CLASS (class);
- widget_class->realize = name_selector_entry_realize;
- widget_class->drag_data_received = name_selector_entry_drag_data_received;
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- "Registry",
- "Data source registry",
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_MINIMUM_QUERY_LENGTH,
- g_param_spec_int (
- "minimum-query-length",
- "Minimum Query Length",
- NULL,
- 1, G_MAXINT,
- 3,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_ADDRESS,
- g_param_spec_boolean (
- "show-address",
- "Show Address",
- NULL,
- FALSE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- signals[UPDATED] = g_signal_new (
- "updated",
- E_TYPE_NAME_SELECTOR_ENTRY,
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (ENameSelectorEntryClass, updated),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-}
-
-/* Remove unquoted commas and control characters from string */
-static gchar *
-sanitize_string (const gchar *string)
-{
- GString *gstring;
- gboolean quoted = FALSE;
- const gchar *p;
-
- gstring = g_string_new ("");
-
- if (!string)
- return g_string_free (gstring, FALSE);
-
- for (p = string; *p; p = g_utf8_next_char (p)) {
- gunichar c = g_utf8_get_char (p);
-
- if (c == '"')
- quoted = ~quoted;
- else if (c == ',' && !quoted)
- continue;
- else if (c == '\t' || c == '\n')
- continue;
-
- g_string_append_unichar (gstring, c);
- }
-
- return g_string_free (gstring, FALSE);
-}
-
-/* Called for each list store entry whenever the user types (but not on cut/paste) */
-static gboolean
-completion_match_cb (GtkEntryCompletion *completion,
- const gchar *key,
- GtkTreeIter *iter,
- gpointer user_data)
-{
- ENS_DEBUG (g_print ("completion_match_cb, key=%s\n", key));
-
- return TRUE;
-}
-
-/* Gets context of n_unichars total (n_unicars / 2, before and after position)
- * and places them in array. If any positions would be outside the string, the
- * corresponding unichars are set to zero. */
-static void
-get_utf8_string_context (const gchar *string,
- gint position,
- gunichar *unichars,
- gint n_unichars)
-{
- gchar *p = NULL;
- gint len;
- gint gap;
- gint i;
-
- /* n_unichars must be even */
- g_assert (n_unichars % 2 == 0);
-
- len = g_utf8_strlen (string, -1);
- gap = n_unichars / 2;
-
- for (i = 0; i < n_unichars; i++) {
- gint char_pos = position - gap + i;
-
- if (char_pos < 0 || char_pos >= len) {
- unichars[i] = '\0';
- continue;
- }
-
- if (p)
- p = g_utf8_next_char (p);
- else
- p = g_utf8_offset_to_pointer (string, char_pos);
-
- unichars[i] = g_utf8_get_char (p);
- }
-}
-
-static gboolean
-get_range_at_position (const gchar *string,
- gint pos,
- gint *start_pos,
- gint *end_pos)
-{
- const gchar *p;
- gboolean quoted = FALSE;
- gint local_start_pos = 0;
- gint local_end_pos = 0;
- gint i;
-
- if (!string || !*string)
- return FALSE;
-
- for (p = string, i = 0; *p; p = g_utf8_next_char (p), i++) {
- gunichar c = g_utf8_get_char (p);
-
- if (c == '"') {
- quoted = ~quoted;
- } else if (c == ',' && !quoted) {
- if (i < pos) {
- /* Start right after comma */
- local_start_pos = i + 1;
- } else {
- /* Stop right before comma */
- local_end_pos = i;
- break;
- }
- } else if (c == ' ' && local_start_pos == i) {
- /* Adjust start to skip space after first comma */
- local_start_pos++;
- }
- }
-
- /* If we didn't hit a comma, we must've hit NULL, and ours was the last element. */
- if (!local_end_pos)
- local_end_pos = i;
-
- if (start_pos)
- *start_pos = local_start_pos;
- if (end_pos)
- *end_pos = local_end_pos;
-
- return TRUE;
-}
-
-static gboolean
-is_quoted_at (const gchar *string,
- gint pos)
-{
- const gchar *p;
- gboolean quoted = FALSE;
- gint i;
-
- for (p = string, i = 0; *p && i < pos; p = g_utf8_next_char (p), i++) {
- gunichar c = g_utf8_get_char (p);
-
- if (c == '"')
- quoted = ~quoted;
- }
-
- return quoted ? TRUE : FALSE;
-}
-
-static gint
-get_index_at_position (const gchar *string,
- gint pos)
-{
- const gchar *p;
- gboolean quoted = FALSE;
- gint n = 0;
- gint i;
-
- for (p = string, i = 0; *p && i < pos; p = g_utf8_next_char (p), i++) {
- gunichar c = g_utf8_get_char (p);
-
- if (c == '"')
- quoted = ~quoted;
- else if (c == ',' && !quoted)
- n++;
- }
-
- return n;
-}
-
-static gboolean
-get_range_by_index (const gchar *string,
- gint index,
- gint *start_pos,
- gint *end_pos)
-{
- const gchar *p;
- gboolean quoted = FALSE;
- gint i;
- gint n = 0;
-
- for (p = string, i = 0; *p && n < index; p = g_utf8_next_char (p), i++) {
- gunichar c = g_utf8_get_char (p);
-
- if (c == '"')
- quoted = ~quoted;
- if (c == ',' && !quoted)
- n++;
- }
-
- if (n < index)
- return FALSE;
-
- return get_range_at_position (string, i, start_pos, end_pos);
-}
-
-static gchar *
-get_address_at_position (const gchar *string,
- gint pos)
-{
- gint start_pos;
- gint end_pos;
- const gchar *start_p;
- const gchar *end_p;
-
- if (!get_range_at_position (string, pos, &start_pos, &end_pos))
- return NULL;
-
- start_p = g_utf8_offset_to_pointer (string, start_pos);
- end_p = g_utf8_offset_to_pointer (string, end_pos);
-
- return g_strndup (start_p, end_p - start_p);
-}
-
-/* Finds the destination in model */
-static EDestination *
-find_destination_by_index (ENameSelectorEntry *name_selector_entry,
- gint index)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
-
- path = gtk_tree_path_new_from_indices (index, -1);
- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (name_selector_entry->priv->destination_store),
- &iter, path)) {
- /* If we have zero destinations, getting a NULL destination at index 0
- * is valid. */
- if (index > 0)
- g_warning ("ENameSelectorEntry is out of sync with model!");
- gtk_tree_path_free (path);
- return NULL;
- }
- gtk_tree_path_free (path);
-
- return e_destination_store_get_destination (name_selector_entry->priv->destination_store, &iter);
-}
-
-/* Finds the destination in model */
-static EDestination *
-find_destination_at_position (ENameSelectorEntry *name_selector_entry,
- gint pos)
-{
- const gchar *text;
- gint index;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- index = get_index_at_position (text, pos);
-
- return find_destination_by_index (name_selector_entry, index);
-}
-
-/* Builds destination from our text */
-static EDestination *
-build_destination_at_position (const gchar *string,
- gint pos)
-{
- EDestination *destination;
- gchar *address;
-
- address = get_address_at_position (string, pos);
- if (!address)
- return NULL;
-
- destination = e_destination_new ();
- e_destination_set_raw (destination, address);
-
- g_free (address);
- return destination;
-}
-
-static gchar *
-name_style_query (const gchar *field,
- const gchar *value)
-{
- gchar *spaced_str;
- gchar *comma_str;
- GString *out = g_string_new ("");
- gchar **strv;
- gchar *query;
-
- spaced_str = sanitize_string (value);
- g_strstrip (spaced_str);
-
- strv = g_strsplit (spaced_str, " ", 0);
-
- if (strv[0] && strv[1]) {
- g_string_append (out, "(or ");
- comma_str = g_strjoinv (", ", strv);
- } else {
- comma_str = NULL;
- }
-
- g_string_append (out, " (beginswith ");
- e_sexp_encode_string (out, field);
- e_sexp_encode_string (out, spaced_str);
- g_string_append (out, ")");
-
- if (comma_str) {
- g_string_append (out, " (beginswith ");
-
- e_sexp_encode_string (out, field);
- g_strstrip (comma_str);
- e_sexp_encode_string (out, comma_str);
- g_string_append (out, "))");
- }
-
- query = g_string_free (out, FALSE);
-
- g_free (spaced_str);
- g_free (comma_str);
- g_strfreev (strv);
-
- return query;
-}
-
-static gchar *
-escape_sexp_string (const gchar *string)
-{
- GString *gstring;
- gchar *encoded_string;
-
- gstring = g_string_new ("");
- e_sexp_encode_string (gstring, string);
-
- encoded_string = gstring->str;
- g_string_free (gstring, FALSE);
-
- return encoded_string;
-}
-
-/**
- * ens_util_populate_user_query_fields:
- *
- * Populates list of user query fields to string usable in query string.
- * Returned pointer is either newly allocated string, supposed to be freed with g_free,
- * or NULL if no fields defined.
- *
- * Since: 2.24
- **/
-gchar *
-ens_util_populate_user_query_fields (GSList *user_query_fields,
- const gchar *cue_str,
- const gchar *encoded_cue_str)
-{
- GString *user_fields;
- GSList *s;
-
- g_return_val_if_fail (cue_str != NULL, NULL);
- g_return_val_if_fail (encoded_cue_str != NULL, NULL);
-
- user_fields = g_string_new ("");
-
- for (s = user_query_fields; s; s = s->next) {
- const gchar *field = s->data;
-
- if (!field || !*field)
- continue;
-
- if (*field == '$') {
- g_string_append_printf (user_fields, " (beginswith \"%s\" %s) ", field + 1, encoded_cue_str);
- } else if (*field == '@') {
- g_string_append_printf (user_fields, " (is \"%s\" %s) ", field + 1, encoded_cue_str);
- } else {
- gchar *tmp = name_style_query (field, cue_str);
-
- g_string_append (user_fields, " ");
- g_string_append (user_fields, tmp);
- g_string_append (user_fields, " ");
- g_free (tmp);
- }
- }
-
- return g_string_free (user_fields, !user_fields->str || !*user_fields->str);
-}
-
-static void
-set_completion_query (ENameSelectorEntry *name_selector_entry,
- const gchar *cue_str)
-{
- ENameSelectorEntryPrivate *priv;
- EBookQuery *book_query;
- gchar *query_str;
- gchar *encoded_cue_str;
- gchar *full_name_query_str;
- gchar *file_as_query_str;
- gchar *user_fields_str;
-
- priv = E_NAME_SELECTOR_ENTRY_GET_PRIVATE (name_selector_entry);
-
- if (!name_selector_entry->priv->contact_store)
- return;
-
- if (!cue_str) {
- /* Clear the store */
- e_contact_store_set_query (name_selector_entry->priv->contact_store, NULL);
- return;
- }
-
- encoded_cue_str = escape_sexp_string (cue_str);
- full_name_query_str = name_style_query ("full_name", cue_str);
- file_as_query_str = name_style_query ("file_as", cue_str);
- user_fields_str = ens_util_populate_user_query_fields (priv->user_query_fields, cue_str, encoded_cue_str);
-
- query_str = g_strdup_printf (
- "(or "
- " (beginswith \"nickname\" %s) "
- " (beginswith \"email\" %s) "
- " %s "
- " %s "
- " %s "
- ")",
- encoded_cue_str, encoded_cue_str,
- full_name_query_str, file_as_query_str,
- user_fields_str ? user_fields_str : "");
-
- g_free (user_fields_str);
- g_free (file_as_query_str);
- g_free (full_name_query_str);
- g_free (encoded_cue_str);
-
- ENS_DEBUG (g_print ("%s\n", query_str));
-
- book_query = e_book_query_from_string (query_str);
- e_contact_store_set_query (name_selector_entry->priv->contact_store, book_query);
- e_book_query_unref (book_query);
-
- g_free (query_str);
-}
-
-static gchar *
-get_entry_substring (ENameSelectorEntry *name_selector_entry,
- gint range_start,
- gint range_end)
-{
- const gchar *entry_text;
- gchar *p0, *p1;
-
- entry_text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
-
- p0 = g_utf8_offset_to_pointer (entry_text, range_start);
- p1 = g_utf8_offset_to_pointer (entry_text, range_end);
-
- return g_strndup (p0, p1 - p0);
-}
-
-static gint
-utf8_casefold_collate_len (const gchar *str1,
- const gchar *str2,
- gint len)
-{
- gchar *s1 = g_utf8_casefold (str1, len);
- gchar *s2 = g_utf8_casefold (str2, len);
- gint rv;
-
- rv = g_utf8_collate (s1, s2);
-
- g_free (s1);
- g_free (s2);
-
- return rv;
-}
-
-static gchar *
-build_textrep_for_contact (EContact *contact,
- EContactField cue_field)
-{
- gchar *name = NULL;
- gchar *email = NULL;
- gchar *textrep;
-
- switch (cue_field) {
- case E_CONTACT_FULL_NAME:
- case E_CONTACT_NICKNAME:
- case E_CONTACT_FILE_AS:
- name = e_contact_get (contact, cue_field);
- email = e_contact_get (contact, E_CONTACT_EMAIL_1);
- break;
-
- case E_CONTACT_EMAIL_1:
- case E_CONTACT_EMAIL_2:
- case E_CONTACT_EMAIL_3:
- case E_CONTACT_EMAIL_4:
- name = NULL;
- email = e_contact_get (contact, cue_field);
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
-
- g_assert (email);
- g_assert (strlen (email) > 0);
-
- if (name)
- textrep = g_strdup_printf ("%s <%s>", name, email);
- else
- textrep = g_strdup_printf ("%s", email);
-
- g_free (name);
- g_free (email);
- return textrep;
-}
-
-static gboolean
-contact_match_cue (ENameSelectorEntry *name_selector_entry,
- EContact *contact,
- const gchar *cue_str,
- EContactField *matched_field,
- gint *matched_field_rank)
-{
- EContactField fields[] = { E_CONTACT_FULL_NAME, E_CONTACT_NICKNAME, E_CONTACT_FILE_AS,
- E_CONTACT_EMAIL_1, E_CONTACT_EMAIL_2, E_CONTACT_EMAIL_3,
- E_CONTACT_EMAIL_4 };
- gchar *email;
- gboolean result = FALSE;
- gint cue_len;
- gint i;
-
- g_assert (contact);
- g_assert (cue_str);
-
- if (g_utf8_strlen (cue_str, -1) < name_selector_entry->priv->minimum_query_length)
- return FALSE;
-
- cue_len = strlen (cue_str);
-
- /* Make sure contact has an email address */
- email = e_contact_get (contact, E_CONTACT_EMAIL_1);
- if (!email || !*email) {
- g_free (email);
- return FALSE;
- }
- g_free (email);
-
- for (i = 0; i < G_N_ELEMENTS (fields); i++) {
- gchar *value;
- gchar *value_sane;
-
- /* Don't match e-mail addresses in contact lists */
- if (e_contact_get (contact, E_CONTACT_IS_LIST) &&
- fields[i] >= E_CONTACT_FIRST_EMAIL_ID &&
- fields[i] <= E_CONTACT_LAST_EMAIL_ID)
- continue;
-
- value = e_contact_get (contact, fields[i]);
- if (!value)
- continue;
-
- value_sane = sanitize_string (value);
- g_free (value);
-
- ENS_DEBUG (g_print ("Comparing '%s' to '%s'\n", value, cue_str));
-
- if (!utf8_casefold_collate_len (value_sane, cue_str, cue_len)) {
- if (matched_field)
- *matched_field = fields [i];
- if (matched_field_rank)
- *matched_field_rank = i;
-
- result = TRUE;
- g_free (value_sane);
- break;
- }
- g_free (value_sane);
- }
-
- return result;
-}
-
-static gboolean
-find_existing_completion (ENameSelectorEntry *name_selector_entry,
- const gchar *cue_str,
- EContact **contact,
- gchar **text,
- EContactField *matched_field,
- EBookClient **book_client)
-{
- GtkTreeIter iter;
- EContact *best_contact = NULL;
- gint best_field_rank = G_MAXINT;
- EContactField best_field = 0;
- EBookClient *best_book_client = NULL;
-
- g_assert (cue_str);
-
- if (!name_selector_entry->priv->contact_store)
- return FALSE;
-
- ENS_DEBUG (g_print ("Completing '%s'\n", cue_str));
-
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (name_selector_entry->priv->contact_store), &iter))
- return FALSE;
-
- do {
- EContact *current_contact;
- gint current_field_rank;
- EContactField current_field;
- gboolean matches;
-
- current_contact = e_contact_store_get_contact (name_selector_entry->priv->contact_store, &iter);
- if (!current_contact)
- continue;
-
- matches = contact_match_cue (name_selector_entry, current_contact, cue_str, ¤t_field, ¤t_field_rank);
- if (matches && current_field_rank < best_field_rank) {
- best_contact = current_contact;
- best_field_rank = current_field_rank;
- best_field = current_field;
- best_book_client = e_contact_store_get_client (name_selector_entry->priv->contact_store, &iter);
- }
- } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (name_selector_entry->priv->contact_store), &iter));
-
- if (!best_contact)
- return FALSE;
-
- if (contact)
- *contact = best_contact;
- if (text)
- *text = build_textrep_for_contact (best_contact, best_field);
- if (matched_field)
- *matched_field = best_field;
- if (book_client)
- *book_client = best_book_client;
-
- return TRUE;
-}
-
-static void
-generate_attribute_list (ENameSelectorEntry *name_selector_entry)
-{
- PangoLayout *layout;
- PangoAttrList *attr_list;
- const gchar *text;
- gint i;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- layout = gtk_entry_get_layout (GTK_ENTRY (name_selector_entry));
-
- /* Set up the attribute list */
-
- attr_list = pango_attr_list_new ();
-
- if (name_selector_entry->priv->attr_list)
- pango_attr_list_unref (name_selector_entry->priv->attr_list);
-
- name_selector_entry->priv->attr_list = attr_list;
-
- /* Parse the entry's text and apply attributes to real contacts */
-
- for (i = 0; ; i++) {
- EDestination *destination;
- PangoAttribute *attr;
- gint start_pos;
- gint end_pos;
-
- if (!get_range_by_index (text, i, &start_pos, &end_pos))
- break;
-
- destination = find_destination_at_position (name_selector_entry, start_pos);
-
- /* Destination will be NULL if we have no entries */
- if (!destination || !e_destination_get_contact (destination))
- continue;
-
- attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
- attr->start_index = g_utf8_offset_to_pointer (text, start_pos) - text;
- attr->end_index = g_utf8_offset_to_pointer (text, end_pos) - text;
- pango_attr_list_insert (attr_list, attr);
- }
-
- pango_layout_set_attributes (layout, attr_list);
-}
-
-static gboolean
-draw_event (ENameSelectorEntry *name_selector_entry)
-{
- PangoLayout *layout;
-
- layout = gtk_entry_get_layout (GTK_ENTRY (name_selector_entry));
- pango_layout_set_attributes (layout, name_selector_entry->priv->attr_list);
-
- return FALSE;
-}
-
-static void
-type_ahead_complete (ENameSelectorEntry *name_selector_entry)
-{
- EContact *contact;
- EBookClient *book_client = NULL;
- EContactField matched_field;
- EDestination *destination;
- gint cursor_pos;
- gint range_start = 0;
- gint range_end = 0;
- gint pos = 0;
- gchar *textrep;
- gint textrep_len;
- gint range_len;
- const gchar *text;
- gchar *cue_str;
- gchar *temp_str;
- ENameSelectorEntryPrivate *priv;
-
- priv = E_NAME_SELECTOR_ENTRY_GET_PRIVATE (name_selector_entry);
-
- cursor_pos = gtk_editable_get_position (GTK_EDITABLE (name_selector_entry));
- if (cursor_pos < 0)
- return;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- get_range_at_position (text, cursor_pos, &range_start, &range_end);
- range_len = range_end - range_start;
- if (range_len < priv->minimum_query_length)
- return;
-
- destination = find_destination_at_position (name_selector_entry, cursor_pos);
-
- cue_str = get_entry_substring (name_selector_entry, range_start, range_end);
- if (!find_existing_completion (name_selector_entry, cue_str, &contact,
- &textrep, &matched_field, &book_client)) {
- g_free (cue_str);
- return;
- }
-
- temp_str = sanitize_string (textrep);
- g_free (textrep);
- textrep = temp_str;
-
- textrep_len = g_utf8_strlen (textrep, -1);
- pos = range_start;
-
- g_signal_handlers_block_by_func (
- name_selector_entry,
- user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (
- name_selector_entry,
- user_delete_text, name_selector_entry);
- g_signal_handlers_block_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_changed, name_selector_entry);
-
- if (textrep_len > range_len) {
- gint i;
-
- /* keep character's case as user types */
- for (i = 0; textrep[i] && cue_str[i]; i++)
- textrep[i] = cue_str[i];
-
- gtk_editable_delete_text (
- GTK_EDITABLE (name_selector_entry),
- range_start, range_end);
- gtk_editable_insert_text (
- GTK_EDITABLE (name_selector_entry),
- textrep, -1, &pos);
- gtk_editable_select_region (
- GTK_EDITABLE (name_selector_entry),
- range_end, range_start + textrep_len);
- priv->is_completing = TRUE;
- }
- g_free (cue_str);
-
- if (contact && destination) {
- gint email_n = 0;
-
- if (matched_field >= E_CONTACT_FIRST_EMAIL_ID && matched_field <= E_CONTACT_LAST_EMAIL_ID)
- email_n = matched_field - E_CONTACT_FIRST_EMAIL_ID;
-
- e_destination_set_contact (destination, contact, email_n);
- if (book_client)
- e_destination_set_client (destination, book_client);
- generate_attribute_list (name_selector_entry);
- }
-
- g_signal_handlers_unblock_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_changed, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- g_free (textrep);
-}
-
-static void
-clear_completion_model (ENameSelectorEntry *name_selector_entry)
-{
- ENameSelectorEntryPrivate *priv;
-
- priv = E_NAME_SELECTOR_ENTRY_GET_PRIVATE (name_selector_entry);
-
- if (!name_selector_entry->priv->contact_store)
- return;
-
- e_contact_store_set_query (name_selector_entry->priv->contact_store, NULL);
- priv->is_completing = FALSE;
-}
-
-static void
-update_completion_model (ENameSelectorEntry *name_selector_entry)
-{
- const gchar *text;
- gint cursor_pos;
- gint range_start = 0;
- gint range_end = 0;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- cursor_pos = gtk_editable_get_position (GTK_EDITABLE (name_selector_entry));
-
- if (cursor_pos >= 0)
- get_range_at_position (text, cursor_pos, &range_start, &range_end);
-
- if (range_end - range_start >= name_selector_entry->priv->minimum_query_length && cursor_pos == range_end) {
- gchar *cue_str;
-
- cue_str = get_entry_substring (name_selector_entry, range_start, range_end);
- set_completion_query (name_selector_entry, cue_str);
- g_free (cue_str);
- } else {
- /* N/A; Clear completion model */
- clear_completion_model (name_selector_entry);
- }
-}
-
-static gboolean
-type_ahead_complete_on_timeout_cb (ENameSelectorEntry *name_selector_entry)
-{
- type_ahead_complete (name_selector_entry);
- name_selector_entry->priv->type_ahead_complete_cb_id = 0;
- return FALSE;
-}
-
-static gboolean
-update_completions_on_timeout_cb (ENameSelectorEntry *name_selector_entry)
-{
- update_completion_model (name_selector_entry);
- name_selector_entry->priv->update_completions_cb_id = 0;
- return FALSE;
-}
-
-static void
-insert_destination_at_position (ENameSelectorEntry *name_selector_entry,
- gint pos)
-{
- EDestination *destination;
- const gchar *text;
- gint index;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- index = get_index_at_position (text, pos);
-
- destination = build_destination_at_position (text, pos);
- g_assert (destination);
-
- g_signal_handlers_block_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_inserted, name_selector_entry);
- e_destination_store_insert_destination (
- name_selector_entry->priv->destination_store,
- index, destination);
- g_signal_handlers_unblock_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_inserted, name_selector_entry);
- g_object_unref (destination);
-}
-
-static void
-modify_destination_at_position (ENameSelectorEntry *name_selector_entry,
- gint pos)
-{
- EDestination *destination;
- const gchar *text;
- gchar *raw_address;
- gboolean rebuild_attributes = FALSE;
-
- destination = find_destination_at_position (name_selector_entry, pos);
- if (!destination)
- return;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- raw_address = get_address_at_position (text, pos);
- g_assert (raw_address);
-
- if (e_destination_get_contact (destination))
- rebuild_attributes = TRUE;
-
- g_signal_handlers_block_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_changed, name_selector_entry);
- e_destination_set_raw (destination, raw_address);
- g_signal_handlers_unblock_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_changed, name_selector_entry);
-
- g_free (raw_address);
-
- if (rebuild_attributes)
- generate_attribute_list (name_selector_entry);
-}
-
-static gchar *
-get_destination_textrep (ENameSelectorEntry *name_selector_entry,
- EDestination *destination)
-{
- gboolean show_email = e_name_selector_entry_get_show_address (name_selector_entry);
- EContact *contact;
-
- g_return_val_if_fail (destination != NULL, NULL);
-
- contact = e_destination_get_contact (destination);
-
- if (!show_email) {
- if (contact && !e_contact_get (contact, E_CONTACT_IS_LIST)) {
- GList *email_list;
-
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- show_email = g_list_length (email_list) > 1;
- deep_free_list (email_list);
- }
- }
-
- /* do not show emails for contact lists even user forces it */
- if (show_email && contact && e_contact_get (contact, E_CONTACT_IS_LIST))
- show_email = FALSE;
-
- return sanitize_string (e_destination_get_textrep (destination, show_email));
-}
-
-static void
-sync_destination_at_position (ENameSelectorEntry *name_selector_entry,
- gint range_pos,
- gint *cursor_pos)
-{
- EDestination *destination;
- const gchar *text;
- gchar *address;
- gint address_len;
- gint range_start, range_end;
-
- /* Get the destination we're looking at. Note that the entry may be empty, and so
- * there may not be one. */
- destination = find_destination_at_position (name_selector_entry, range_pos);
- if (!destination)
- return;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- if (!get_range_at_position (text, range_pos, &range_start, &range_end)) {
- g_warning ("ENameSelectorEntry is out of sync with model!");
- return;
- }
-
- address = get_destination_textrep (name_selector_entry, destination);
- address_len = g_utf8_strlen (address, -1);
-
- if (cursor_pos) {
- /* Update cursor placement */
- if (*cursor_pos >= range_end)
- *cursor_pos += address_len - (range_end - range_start);
- else if (*cursor_pos > range_start)
- *cursor_pos = range_start + address_len;
- }
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), range_start, range_end);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), address, -1, &range_start);
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- generate_attribute_list (name_selector_entry);
- g_free (address);
-}
-
-static void
-remove_destination_by_index (ENameSelectorEntry *name_selector_entry,
- gint index)
-{
- EDestination *destination;
-
- destination = find_destination_by_index (name_selector_entry, index);
- if (destination) {
- g_signal_handlers_block_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_deleted, name_selector_entry);
- e_destination_store_remove_destination (
- name_selector_entry->priv->destination_store,
- destination);
- g_signal_handlers_unblock_by_func (
- name_selector_entry->priv->destination_store,
- destination_row_deleted, name_selector_entry);
- }
-}
-
-static void
-post_insert_update (ENameSelectorEntry *name_selector_entry,
- gint position)
-{
- const gchar *text;
- glong length;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- length = g_utf8_strlen (text, -1);
- text = g_utf8_next_char (text);
-
- if (*text == '\0') {
- /* First and only character, create initial destination. */
- insert_destination_at_position (name_selector_entry, 0);
- } else {
- /* Modified an existing destination. */
- modify_destination_at_position (name_selector_entry, position);
- }
-
- /* If editing within the string, regenerate attributes. */
- if (position < length)
- generate_attribute_list (name_selector_entry);
-}
-
-/* Returns the number of characters inserted */
-static gint
-insert_unichar (ENameSelectorEntry *name_selector_entry,
- gint *pos,
- gunichar c)
-{
- const gchar *text;
- gunichar str_context[4];
- gchar buf[7];
- gint len;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- get_utf8_string_context (text, *pos, str_context, 4);
-
- /* Space is not allowed:
- * - Before or after another space.
- * - At start of string. */
-
- if (c == ' ' && (str_context[1] == ' ' || str_context[1] == '\0' || str_context[2] == ' '))
- return 0;
-
- /* Comma is not allowed:
- * - After another comma.
- * - At start of string. */
-
- if (c == ',' && !is_quoted_at (text, *pos)) {
- gint start_pos;
- gint end_pos;
- gboolean at_start = FALSE;
- gboolean at_end = FALSE;
-
- if (str_context[1] == ',' || str_context[1] == '\0')
- return 0;
-
- /* We do this so we can avoid disturbing destinations with completed contacts
- * either before or after the destination being inserted. */
- get_range_at_position (text, *pos, &start_pos, &end_pos);
- if (*pos <= start_pos)
- at_start = TRUE;
- if (*pos >= end_pos)
- at_end = TRUE;
-
- /* Must insert comma first, so modify_destination_at_position can do its job
- * correctly, splitting up the contact if necessary. */
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ", ", -1, pos);
-
- /* Update model */
- g_assert (*pos >= 2);
-
- /* If we inserted the comma at the end of, or in the middle of, an existing
- * address, add a new destination for what appears after comma. Else, we
- * have to add a destination for what appears before comma (a blank one). */
- if (at_end) {
- /* End: Add last, sync first */
- insert_destination_at_position (name_selector_entry, *pos);
- sync_destination_at_position (name_selector_entry, *pos - 2, pos);
- /* Sync generates the attributes list */
- } else if (at_start) {
- /* Start: Add first */
- insert_destination_at_position (name_selector_entry, *pos - 2);
- generate_attribute_list (name_selector_entry);
- } else {
- /* Middle: */
- insert_destination_at_position (name_selector_entry, *pos);
- modify_destination_at_position (name_selector_entry, *pos - 2);
- generate_attribute_list (name_selector_entry);
- }
-
- return 2;
- }
-
- /* Generic case. Allowed spaces also end up here. */
-
- len = g_unichar_to_utf8 (c, buf);
- buf[len] = '\0';
-
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), buf, -1, pos);
-
- post_insert_update (name_selector_entry, *pos);
-
- return 1;
-}
-
-static void
-user_insert_text (ENameSelectorEntry *name_selector_entry,
- gchar *new_text,
- gint new_text_length,
- gint *position,
- gpointer user_data)
-{
- gint chars_inserted = 0;
- gboolean fast_insert;
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- fast_insert =
- (g_utf8_strchr (new_text, new_text_length, ' ') == NULL) &&
- (g_utf8_strchr (new_text, new_text_length, ',') == NULL);
-
- /* If the text to insert does not contain spaces or commas,
- * insert all of it at once. This avoids confusing on-going
- * input method behavior. */
- if (fast_insert) {
- gint old_position = *position;
-
- gtk_editable_insert_text (
- GTK_EDITABLE (name_selector_entry),
- new_text, new_text_length, position);
-
- chars_inserted = *position - old_position;
- if (chars_inserted > 0)
- post_insert_update (name_selector_entry, *position);
-
- /* Otherwise, apply some rules as to where spaces and commas
- * can be inserted, and insert a trailing space after comma. */
- } else {
- const gchar *cp;
-
- for (cp = new_text; *cp; cp = g_utf8_next_char (cp)) {
- gunichar uc = g_utf8_get_char (cp);
- insert_unichar (name_selector_entry, position, uc);
- chars_inserted++;
- }
- }
-
- if (chars_inserted >= 1) {
- /* If the user inserted one character, kick off completion */
- re_set_timeout (name_selector_entry->priv->update_completions_cb_id, update_completions_on_timeout_cb, name_selector_entry);
- re_set_timeout (name_selector_entry->priv->type_ahead_complete_cb_id, type_ahead_complete_on_timeout_cb, name_selector_entry);
- }
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- g_signal_stop_emission_by_name (name_selector_entry, "insert_text");
-}
-
-static void
-user_delete_text (ENameSelectorEntry *name_selector_entry,
- gint start_pos,
- gint end_pos,
- gpointer user_data)
-{
- const gchar *text;
- gint index_start, index_end;
- gint selection_start, selection_end;
- gunichar str_context[2], str_b_context[2];
- gint len;
- gint i;
- gboolean del_space = FALSE, del_comma = FALSE;
-
- if (start_pos == end_pos)
- return;
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- len = g_utf8_strlen (text, -1);
-
- if (end_pos == -1)
- end_pos = len;
-
- gtk_editable_get_selection_bounds (
- GTK_EDITABLE (name_selector_entry),
- &selection_start, &selection_end);
-
- get_utf8_string_context (text, start_pos, str_context, 2);
- get_utf8_string_context (text, end_pos, str_b_context, 2);
-
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- if (end_pos - start_pos == 1) {
- /* Might be backspace; update completion model so dropdown is accurate */
- re_set_timeout (name_selector_entry->priv->update_completions_cb_id, update_completions_on_timeout_cb, name_selector_entry);
- }
-
- index_start = get_index_at_position (text, start_pos);
- index_end = get_index_at_position (text, end_pos);
-
- g_signal_stop_emission_by_name (name_selector_entry, "delete_text");
-
- /* If the deletion touches more than one destination, the first one is changed
- * and the rest are removed. If the last destination wasn't completely deleted,
- * it becomes part of the first one, since the separator between them was
- * removed.
- *
- * Here, we let the model know about removals. */
- for (i = index_end; i > index_start; i--) {
- EDestination *destination = find_destination_by_index (name_selector_entry, i);
- gint range_start, range_end;
- gchar *ttext;
- const gchar *email = NULL;
- gboolean sel = FALSE;
-
- if (destination)
- email = e_destination_get_textrep (destination, TRUE);
-
- if (!email || !*email)
- continue;
-
- if (!get_range_by_index (text, i, &range_start, &range_end)) {
- g_warning ("ENameSelectorEntry is out of sync with model!");
- return;
- }
-
- if ((selection_start < range_start && selection_end > range_start) ||
- (selection_end > range_start && selection_end < range_end))
- sel = TRUE;
-
- if (!sel) {
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), range_start, range_end);
-
- ttext = sanitize_string (email);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ttext, -1, &range_start);
- g_free (ttext);
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- }
-
- remove_destination_by_index (name_selector_entry, i);
- }
-
- /* Do the actual deletion */
-
- if (end_pos == start_pos +1 && index_end == index_start) {
- /* We could be just deleting the empty text */
- gchar *c;
-
- /* Get the actual deleted text */
- c = gtk_editable_get_chars (GTK_EDITABLE (name_selector_entry), start_pos, start_pos + 1);
-
- if ( c[0] == ' ') {
- /* If we are at the beginning or removing junk space, let us ignore it */
- del_space = TRUE;
- }
- g_free (c);
- } else if (end_pos == start_pos +1 && index_end == index_start + 1) {
- /* We could be just deleting the empty text */
- gchar *c;
-
- /* Get the actual deleted text */
- c = gtk_editable_get_chars (GTK_EDITABLE (name_selector_entry), start_pos, start_pos + 1);
-
- if ( c[0] == ',' && !is_quoted_at (text, start_pos)) {
- /* If we are at the beginning or removing junk space, let us ignore it */
- del_comma = TRUE;
- }
- g_free (c);
- }
-
- if (del_comma) {
- gint range_start=-1, range_end;
- EDestination *dest = find_destination_by_index (name_selector_entry, index_end);
- /* If we have deleted the last comma, let us autocomplete normally
- */
-
- if (dest && len - end_pos != 0) {
-
- EDestination *destination1 = find_destination_by_index (name_selector_entry, index_start);
- gchar *ttext;
- const gchar *email = NULL;
-
- if (destination1)
- email = e_destination_get_textrep (destination1, TRUE);
-
- if (email && *email) {
-
- if (!get_range_by_index (text, i, &range_start, &range_end)) {
- g_warning ("ENameSelectorEntry is out of sync with model!");
- return;
- }
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), range_start, range_end);
-
- ttext = sanitize_string (email);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ttext, -1, &range_start);
- g_free (ttext);
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- }
-
- if (range_start != -1) {
- start_pos = range_start;
- end_pos = start_pos + 1;
- gtk_editable_set_position (GTK_EDITABLE (name_selector_entry),start_pos);
- }
- }
- }
- gtk_editable_delete_text (
- GTK_EDITABLE (name_selector_entry),
- start_pos, end_pos);
-
- /*If the user is deleting a '"' new destinations have to be created for ',' between the quoted text
- Like "fd,ty,uy" is a one entity, but if you remove the quotes it has to be broken doan into 3 seperate
- addresses.
- */
-
- if (str_b_context[1] == '"') {
- const gchar *p;
- gint j;
- p = text + end_pos;
- for (p = text + (end_pos - 1), j = end_pos - 1; *p && *p != '"' ; p = g_utf8_next_char (p), j++) {
- gunichar c = g_utf8_get_char (p);
- if (c == ',') {
- insert_destination_at_position (name_selector_entry, j + 1);
- }
- }
-
- }
-
- /* Let model know about changes */
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- if (!*text || strlen (text) <= 0) {
- /* If the entry was completely cleared, remove the initial destination too */
- remove_destination_by_index (name_selector_entry, 0);
- generate_attribute_list (name_selector_entry);
- } else if (!del_space) {
- modify_destination_at_position (name_selector_entry, start_pos);
- }
-
- /* If editing within the string, we need to regenerate attributes */
- if (end_pos < len)
- generate_attribute_list (name_selector_entry);
-
- /* Prevent type-ahead completion */
- if (name_selector_entry->priv->type_ahead_complete_cb_id) {
- g_source_remove (name_selector_entry->priv->type_ahead_complete_cb_id);
- name_selector_entry->priv->type_ahead_complete_cb_id = 0;
- }
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-}
-
-static gboolean
-completion_match_selected (ENameSelectorEntry *name_selector_entry,
- ETreeModelGenerator *email_generator_model,
- GtkTreeIter *generator_iter)
-{
- EContact *contact;
- EBookClient *book_client;
- EDestination *destination;
- gint cursor_pos;
- GtkTreeIter contact_iter;
- gint email_n;
-
- if (!name_selector_entry->priv->contact_store)
- return FALSE;
-
- g_return_val_if_fail (name_selector_entry->priv->email_generator == email_generator_model, FALSE);
-
- e_tree_model_generator_convert_iter_to_child_iter (
- email_generator_model,
- &contact_iter, &email_n,
- generator_iter);
-
- contact = e_contact_store_get_contact (name_selector_entry->priv->contact_store, &contact_iter);
- book_client = e_contact_store_get_client (name_selector_entry->priv->contact_store, &contact_iter);
- cursor_pos = gtk_editable_get_position (GTK_EDITABLE (name_selector_entry));
-
- /* Set the contact in the model's destination */
-
- destination = find_destination_at_position (name_selector_entry, cursor_pos);
- e_destination_set_contact (destination, contact, email_n);
- if (book_client)
- e_destination_set_client (destination, book_client);
- sync_destination_at_position (name_selector_entry, cursor_pos, &cursor_pos);
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ", ", -1, &cursor_pos);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- /*Add destination at end for next entry*/
- insert_destination_at_position (name_selector_entry, cursor_pos);
- /* Place cursor at end of address */
-
- gtk_editable_set_position (GTK_EDITABLE (name_selector_entry), cursor_pos);
- g_signal_emit (name_selector_entry, signals[UPDATED], 0, destination, NULL);
- return TRUE;
-}
-
-static void
-entry_activate (ENameSelectorEntry *name_selector_entry)
-{
- gint cursor_pos;
- gint range_start, range_end;
- ENameSelectorEntryPrivate *priv;
- EDestination *destination;
- gint range_len;
- const gchar *text;
- gchar *cue_str;
-
- cursor_pos = gtk_editable_get_position (GTK_EDITABLE (name_selector_entry));
- if (cursor_pos < 0)
- return;
-
- priv = E_NAME_SELECTOR_ENTRY_GET_PRIVATE (name_selector_entry);
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- if (!get_range_at_position (text, cursor_pos, &range_start, &range_end))
- return;
-
- range_len = range_end - range_start;
- if (range_len < priv->minimum_query_length)
- return;
-
- destination = find_destination_at_position (name_selector_entry, cursor_pos);
- if (!destination)
- return;
-
- cue_str = get_entry_substring (name_selector_entry, range_start, range_end);
-#if 0
- if (!find_existing_completion (name_selector_entry, cue_str, &contact,
- &textrep, &matched_field)) {
- g_free (cue_str);
- return;
- }
-#endif
- g_free (cue_str);
- sync_destination_at_position (name_selector_entry, cursor_pos, &cursor_pos);
-
- /* Place cursor at end of address */
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- get_range_at_position (text, cursor_pos, &range_start, &range_end);
-
- if (priv->is_completing) {
- gchar *str_context = NULL;
-
- str_context = gtk_editable_get_chars (GTK_EDITABLE (name_selector_entry), range_end, range_end + 1);
-
- if (str_context[0] != ',') {
- /* At the end*/
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ", ", -1, &range_end);
- } else {
- /* In the middle */
- gint newpos = strlen (text);
-
- /* Doing this we can make sure that It wont ask for completion again. */
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ", ", -1, &newpos);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), newpos - 2, newpos);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- /* Move it close to next destination*/
- range_end = range_end + 2;
-
- }
- g_free (str_context);
- }
-
- gtk_editable_set_position (GTK_EDITABLE (name_selector_entry), range_end);
- g_signal_emit (name_selector_entry, signals[UPDATED], 0, destination, NULL);
-
- if (priv->is_completing)
- clear_completion_model (name_selector_entry);
-}
-
-static void
-update_text (ENameSelectorEntry *name_selector_entry,
- const gchar *text)
-{
- gint start = 0, end = 0;
- gboolean has_selection;
-
- has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (name_selector_entry), &start, &end);
-
- gtk_entry_set_text (GTK_ENTRY (name_selector_entry), text);
-
- if (has_selection)
- gtk_editable_select_region (GTK_EDITABLE (name_selector_entry), start, end);
-}
-
-static void
-sanitize_entry (ENameSelectorEntry *name_selector_entry)
-{
- gint n;
- GList *l, *known, *del = NULL;
- GString *str = g_string_new ("");
-
- g_signal_handlers_block_matched (name_selector_entry, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
- g_signal_handlers_block_matched (name_selector_entry->priv->destination_store, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
-
- known = e_destination_store_list_destinations (name_selector_entry->priv->destination_store);
- for (l = known, n = 0; l != NULL; l = l->next, n++) {
- EDestination *dest = l->data;
-
- if (!dest || !e_destination_get_address (dest))
- del = g_list_prepend (del, GINT_TO_POINTER (n));
- else {
- gchar *text;
-
- text = get_destination_textrep (name_selector_entry, dest);
- if (text) {
- if (str->str && str->str[0])
- g_string_append (str, ", ");
-
- g_string_append (str, text);
- }
- g_free (text);
- }
- }
- g_list_free (known);
-
- for (l = del; l != NULL; l = l->next) {
- e_destination_store_remove_destination_nth (name_selector_entry->priv->destination_store, GPOINTER_TO_INT (l->data));
- }
- g_list_free (del);
-
- update_text (name_selector_entry, str->str);
-
- g_string_free (str, TRUE);
-
- g_signal_handlers_unblock_matched (name_selector_entry->priv->destination_store, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
- g_signal_handlers_unblock_matched (name_selector_entry, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
-
- generate_attribute_list (name_selector_entry);
-}
-
-static gboolean
-user_focus_in (ENameSelectorEntry *name_selector_entry,
- GdkEventFocus *event_focus)
-{
- gint n;
- GList *l, *known;
- GString *str = g_string_new ("");
- EDestination *dest_dummy = e_destination_new ();
-
- g_signal_handlers_block_matched (name_selector_entry, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
- g_signal_handlers_block_matched (name_selector_entry->priv->destination_store, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
-
- known = e_destination_store_list_destinations (name_selector_entry->priv->destination_store);
- for (l = known, n = 0; l != NULL; l = l->next, n++) {
- EDestination *dest = l->data;
-
- if (dest) {
- gchar *text;
-
- text = get_destination_textrep (name_selector_entry, dest);
- if (text) {
- if (str->str && str->str[0])
- g_string_append (str, ", ");
-
- g_string_append (str, text);
- }
- g_free (text);
- }
- }
- g_list_free (known);
-
- /* Add a blank destination */
- e_destination_store_append_destination (name_selector_entry->priv->destination_store, dest_dummy);
- if (str->str && str->str[0])
- g_string_append (str, ", ");
-
- gtk_entry_set_text (GTK_ENTRY (name_selector_entry), str->str);
-
- g_string_free (str, TRUE);
-
- g_signal_handlers_unblock_matched (name_selector_entry->priv->destination_store, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
- g_signal_handlers_unblock_matched (name_selector_entry, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, name_selector_entry);
-
- generate_attribute_list (name_selector_entry);
-
- return FALSE;
-}
-
-static gboolean
-user_focus_out (ENameSelectorEntry *name_selector_entry,
- GdkEventFocus *event_focus)
-{
- if (!event_focus->in) {
- entry_activate (name_selector_entry);
- }
-
- if (name_selector_entry->priv->type_ahead_complete_cb_id) {
- g_source_remove (name_selector_entry->priv->type_ahead_complete_cb_id);
- name_selector_entry->priv->type_ahead_complete_cb_id = 0;
- }
-
- if (name_selector_entry->priv->update_completions_cb_id) {
- g_source_remove (name_selector_entry->priv->update_completions_cb_id);
- name_selector_entry->priv->update_completions_cb_id = 0;
- }
-
- clear_completion_model (name_selector_entry);
-
- if (!event_focus->in) {
- sanitize_entry (name_selector_entry);
- }
-
- return FALSE;
-}
-
-static void
-deep_free_list (GList *list)
-{
- GList *l;
-
- for (l = list; l; l = g_list_next (l))
- g_free (l->data);
-
- g_list_free (list);
-}
-
-/* Given a widget, determines the height that text will normally be drawn. */
-static guint
-entry_height (GtkWidget *widget)
-{
- PangoLayout *layout;
- gint bound;
-
- g_return_val_if_fail (widget != NULL, 0);
-
- layout = gtk_widget_create_pango_layout (widget, NULL);
-
- pango_layout_get_pixel_size (layout, NULL, &bound);
-
- return bound;
-}
-
-static void
-contact_layout_pixbuffer (GtkCellLayout *cell_layout,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- ENameSelectorEntry *name_selector_entry)
-{
- EContact *contact;
- GtkTreeIter generator_iter;
- GtkTreeIter contact_store_iter;
- gint email_n;
- EContactPhoto *photo;
- GdkPixbuf *pixbuf = NULL;
-
- if (!name_selector_entry->priv->contact_store)
- return;
-
- gtk_tree_model_filter_convert_iter_to_child_iter (
- GTK_TREE_MODEL_FILTER (model),
- &generator_iter, iter);
- e_tree_model_generator_convert_iter_to_child_iter (
- name_selector_entry->priv->email_generator,
- &contact_store_iter, &email_n,
- &generator_iter);
-
- contact = e_contact_store_get_contact (name_selector_entry->priv->contact_store, &contact_store_iter);
- if (!contact) {
- g_object_set (cell, "pixbuf", pixbuf, NULL);
- return;
- }
-
- photo = e_contact_get (contact, E_CONTACT_PHOTO);
- if (photo && photo->type == E_CONTACT_PHOTO_TYPE_INLINED) {
- guint max_height = entry_height (GTK_WIDGET (name_selector_entry));
- GdkPixbufLoader *loader;
-
- loader = gdk_pixbuf_loader_new ();
- if (gdk_pixbuf_loader_write (loader, (guchar *) photo->data.inlined.data, photo->data.inlined.length, NULL) &&
- gdk_pixbuf_loader_close (loader, NULL)) {
- pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
- if (pixbuf)
- g_object_ref (pixbuf);
- }
- g_object_unref (loader);
-
- if (pixbuf) {
- gint w, h;
- gdouble scale = 1.0;
-
- w = gdk_pixbuf_get_width (pixbuf);
- h = gdk_pixbuf_get_height (pixbuf);
-
- if (h > w)
- scale = max_height / (double) h;
- else
- scale = max_height / (double) w;
-
- if (scale < 1.0) {
- GdkPixbuf *tmp;
-
- tmp = gdk_pixbuf_scale_simple (pixbuf, w * scale, h * scale, GDK_INTERP_BILINEAR);
- g_object_unref (pixbuf);
- pixbuf = tmp;
- }
-
- }
- }
-
- e_contact_photo_free (photo);
-
- g_object_set (cell, "pixbuf", pixbuf, NULL);
-
- if (pixbuf)
- g_object_unref (pixbuf);
-}
-
-static void
-contact_layout_formatter (GtkCellLayout *cell_layout,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- ENameSelectorEntry *name_selector_entry)
-{
- EContact *contact;
- GtkTreeIter generator_iter;
- GtkTreeIter contact_store_iter;
- GList *email_list;
- gchar *string;
- gchar *file_as_str;
- gchar *email_str;
- gint email_n;
-
- if (!name_selector_entry->priv->contact_store)
- return;
-
- gtk_tree_model_filter_convert_iter_to_child_iter (
- GTK_TREE_MODEL_FILTER (model),
- &generator_iter, iter);
- e_tree_model_generator_convert_iter_to_child_iter (
- name_selector_entry->priv->email_generator,
- &contact_store_iter, &email_n,
- &generator_iter);
-
- contact = e_contact_store_get_contact (name_selector_entry->priv->contact_store, &contact_store_iter);
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- email_str = g_list_nth_data (email_list, email_n);
- file_as_str = e_contact_get (contact, E_CONTACT_FILE_AS);
-
- if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
- string = g_strdup_printf ("%s", file_as_str ? file_as_str : "?");
- } else {
- string = g_strdup_printf (
- "%s%s<%s>", file_as_str ? file_as_str : "",
- file_as_str ? " " : "",
- email_str ? email_str : "");
- }
-
- g_free (file_as_str);
- deep_free_list (email_list);
-
- g_object_set (cell, "text", string, NULL);
- g_free (string);
-}
-
-static gint
-generate_contact_rows (EContactStore *contact_store,
- GtkTreeIter *iter,
- ENameSelectorEntry *name_selector_entry)
-{
- EContact *contact;
- const gchar *contact_uid;
- GList *email_list;
- gint n_rows;
-
- contact = e_contact_store_get_contact (contact_store, iter);
- g_assert (contact != NULL);
-
- contact_uid = e_contact_get_const (contact, E_CONTACT_UID);
- if (!contact_uid)
- return 0; /* Can happen with broken databases */
-
- if (e_contact_get (contact, E_CONTACT_IS_LIST))
- return 1;
-
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- n_rows = g_list_length (email_list);
- deep_free_list (email_list);
-
- return n_rows;
-}
-
-static void
-ensure_type_ahead_complete_on_timeout (ENameSelectorEntry *name_selector_entry)
-{
- re_set_timeout (
- name_selector_entry->priv->type_ahead_complete_cb_id,
- type_ahead_complete_on_timeout_cb, name_selector_entry);
-}
-
-static void
-setup_contact_store (ENameSelectorEntry *name_selector_entry)
-{
- if (name_selector_entry->priv->email_generator) {
- g_object_unref (name_selector_entry->priv->email_generator);
- name_selector_entry->priv->email_generator = NULL;
- }
-
- if (name_selector_entry->priv->contact_store) {
- name_selector_entry->priv->email_generator =
- e_tree_model_generator_new (
- GTK_TREE_MODEL (
- name_selector_entry->priv->contact_store));
-
- e_tree_model_generator_set_generate_func (
- name_selector_entry->priv->email_generator,
- (ETreeModelGeneratorGenerateFunc) generate_contact_rows,
- name_selector_entry, NULL);
-
- /* Assign the store to the entry completion */
-
- gtk_entry_completion_set_model (
- name_selector_entry->priv->entry_completion,
- GTK_TREE_MODEL (
- name_selector_entry->priv->email_generator));
-
- /* Set up callback for incoming matches */
- g_signal_connect_swapped (
- name_selector_entry->priv->contact_store, "row-inserted",
- G_CALLBACK (ensure_type_ahead_complete_on_timeout), name_selector_entry);
- } else {
- /* Remove the store from the entry completion */
-
- gtk_entry_completion_set_model (name_selector_entry->priv->entry_completion, NULL);
- }
-}
-
-static void
-book_loaded_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- EContactStore *contact_store = user_data;
- ESource *source = E_SOURCE (source_object);
- EBookClient *book_client;
- EClient *client = NULL;
- GError *error = NULL;
-
- e_client_utils_open_new_finish (source, result, &client, &error);
-
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- g_warn_if_fail (client == NULL);
- g_error_free (error);
- goto exit;
- }
-
- if (error != NULL) {
- g_warning ("%s", error->message);
- g_warn_if_fail (client == NULL);
- g_error_free (error);
- goto exit;
- }
-
- book_client = E_BOOK_CLIENT (client);
-
- g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
- e_contact_store_add_client (contact_store, book_client);
- g_object_unref (book_client);
-
- exit:
- g_object_unref (contact_store);
-}
-
-static void
-setup_default_contact_store (ENameSelectorEntry *name_selector_entry)
-{
- ESourceRegistry *registry;
- EContactStore *contact_store;
- GList *list, *iter;
- const gchar *extension_name;
-
- g_return_if_fail (name_selector_entry->priv->contact_store == NULL);
-
- /* Create a book for each completion source, and assign them to the contact store */
-
- contact_store = e_contact_store_new ();
- name_selector_entry->priv->contact_store = contact_store;
-
- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
- registry = e_name_selector_entry_get_registry (name_selector_entry);
-
- /* An ESourceRegistry should have been set by now. */
- g_return_if_fail (registry != NULL);
-
- list = e_source_registry_list_sources (registry, extension_name);
-
- for (iter = list; iter != NULL; iter = g_list_next (iter)) {
- ESource *source = E_SOURCE (iter->data);
- ESourceAutocomplete *extension;
- GCancellable *cancellable;
- const gchar *extension_name;
-
- extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
- extension = e_source_get_extension (source, extension_name);
-
- /* Skip disabled address books. */
- if (!e_source_registry_check_enabled (registry, source))
- continue;
-
- /* Skip non-completion address books. */
- if (!e_source_autocomplete_get_include_me (extension))
- continue;
-
- cancellable = g_cancellable_new ();
-
- g_queue_push_tail (
- &name_selector_entry->priv->cancellables,
- cancellable);
-
- e_client_utils_open_new (
- source, E_CLIENT_SOURCE_TYPE_CONTACTS, TRUE, cancellable,
- book_loaded_cb, g_object_ref (contact_store));
- }
-
- g_list_free_full (list, (GDestroyNotify) g_object_unref);
-
- setup_contact_store (name_selector_entry);
-}
-
-static void
-destination_row_changed (ENameSelectorEntry *name_selector_entry,
- GtkTreePath *path,
- GtkTreeIter *iter)
-{
- EDestination *destination;
- const gchar *entry_text;
- gchar *text;
- gint range_start, range_end;
- gint n;
-
- n = gtk_tree_path_get_indices (path)[0];
- destination = e_destination_store_get_destination (name_selector_entry->priv->destination_store, iter);
-
- if (!destination)
- return;
-
- g_assert (n >= 0);
-
- entry_text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- if (!get_range_by_index (entry_text, n, &range_start, &range_end)) {
- g_warning ("ENameSelectorEntry is out of sync with model!");
- return;
- }
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), range_start, range_end);
-
- text = get_destination_textrep (name_selector_entry, destination);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), text, -1, &range_start);
- g_free (text);
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- clear_completion_model (name_selector_entry);
- generate_attribute_list (name_selector_entry);
-}
-
-static void
-destination_row_inserted (ENameSelectorEntry *name_selector_entry,
- GtkTreePath *path,
- GtkTreeIter *iter)
-{
- EDestination *destination;
- const gchar *entry_text;
- gchar *text;
- gboolean comma_before = FALSE;
- gboolean comma_after = FALSE;
- gint range_start, range_end;
- gint insert_pos;
- gint n;
-
- n = gtk_tree_path_get_indices (path)[0];
- destination = e_destination_store_get_destination (name_selector_entry->priv->destination_store, iter);
-
- g_assert (n >= 0);
- g_assert (destination != NULL);
-
- entry_text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
-
- if (get_range_by_index (entry_text, n, &range_start, &range_end) && range_start != range_end) {
- /* Another destination comes after us */
- insert_pos = range_start;
- comma_after = TRUE;
- } else if (n > 0 && get_range_by_index (entry_text, n - 1, &range_start, &range_end)) {
- /* Another destination comes before us */
- insert_pos = range_end;
- comma_before = TRUE;
- } else if (n == 0) {
- /* We're the sole destination */
- insert_pos = 0;
- } else {
- g_warning ("ENameSelectorEntry is out of sync with model!");
- return;
- }
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- if (comma_before)
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ", ", -1, &insert_pos);
-
- text = get_destination_textrep (name_selector_entry, destination);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), text, -1, &insert_pos);
- g_free (text);
-
- if (comma_after)
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), ", ", -1, &insert_pos);
-
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-
- clear_completion_model (name_selector_entry);
- generate_attribute_list (name_selector_entry);
-}
-
-static void
-destination_row_deleted (ENameSelectorEntry *name_selector_entry,
- GtkTreePath *path)
-{
- const gchar *text;
- gboolean deleted_comma = FALSE;
- gint range_start, range_end;
- gchar *p0;
- gint n;
-
- n = gtk_tree_path_get_indices (path)[0];
- g_assert (n >= 0);
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
-
- if (!get_range_by_index (text, n, &range_start, &range_end)) {
- g_warning ("ENameSelectorEntry is out of sync with model!");
- return;
- }
-
- /* Expand range for deletion forwards */
- for (p0 = g_utf8_offset_to_pointer (text, range_end); *p0;
- p0 = g_utf8_next_char (p0), range_end++) {
- gunichar c = g_utf8_get_char (p0);
-
- /* Gobble spaces directly after comma */
- if (c != ' ' && deleted_comma) {
- range_end--;
- break;
- }
-
- if (c == ',') {
- deleted_comma = TRUE;
- range_end++;
- }
- }
-
- /* Expand range for deletion backwards */
- for (p0 = g_utf8_offset_to_pointer (text, range_start); range_start > 0;
- p0 = g_utf8_prev_char (p0), range_start--) {
- gunichar c = g_utf8_get_char (p0);
-
- if (c == ',') {
- if (!deleted_comma) {
- deleted_comma = TRUE;
- break;
- }
-
- range_start++;
-
- /* Leave a space in front; we deleted the comma and spaces before the
- * following destination */
- p0 = g_utf8_next_char (p0);
- c = g_utf8_get_char (p0);
- if (c == ' ')
- range_start++;
-
- break;
- }
- }
-
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), range_start, range_end);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- clear_completion_model (name_selector_entry);
- generate_attribute_list (name_selector_entry);
-}
-
-static void
-setup_destination_store (ENameSelectorEntry *name_selector_entry)
-{
- GtkTreeIter iter;
-
- g_signal_connect_swapped (
- name_selector_entry->priv->destination_store, "row-changed",
- G_CALLBACK (destination_row_changed), name_selector_entry);
- g_signal_connect_swapped (
- name_selector_entry->priv->destination_store, "row-deleted",
- G_CALLBACK (destination_row_deleted), name_selector_entry);
- g_signal_connect_swapped (
- name_selector_entry->priv->destination_store, "row-inserted",
- G_CALLBACK (destination_row_inserted), name_selector_entry);
-
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (name_selector_entry->priv->destination_store), &iter))
- return;
-
- do {
- GtkTreePath *path;
-
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (name_selector_entry->priv->destination_store), &iter);
- g_assert (path);
-
- destination_row_inserted (name_selector_entry, path, &iter);
- } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (name_selector_entry->priv->destination_store), &iter));
-}
-
-static gboolean
-prepare_popup_destination (ENameSelectorEntry *name_selector_entry,
- GdkEventButton *event_button)
-{
- EDestination *destination;
- PangoLayout *layout;
- gint layout_offset_x;
- gint layout_offset_y;
- gint x, y;
- gint index;
-
- if (event_button->type != GDK_BUTTON_PRESS)
- return FALSE;
-
- if (event_button->button != 3)
- return FALSE;
-
- if (name_selector_entry->priv->popup_destination) {
- g_object_unref (name_selector_entry->priv->popup_destination);
- name_selector_entry->priv->popup_destination = NULL;
- }
-
- gtk_entry_get_layout_offsets (
- GTK_ENTRY (name_selector_entry),
- &layout_offset_x, &layout_offset_y);
- x = (event_button->x + 0.5) - layout_offset_x;
- y = (event_button->y + 0.5) - layout_offset_y;
-
- if (x < 0 || y < 0)
- return FALSE;
-
- layout = gtk_entry_get_layout (GTK_ENTRY (name_selector_entry));
- if (!pango_layout_xy_to_index (layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, NULL))
- return FALSE;
-
- index = gtk_entry_layout_index_to_text_index (GTK_ENTRY (name_selector_entry), index);
- destination = find_destination_at_position (name_selector_entry, index);
- /* FIXME: Add this to a private variable, in ENameSelectorEntry Class*/
- g_object_set_data ((GObject *) name_selector_entry, "index", GINT_TO_POINTER (index));
-
- if (!destination || !e_destination_get_contact (destination))
- return FALSE;
-
- /* TODO: Unref destination when we finalize */
- name_selector_entry->priv->popup_destination = g_object_ref (destination);
- return FALSE;
-}
-
-static EBookClient *
-find_client_by_contact (GSList *clients,
- const gchar *contact_uid,
- const gchar *source_uid)
-{
- GSList *l;
-
- if (source_uid && *source_uid) {
- /* this is much quicket than asking each client for an existence */
- for (l = clients; l; l = g_slist_next (l)) {
- EBookClient *client = l->data;
- ESource *source = e_client_get_source (E_CLIENT (client));
-
- if (!source)
- continue;
-
- if (g_strcmp0 (source_uid, e_source_get_uid (source)) == 0)
- return client;
- }
- }
-
- for (l = clients; l; l = g_slist_next (l)) {
- EBookClient *client = l->data;
- EContact *contact = NULL;
- gboolean result;
-
- result = e_book_client_get_contact_sync (client, contact_uid, &contact, NULL, NULL);
- if (contact)
- g_object_unref (contact);
-
- if (result)
- return client;
- }
-
- return NULL;
-}
-
-static void
-editor_closed_cb (GtkWidget *editor,
- gpointer data)
-{
- EContact *contact;
- gchar *contact_uid;
- EDestination *destination;
- GSList *clients;
- EBookClient *book_client;
- gint email_num;
- ENameSelectorEntry *name_selector_entry = E_NAME_SELECTOR_ENTRY (data);
-
- destination = name_selector_entry->priv->popup_destination;
- contact = e_destination_get_contact (destination);
- if (!contact) {
- g_object_unref (name_selector_entry);
- return;
- }
-
- contact_uid = e_contact_get (contact, E_CONTACT_UID);
- if (!contact_uid) {
- g_object_unref (contact);
- g_object_unref (name_selector_entry);
- return;
- }
-
- if (name_selector_entry->priv->contact_store) {
- clients = e_contact_store_get_clients (name_selector_entry->priv->contact_store);
- book_client = find_client_by_contact (clients, contact_uid, e_destination_get_source_uid (destination));
- g_slist_free (clients);
- } else {
- book_client = NULL;
- }
-
- if (book_client) {
- contact = NULL;
-
- g_warn_if_fail (e_book_client_get_contact_sync (book_client, contact_uid, &contact, NULL, NULL));
- email_num = e_destination_get_email_num (destination);
- e_destination_set_contact (destination, contact, email_num);
- e_destination_set_client (destination, book_client);
- } else {
- contact = NULL;
- }
-
- g_free (contact_uid);
- if (contact)
- g_object_unref (contact);
- g_object_unref (name_selector_entry);
-}
-
-/* To parse something like...
- * =?UTF-8?Q?=E0=A4=95=E0=A4=95=E0=A4=AC=E0=A5=82=E0=A5=8B=E0=A5=87?=\t\n=?UTF-8?Q?=E0=A4=B0?=\t\n<aa@aa.ccom>
- * and return the decoded representation of name & email parts.
- * */
-static gboolean
-eab_parse_qp_email (const gchar *string,
- gchar **name,
- gchar **email)
-{
- struct _camel_header_address *address;
- gboolean res = FALSE;
-
- address = camel_header_address_decode (string, "UTF-8");
-
- if (!address)
- return FALSE;
-
- /* report success only when we have filled both name and email address */
- if (address->type == CAMEL_HEADER_ADDRESS_NAME && address->name && *address->name && address->v.addr && *address->v.addr) {
- *name = g_strdup (address->name);
- *email = g_strdup (address->v.addr);
- res = TRUE;
- }
-
- camel_header_address_unref (address);
-
- return res;
-}
-
-static void
-popup_activate_inline_expand (ENameSelectorEntry *name_selector_entry,
- GtkWidget *menu_item)
-{
- const gchar *text;
- GString *sanitized_text = g_string_new ("");
- EDestination *destination = name_selector_entry->priv->popup_destination;
- gint position, start, end;
- const GList *dests;
-
- position = GPOINTER_TO_INT (g_object_get_data ((GObject *) name_selector_entry, "index"));
-
- for (dests = e_destination_list_get_dests (destination); dests; dests = dests->next) {
- const EDestination *dest = dests->data;
- gchar *sanitized;
- gchar *name = NULL, *email = NULL, *tofree = NULL;
-
- if (!dest)
- continue;
-
- text = e_destination_get_textrep (dest, TRUE);
-
- if (!text || !*text)
- continue;
-
- if (eab_parse_qp_email (text, &name, &email)) {
- tofree = g_strdup_printf ("%s <%s>", name, email);
- text = tofree;
- g_free (name);
- g_free (email);
- }
-
- sanitized = sanitize_string (text);
- g_free (tofree);
- if (!sanitized)
- continue;
-
- if (*sanitized) {
- if (*sanitized_text->str)
- g_string_append (sanitized_text, ", ");
-
- g_string_append (sanitized_text, sanitized);
- }
-
- g_free (sanitized);
- }
-
- text = gtk_entry_get_text (GTK_ENTRY (name_selector_entry));
- get_range_at_position (text, position, &start, &end);
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), start, end);
- gtk_editable_insert_text (GTK_EDITABLE (name_selector_entry), sanitized_text->str, -1, &start);
- g_string_free (sanitized_text, TRUE);
-
- clear_completion_model (name_selector_entry);
- generate_attribute_list (name_selector_entry);
-}
-
-static void
-popup_activate_contact (ENameSelectorEntry *name_selector_entry,
- GtkWidget *menu_item)
-{
- EBookClient *book_client;
- GSList *clients;
- EDestination *destination;
- EContact *contact;
- gchar *contact_uid;
-
- destination = name_selector_entry->priv->popup_destination;
- if (!destination)
- return;
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- contact_uid = e_contact_get (contact, E_CONTACT_UID);
- if (!contact_uid)
- return;
-
- if (name_selector_entry->priv->contact_store) {
- clients = e_contact_store_get_clients (name_selector_entry->priv->contact_store);
- book_client = find_client_by_contact (clients, contact_uid, e_destination_get_source_uid (destination));
- g_slist_free (clients);
- g_free (contact_uid);
- } else {
- book_client = NULL;
- }
-
- if (!book_client)
- return;
-
- if (e_destination_is_evolution_list (destination)) {
- GtkWidget *contact_list_editor;
-
- if (!name_selector_entry->priv->contact_list_editor_func)
- return;
-
- contact_list_editor = (*name_selector_entry->priv->contact_list_editor_func) (book_client, contact, FALSE, TRUE);
- g_object_ref (name_selector_entry);
- g_signal_connect (
- contact_list_editor, "editor_closed",
- G_CALLBACK (editor_closed_cb), name_selector_entry);
- } else {
- GtkWidget *contact_editor;
-
- if (!name_selector_entry->priv->contact_editor_func)
- return;
-
- contact_editor = (*name_selector_entry->priv->contact_editor_func) (book_client, contact, FALSE, TRUE);
- g_object_ref (name_selector_entry);
- g_signal_connect (
- contact_editor, "editor_closed",
- G_CALLBACK (editor_closed_cb), name_selector_entry);
- }
-}
-
-static void
-popup_activate_email (ENameSelectorEntry *name_selector_entry,
- GtkWidget *menu_item)
-{
- EDestination *destination;
- EContact *contact;
- gint email_num;
-
- destination = name_selector_entry->priv->popup_destination;
- if (!destination)
- return;
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- email_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "order"));
- e_destination_set_contact (destination, contact, email_num);
-}
-
-static void
-popup_activate_list (EDestination *destination,
- GtkWidget *item)
-{
- gboolean status = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item));
-
- e_destination_set_ignored (destination, !status);
-}
-
-static void
-popup_activate_cut (ENameSelectorEntry *name_selector_entry,
- GtkWidget *menu_item)
-{
- EDestination *destination;
- const gchar *contact_email;
- gchar *pemail = NULL;
- GtkClipboard *clipboard;
-
- destination = name_selector_entry->priv->popup_destination;
- contact_email =e_destination_get_textrep (destination, TRUE);
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
- pemail = g_strconcat (contact_email, ",", NULL);
- gtk_clipboard_set_text (clipboard, pemail, strlen (pemail));
-
- clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, pemail, strlen (pemail));
-
- gtk_editable_delete_text (GTK_EDITABLE (name_selector_entry), 0, 0);
- e_destination_store_remove_destination (name_selector_entry->priv->destination_store, destination);
-
- g_free (pemail);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-}
-
-static void
-popup_activate_copy (ENameSelectorEntry *name_selector_entry,
- GtkWidget *menu_item)
-{
- EDestination *destination;
- const gchar *contact_email;
- gchar *pemail;
- GtkClipboard *clipboard;
-
- destination = name_selector_entry->priv->popup_destination;
- contact_email = e_destination_get_textrep (destination, TRUE);
-
- g_signal_handlers_block_by_func (name_selector_entry, user_insert_text, name_selector_entry);
- g_signal_handlers_block_by_func (name_selector_entry, user_delete_text, name_selector_entry);
-
- clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
- pemail = g_strconcat (contact_email, ",", NULL);
- gtk_clipboard_set_text (clipboard, pemail, strlen (pemail));
-
- clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, pemail, strlen (pemail));
- g_free (pemail);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_delete_text, name_selector_entry);
- g_signal_handlers_unblock_by_func (name_selector_entry, user_insert_text, name_selector_entry);
-}
-
-static void
-destination_set_list (GtkWidget *item,
- EDestination *destination)
-{
- EContact *contact;
- gboolean status = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item));
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- e_destination_set_ignored (destination, !status);
-}
-
-static void
-destination_set_email (GtkWidget *item,
- EDestination *destination)
-{
- gint email_num;
- EContact *contact;
-
- if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
- return;
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- email_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "order"));
- e_destination_set_contact (destination, contact, email_num);
-}
-
-static void
-populate_popup (ENameSelectorEntry *name_selector_entry,
- GtkMenu *menu)
-{
- EDestination *destination;
- EContact *contact;
- GtkWidget *menu_item;
- GList *email_list = NULL;
- GList *l;
- gint i;
- gchar *edit_label;
- gchar *cut_label;
- gchar *copy_label;
- gint email_num, len;
- GSList *group = NULL;
- gboolean is_list;
- gboolean show_menu = FALSE;
-
- destination = name_selector_entry->priv->popup_destination;
- if (!destination)
- return;
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- /* Prepend the menu items, backwards */
-
- /* Separator */
-
- menu_item = gtk_separator_menu_item_new ();
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- email_num = e_destination_get_email_num (destination);
-
- /* Addresses */
- is_list = e_contact_get (contact, E_CONTACT_IS_LIST) ? TRUE : FALSE;
- if (is_list) {
- const GList *dests = e_destination_list_get_dests (destination);
- GList *iter;
- gint length = g_list_length ((GList *) dests);
-
- for (iter = (GList *) dests; iter; iter = iter->next) {
- EDestination *dest = (EDestination *) iter->data;
- const gchar *email = e_destination_get_email (dest);
-
- if (!email || *email == '\0')
- continue;
-
- if (length > 1) {
- menu_item = gtk_check_menu_item_new_with_label (email);
- g_signal_connect (
- menu_item, "toggled",
- G_CALLBACK (destination_set_list), dest);
- } else {
- menu_item = gtk_menu_item_new_with_label (email);
- }
-
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- show_menu = TRUE;
-
- if (length > 1) {
- gtk_check_menu_item_set_active (
- GTK_CHECK_MENU_ITEM (menu_item),
- !e_destination_is_ignored (dest));
- g_signal_connect_swapped (
- menu_item, "activate",
- G_CALLBACK (popup_activate_list), dest);
- }
- }
-
- } else {
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- len = g_list_length (email_list);
-
- for (l = email_list, i = 0; l; l = g_list_next (l), i++) {
- gchar *email = l->data;
-
- if (!email || *email == '\0')
- continue;
-
- if (len > 1) {
- menu_item = gtk_radio_menu_item_new_with_label (group, email);
- group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
- g_signal_connect (menu_item, "toggled", G_CALLBACK (destination_set_email), destination);
- } else {
- menu_item = gtk_menu_item_new_with_label (email);
- }
-
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- show_menu = TRUE;
- g_object_set_data (G_OBJECT (menu_item), "order", GINT_TO_POINTER (i));
-
- if (i == email_num && len > 1) {
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
- g_signal_connect_swapped (
- menu_item, "activate",
- G_CALLBACK (popup_activate_email),
- name_selector_entry);
- }
- }
- }
-
- /* Separator */
-
- if (show_menu) {
- menu_item = gtk_separator_menu_item_new ();
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- }
-
- /* Expand a list inline */
- if (is_list) {
- /* To Translators: This would be similiar to "Expand MyList Inline" where MyList is a Contact List*/
- edit_label = g_strdup_printf (_("E_xpand %s Inline"), (gchar *) e_contact_get_const (contact, E_CONTACT_FILE_AS));
- menu_item = gtk_menu_item_new_with_mnemonic (edit_label);
- g_free (edit_label);
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- g_signal_connect_swapped (
- menu_item, "activate", G_CALLBACK (popup_activate_inline_expand),
- name_selector_entry);
-
- /* Separator */
- menu_item = gtk_separator_menu_item_new ();
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- }
-
- /* Copy Contact Item */
- copy_label = g_strdup_printf (_("Cop_y %s"), (gchar *) e_contact_get_const (contact, E_CONTACT_FILE_AS));
- menu_item = gtk_menu_item_new_with_mnemonic (copy_label);
- g_free (copy_label);
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
-
- g_signal_connect_swapped (
- menu_item, "activate", G_CALLBACK (popup_activate_copy),
- name_selector_entry);
-
- /* Cut Contact Item */
- cut_label = g_strdup_printf (_("C_ut %s"), (gchar *) e_contact_get_const (contact, E_CONTACT_FILE_AS));
- menu_item = gtk_menu_item_new_with_mnemonic (cut_label);
- g_free (cut_label);
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
-
- g_signal_connect_swapped (
- menu_item, "activate", G_CALLBACK (popup_activate_cut),
- name_selector_entry);
-
- if (show_menu) {
- menu_item = gtk_separator_menu_item_new ();
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- }
-
- /* Edit Contact item */
-
- edit_label = g_strdup_printf (_("_Edit %s"), (gchar *) e_contact_get_const (contact, E_CONTACT_FILE_AS));
- menu_item = gtk_menu_item_new_with_mnemonic (edit_label);
- g_free (edit_label);
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
-
- g_signal_connect_swapped (
- menu_item, "activate", G_CALLBACK (popup_activate_contact),
- name_selector_entry);
-
- deep_free_list (email_list);
-}
-
-static void
-copy_or_cut_clipboard (ENameSelectorEntry *name_selector_entry,
- gboolean is_cut)
-{
- GtkClipboard *clipboard;
- GtkEditable *editable;
- const gchar *text, *cp;
- GHashTable *hash;
- GHashTableIter iter;
- gpointer key, value;
- GString *addresses;
- gint ii, start, end;
- gunichar uc;
-
- editable = GTK_EDITABLE (name_selector_entry);
- text = gtk_entry_get_text (GTK_ENTRY (editable));
-
- if (!gtk_editable_get_selection_bounds (editable, &start, &end))
- return;
-
- g_return_if_fail (end > start);
-
- hash = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- ii = end;
- cp = g_utf8_offset_to_pointer (text, end);
- uc = g_utf8_get_char (cp);
-
- /* Exclude trailing whitespace and commas. */
- while (ii >= start && (uc == ',' || g_unichar_isspace (uc))) {
- cp = g_utf8_prev_char (cp);
- uc = g_utf8_get_char (cp);
- ii--;
- }
-
- /* Determine the index of each remaining character. */
- while (ii >= start) {
- gint index = get_index_at_position (text, ii--);
- g_hash_table_insert (hash, GINT_TO_POINTER (index), NULL);
- }
-
- addresses = g_string_new ("");
-
- g_hash_table_iter_init (&iter, hash);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- gint index = GPOINTER_TO_INT (key);
- EDestination *dest;
- gint rstart, rend;
-
- if (!get_range_by_index (text, index, &rstart, &rend))
- continue;
-
- if (rstart < start) {
- if (addresses->str && *addresses->str)
- g_string_append (addresses, ", ");
-
- g_string_append_len (addresses, text + start, rend - start);
- } else if (rend > end) {
- if (addresses->str && *addresses->str)
- g_string_append (addresses, ", ");
-
- g_string_append_len (addresses, text + rstart, end - rstart);
- } else {
- /* the contact is whole selected */
- dest = find_destination_by_index (name_selector_entry, index);
- if (dest && e_destination_get_textrep (dest, TRUE)) {
- if (addresses->str && *addresses->str)
- g_string_append (addresses, ", ");
-
- g_string_append (addresses, e_destination_get_textrep (dest, TRUE));
-
- /* store the 'dest' as a value for the index */
- g_hash_table_insert (hash, GINT_TO_POINTER (index), dest);
- } else
- g_string_append_len (addresses, text + rstart, rend - rstart);
- }
- }
-
- if (is_cut)
- gtk_editable_delete_text (editable, start, end);
-
- g_hash_table_unref (hash);
-
- clipboard = gtk_widget_get_clipboard (
- GTK_WIDGET (name_selector_entry), GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, addresses->str, -1);
-
- g_string_free (addresses, TRUE);
-}
-
-static void
-copy_clipboard (GtkEntry *entry,
- ENameSelectorEntry *name_selector_entry)
-{
- copy_or_cut_clipboard (name_selector_entry, FALSE);
- g_signal_stop_emission_by_name (entry, "copy-clipboard");
-}
-
-static void
-cut_clipboard (GtkEntry *entry,
- ENameSelectorEntry *name_selector_entry)
-{
- copy_or_cut_clipboard (name_selector_entry, TRUE);
- g_signal_stop_emission_by_name (entry, "cut-clipboard");
-}
-
-static void
-e_name_selector_entry_init (ENameSelectorEntry *name_selector_entry)
-{
- GtkCellRenderer *renderer;
-
- name_selector_entry->priv =
- E_NAME_SELECTOR_ENTRY_GET_PRIVATE (name_selector_entry);
-
- g_queue_init (&name_selector_entry->priv->cancellables);
-
- name_selector_entry->priv->minimum_query_length = 3;
- name_selector_entry->priv->show_address = FALSE;
-
- /* Edit signals */
-
- g_signal_connect (
- name_selector_entry, "insert-text",
- G_CALLBACK (user_insert_text), name_selector_entry);
- g_signal_connect (
- name_selector_entry, "delete-text",
- G_CALLBACK (user_delete_text), name_selector_entry);
- g_signal_connect (
- name_selector_entry, "focus-out-event",
- G_CALLBACK (user_focus_out), name_selector_entry);
- g_signal_connect_after (
- name_selector_entry, "focus-in-event",
- G_CALLBACK (user_focus_in), name_selector_entry);
-
- /* Drawing */
-
- g_signal_connect (
- name_selector_entry, "draw",
- G_CALLBACK (draw_event), name_selector_entry);
-
- /* Activation: Complete current entry if possible */
-
- g_signal_connect (
- name_selector_entry, "activate",
- G_CALLBACK (entry_activate), name_selector_entry);
-
- /* Pop-up menu */
-
- g_signal_connect (
- name_selector_entry, "button-press-event",
- G_CALLBACK (prepare_popup_destination), name_selector_entry);
- g_signal_connect (
- name_selector_entry, "populate-popup",
- G_CALLBACK (populate_popup), name_selector_entry);
-
- /* Clipboard signals */
- g_signal_connect (
- name_selector_entry, "copy-clipboard",
- G_CALLBACK (copy_clipboard), name_selector_entry);
- g_signal_connect (
- name_selector_entry, "cut-clipboard",
- G_CALLBACK (cut_clipboard), name_selector_entry);
-
- /* Completion */
-
- name_selector_entry->priv->email_generator = NULL;
-
- name_selector_entry->priv->entry_completion = gtk_entry_completion_new ();
- gtk_entry_completion_set_match_func (
- name_selector_entry->priv->entry_completion,
- (GtkEntryCompletionMatchFunc) completion_match_cb, NULL, NULL);
- g_signal_connect_swapped (
- name_selector_entry->priv->entry_completion, "match-selected",
- G_CALLBACK (completion_match_selected), name_selector_entry);
-
- gtk_entry_set_completion (
- GTK_ENTRY (name_selector_entry),
- name_selector_entry->priv->entry_completion);
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_layout_pack_start (
- GTK_CELL_LAYOUT (name_selector_entry->priv->entry_completion),
- renderer, FALSE);
- gtk_cell_layout_set_cell_data_func (
- GTK_CELL_LAYOUT (name_selector_entry->priv->entry_completion),
- GTK_CELL_RENDERER (renderer),
- (GtkCellLayoutDataFunc) contact_layout_pixbuffer,
- name_selector_entry, NULL);
-
- /* Completion list name renderer */
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (
- GTK_CELL_LAYOUT (name_selector_entry->priv->entry_completion),
- renderer, TRUE);
- gtk_cell_layout_set_cell_data_func (
- GTK_CELL_LAYOUT (name_selector_entry->priv->entry_completion),
- GTK_CELL_RENDERER (renderer),
- (GtkCellLayoutDataFunc) contact_layout_formatter,
- name_selector_entry, NULL);
-
- /* Destination store */
-
- name_selector_entry->priv->destination_store = e_destination_store_new ();
- setup_destination_store (name_selector_entry);
- name_selector_entry->priv->is_completing = FALSE;
-}
-
-/**
- * e_name_selector_entry_new:
- *
- * Creates a new #ENameSelectorEntry.
- *
- * Returns: A new #ENameSelectorEntry.
- **/
-ENameSelectorEntry *
-e_name_selector_entry_new (ESourceRegistry *registry)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
-
- return g_object_new (
- E_TYPE_NAME_SELECTOR_ENTRY,
- "registry", registry, NULL);
-}
-
-/**
- * e_name_selector_entry_get_registry:
- * @name_selector_entry: an #ENameSelectorEntry
- *
- * Returns the #ESourceRegistry used to query address books.
- *
- * Returns: the #ESourceRegistry, or %NULL
- *
- * Since: 3.6
- **/
-ESourceRegistry *
-e_name_selector_entry_get_registry (ENameSelectorEntry *name_selector_entry)
-{
- g_return_val_if_fail (
- E_IS_NAME_SELECTOR_ENTRY (name_selector_entry), NULL);
-
- return name_selector_entry->priv->registry;
-}
-
-/**
- * e_name_selector_entry_set_registry:
- * @name_selector_entry: an #ENameSelectorEntry
- * @registry: an #ESourceRegistry
- *
- * Sets the #ESourceRegistry used to query address books.
- *
- * This function is intended for cases where @name_selector_entry is
- * instantiated by a #GtkBuilder and has to be given an #EsourceRegistry
- * after it is fully constructed.
- *
- * Since: 3.6
- **/
-void
-e_name_selector_entry_set_registry (ENameSelectorEntry *name_selector_entry,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry));
-
- if (name_selector_entry->priv->registry == registry)
- return;
-
- if (registry != NULL) {
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_object_ref (registry);
- }
-
- if (name_selector_entry->priv->registry != NULL)
- g_object_unref (name_selector_entry->priv->registry);
-
- name_selector_entry->priv->registry = registry;
-
- g_object_notify (G_OBJECT (name_selector_entry), "registry");
-}
-
-/**
- * e_name_selector_entry_get_minimum_query_length:
- * @name_selector_entry: an #ENameSelectorEntry
- *
- * Returns: Minimum length of query before completion starts
- *
- * Since: 3.6
- **/
-gint
-e_name_selector_entry_get_minimum_query_length (ENameSelectorEntry *name_selector_entry)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry), -1);
-
- return name_selector_entry->priv->minimum_query_length;
-}
-
-/**
- * e_name_selector_entry_set_minimum_query_length:
- * @name_selector_entry: an #ENameSelectorEntry
- * @length: minimum query length
- *
- * Sets minimum length of query before completion starts.
- *
- * Since: 3.6
- **/
-void
-e_name_selector_entry_set_minimum_query_length (ENameSelectorEntry *name_selector_entry,
- gint length)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry));
- g_return_if_fail (length > 0);
-
- if (name_selector_entry->priv->minimum_query_length == length)
- return;
-
- name_selector_entry->priv->minimum_query_length = length;
-
- g_object_notify (G_OBJECT (name_selector_entry), "minimum-query-length");
-}
-
-/**
- * e_name_selector_entry_get_show_address:
- * @name_selector_entry: an #ENameSelectorEntry
- *
- * Returns: Whether always show email address for an auto-completed contact.
- *
- * Since: 3.6
- **/
-gboolean
-e_name_selector_entry_get_show_address (ENameSelectorEntry *name_selector_entry)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry), FALSE);
-
- return name_selector_entry->priv->show_address;
-}
-
-/**
- * e_name_selector_entry_set_show_address:
- * @name_selector_entry: an #ENameSelectorEntry
- * @show: new value to set
- *
- * Sets whether always show email address for an auto-completed contact.
- *
- * Since: 3.6
- **/
-void
-e_name_selector_entry_set_show_address (ENameSelectorEntry *name_selector_entry,
- gboolean show)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry));
-
- if ((name_selector_entry->priv->show_address ? 1 : 0) == (show ? 1 : 0))
- return;
-
- name_selector_entry->priv->show_address = show;
-
- sanitize_entry (name_selector_entry);
-
- g_object_notify (G_OBJECT (name_selector_entry), "show-address");
-}
-
-/**
- * e_name_selector_entry_peek_contact_store:
- * @name_selector_entry: an #ENameSelectorEntry
- *
- * Gets the #EContactStore being used by @name_selector_entry.
- *
- * Returns: An #EContactStore.
- **/
-EContactStore *
-e_name_selector_entry_peek_contact_store (ENameSelectorEntry *name_selector_entry)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry), NULL);
-
- return name_selector_entry->priv->contact_store;
-}
-
-/**
- * e_name_selector_entry_set_contact_store:
- * @name_selector_entry: an #ENameSelectorEntry
- * @contact_store: an #EContactStore to use
- *
- * Sets the #EContactStore being used by @name_selector_entry to @contact_store.
- **/
-void
-e_name_selector_entry_set_contact_store (ENameSelectorEntry *name_selector_entry,
- EContactStore *contact_store)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry));
- g_return_if_fail (contact_store == NULL || E_IS_CONTACT_STORE (contact_store));
-
- if (contact_store == name_selector_entry->priv->contact_store)
- return;
-
- if (name_selector_entry->priv->contact_store)
- g_object_unref (name_selector_entry->priv->contact_store);
- name_selector_entry->priv->contact_store = contact_store;
- if (name_selector_entry->priv->contact_store)
- g_object_ref (name_selector_entry->priv->contact_store);
-
- setup_contact_store (name_selector_entry);
-}
-
-/**
- * e_name_selector_entry_peek_destination_store:
- * @name_selector_entry: an #ENameSelectorEntry
- *
- * Gets the #EDestinationStore being used to store @name_selector_entry's destinations.
- *
- * Returns: An #EDestinationStore.
- **/
-EDestinationStore *
-e_name_selector_entry_peek_destination_store (ENameSelectorEntry *name_selector_entry)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry), NULL);
-
- return name_selector_entry->priv->destination_store;
-}
-
-/**
- * e_name_selector_entry_set_destination_store:
- * @name_selector_entry: an #ENameSelectorEntry
- * @destination_store: an #EDestinationStore to use
- *
- * Sets @destination_store as the #EDestinationStore to be used to store
- * destinations for @name_selector_entry.
- **/
-void
-e_name_selector_entry_set_destination_store (ENameSelectorEntry *name_selector_entry,
- EDestinationStore *destination_store)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry));
- g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
-
- if (destination_store == name_selector_entry->priv->destination_store)
- return;
-
- g_object_unref (name_selector_entry->priv->destination_store);
- name_selector_entry->priv->destination_store = g_object_ref (destination_store);
-
- setup_destination_store (name_selector_entry);
-}
-
-/**
- * e_name_selector_entry_get_popup_destination:
- *
- * Since: 2.32
- **/
-EDestination *
-e_name_selector_entry_get_popup_destination (ENameSelectorEntry *name_selector_entry)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_ENTRY (name_selector_entry), NULL);
-
- return name_selector_entry->priv->popup_destination;
-}
-
-/**
- * e_name_selector_entry_set_contact_editor_func:
- *
- * DO NOT USE.
- **/
-void
-e_name_selector_entry_set_contact_editor_func (ENameSelectorEntry *name_selector_entry,
- gpointer func)
-{
- name_selector_entry->priv->contact_editor_func = func;
-}
-
-/**
- * e_name_selector_entry_set_contact_list_editor_func:
- *
- * DO NOT USE.
- **/
-void
-e_name_selector_entry_set_contact_list_editor_func (ENameSelectorEntry *name_selector_entry,
- gpointer func)
-{
- name_selector_entry->priv->contact_list_editor_func = func;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector-entry.c - Single-line text entry widget for EDestinations.
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser 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 Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_NAME_SELECTOR_ENTRY_H
-#define E_NAME_SELECTOR_ENTRY_H
-
-#include <gtk/gtk.h>
-#include <libebook/libebook.h>
-
-#include <libedataserverui/e-contact-store.h>
-#include <libedataserverui/e-destination-store.h>
-#include <libedataserverui/e-tree-model-generator.h>
-
-/* Standard GObject macros */
-#define E_TYPE_NAME_SELECTOR_ENTRY \
- (e_name_selector_entry_get_type ())
-#define E_NAME_SELECTOR_ENTRY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_NAME_SELECTOR_ENTRY, ENameSelectorEntry))
-#define E_NAME_SELECTOR_ENTRY_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_NAME_SELECTOR_ENTRY, ENameSelectorEntryClass))
-#define E_IS_NAME_SELECTOR_ENTRY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_NAME_SELECTOR_ENTRY))
-#define E_IS_NAME_SELECTOR_ENTRY_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_NAME_SELECTOR_ENTRY))
-#define E_NAME_SELECTOR_ENTRY_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_NAME_SELECTOR_ENTRY, ENameSelectorEntryClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ENameSelectorEntry ENameSelectorEntry;
-typedef struct _ENameSelectorEntryClass ENameSelectorEntryClass;
-typedef struct _ENameSelectorEntryPrivate ENameSelectorEntryPrivate;
-
-struct _ENameSelectorEntry {
- GtkEntry parent;
- ENameSelectorEntryPrivate *priv;
-};
-
-struct _ENameSelectorEntryClass {
- GtkEntryClass parent_class;
-
- void (*updated) (ENameSelectorEntry *entry, gchar *email);
-
- gpointer reserved1;
- gpointer reserved2;
-};
-
-GType e_name_selector_entry_get_type (void);
-ENameSelectorEntry *
- e_name_selector_entry_new (ESourceRegistry *registry);
-ESourceRegistry *
- e_name_selector_entry_get_registry
- (ENameSelectorEntry *name_selector_entry);
-void e_name_selector_entry_set_registry
- (ENameSelectorEntry *name_selector_entry,
- ESourceRegistry *registry);
-gint e_name_selector_entry_get_minimum_query_length
- (ENameSelectorEntry *name_selector_entry);
-void e_name_selector_entry_set_minimum_query_length
- (ENameSelectorEntry *name_selector_entry,
- gint length);
-gboolean e_name_selector_entry_get_show_address
- (ENameSelectorEntry *name_selector_entry);
-void e_name_selector_entry_set_show_address
- (ENameSelectorEntry *name_selector_entry,
- gboolean show);
-EContactStore * e_name_selector_entry_peek_contact_store
- (ENameSelectorEntry *name_selector_entry);
-void e_name_selector_entry_set_contact_store
- (ENameSelectorEntry *name_selector_entry,
- EContactStore *contact_store);
-EDestinationStore *
- e_name_selector_entry_peek_destination_store
- (ENameSelectorEntry *name_selector_entry);
-void e_name_selector_entry_set_destination_store
- (ENameSelectorEntry *name_selector_entry,
- EDestinationStore *destination_store);
-EDestination * e_name_selector_entry_get_popup_destination
- (ENameSelectorEntry *name_selector_entry);
-
-/* TEMPORARY API - DO NOT USE */
-void e_name_selector_entry_set_contact_editor_func
- (ENameSelectorEntry *name_selector_entry,
- gpointer func);
-void e_name_selector_entry_set_contact_list_editor_func
- (ENameSelectorEntry *name_selector_entry,
- gpointer func);
-gchar * ens_util_populate_user_query_fields
- (GSList *user_query_fields,
- const gchar *cue_str,
- const gchar *encoded_cue_str);
-
-G_END_DECLS
-
-#endif /* E_NAME_SELECTOR_ENTRY_H */
+++ /dev/null
-/*
- * Single-line text entry widget for EDestinations.
- *
- * 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:
- * Srinivasa Ragavan <sragavan@novell.com>
- * Devashish Sharma <sdevashish@novell.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#include <config.h>
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-#include <glib/gi18n-lib.h>
-
-#include <libedataserverui/e-book-auth-util.h>
-#include <libedataserverui/e-data-server-ui-marshal.h>
-#include <libedataserverui/e-name-selector-entry.h>
-
-#include "e-name-selector-list.h"
-
-#define E_NAME_SELECTOR_LIST_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_NAME_SELECTOR_LIST, ENameSelectorListPrivate))
-
-#define MAX_ROW 10
-
-struct _ENameSelectorListPrivate {
- GtkWindow *popup;
- GtkWidget *tree_view;
- GtkWidget *menu;
- gint rows;
- GdkDevice *grab_keyboard;
- GdkDevice *grab_pointer;
-};
-
-G_DEFINE_TYPE (ENameSelectorList, e_name_selector_list, E_TYPE_NAME_SELECTOR_ENTRY)
-
-/* Signals */
-
-static void
-enl_popup_size (ENameSelectorList *list)
-{
- gint height = 0, count;
- GtkAllocation allocation;
- GtkTreeViewColumn *column = NULL;
-
- column = gtk_tree_view_get_column ( GTK_TREE_VIEW (list->priv->tree_view), 0);
- if (column)
- gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, NULL, &height);
-
- /* Show a maximum of 10 rows in the popup list view */
- count = list->priv->rows;
- if (count > MAX_ROW)
- count = MAX_ROW;
- if (count <= 0)
- count = 1;
-
- gtk_widget_get_allocation (GTK_WIDGET (list), &allocation);
- gtk_widget_set_size_request (list->priv->tree_view, allocation.width - 3 , height * count);
-}
-
-static void
-enl_popup_position (ENameSelectorList *list)
-{
- GtkAllocation allocation;
- GdkWindow *window;
- gint x,y;
-
- gtk_widget_get_allocation (GTK_WIDGET (list), &allocation);
-
- enl_popup_size (list);
- window = gtk_widget_get_window (GTK_WIDGET (list));
- gdk_window_get_origin (window, &x, &y);
- y = y + allocation.height;
-
- gtk_window_move (list->priv->popup, x, y);
-}
-
-static gboolean
-popup_grab_on_window (GdkWindow *window,
- GdkDevice *keyboard,
- GdkDevice *pointer,
- guint32 activate_time)
-{
- if (keyboard && gdk_device_grab (keyboard, window,
- GDK_OWNERSHIP_WINDOW, TRUE,
- GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
- NULL, activate_time) != GDK_GRAB_SUCCESS)
- return FALSE;
-
- if (pointer && gdk_device_grab (pointer, window,
- GDK_OWNERSHIP_WINDOW, TRUE,
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK,
- NULL, activate_time) != GDK_GRAB_SUCCESS) {
- if (keyboard)
- gdk_device_ungrab (keyboard, activate_time);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-enl_popup_grab (ENameSelectorList *list,
- const GdkEvent *event)
-{
- EDestinationStore *store;
- ENameSelectorEntry *entry;
- GdkWindow *window;
- GdkDevice *device = NULL;
- GdkDevice *keyboard, *pointer;
- gint len;
-
- if (list->priv->grab_pointer && list->priv->grab_keyboard)
- return;
-
- window = gtk_widget_get_window (GTK_WIDGET (list->priv->popup));
-
- if (event)
- device = gdk_event_get_device (event);
- if (!device)
- device = gtk_get_current_event_device ();
- if (!device) {
- GdkDeviceManager *device_manager;
-
- device_manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (list)));
- device = gdk_device_manager_get_client_pointer (device_manager);
- }
-
- if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD) {
- keyboard = device;
- pointer = gdk_device_get_associated_device (device);
- } else {
- pointer = device;
- keyboard = gdk_device_get_associated_device (device);
- }
-
- if (!popup_grab_on_window (window, keyboard, pointer, gtk_get_current_event_time ()))
- return;
-
- gtk_widget_grab_focus ((GtkWidget *) list);
-
- /* Build the listview from the model */
- entry = E_NAME_SELECTOR_ENTRY (list);
- store = e_name_selector_entry_peek_destination_store (entry);
- gtk_tree_view_set_model (
- GTK_TREE_VIEW (list->priv->tree_view),
- GTK_TREE_MODEL (store));
-
- /* If any selection of text is present, unselect it */
- len = strlen (gtk_entry_get_text (GTK_ENTRY (list)));
- gtk_editable_select_region (GTK_EDITABLE (list), len, -1);
-
- gtk_device_grab_add (GTK_WIDGET (list->priv->popup), pointer, TRUE);
- list->priv->grab_keyboard = keyboard;
- list->priv->grab_pointer = pointer;
-}
-
-static void
-enl_popup_ungrab (ENameSelectorList *list)
-{
- if (!list->priv->grab_pointer ||
- !list->priv->grab_keyboard ||
- !gtk_widget_has_grab (GTK_WIDGET (list->priv->popup)))
- return;
-
- gtk_device_grab_remove (GTK_WIDGET (list->priv->popup), list->priv->grab_pointer);
- gtk_device_grab_remove (GTK_WIDGET (list->priv->popup), list->priv->grab_keyboard);
-
- list->priv->grab_pointer = NULL;
- list->priv->grab_keyboard = NULL;
-}
-
-static gboolean
-enl_entry_focus_in (ENameSelectorList *list,
- GdkEventFocus *event,
- gpointer dummy)
-{
- gint len;
-
- /* FIXME: Dont select every thing by default- Code is there but still it does */
- len = strlen (gtk_entry_get_text (GTK_ENTRY (list)));
- gtk_editable_select_region (GTK_EDITABLE (list), len, -1);
-
- return TRUE;
-}
-
-static gboolean
-enl_entry_focus_out (ENameSelectorList *list,
- GdkEventFocus *event,
- gpointer dummy)
-{
- /* When we lose focus and popup is still present hide it. Dont do it, when we click the popup. Look for grab */
- if (gtk_widget_get_visible (GTK_WIDGET (list->priv->popup))
- && !gtk_widget_has_grab (GTK_WIDGET (list->priv->popup))) {
- enl_popup_ungrab (list);
- gtk_widget_hide ((GtkWidget *) list->priv->popup);
-
- return FALSE;
- }
-
- return FALSE;
-}
-
-static gboolean
-enl_popup_button_press (GtkWidget *widget,
- GdkEventButton *event,
- ENameSelectorList *list)
-{
- if (!gtk_widget_get_mapped (widget))
- return FALSE;
-
- /* if we come here, it's usually time to popdown */
- gtk_widget_hide ((GtkWidget *) list->priv->popup);
-
- return TRUE;
-}
-
-static gboolean
-enl_popup_focus_out (GtkWidget *w,
- GdkEventFocus *event,
- ENameSelectorList *list)
-{
- /* Just ungrab. We lose focus on button press event */
- enl_popup_ungrab (list);
- return TRUE;
-}
-
-static gboolean
-enl_popup_enter_notify (GtkWidget *widget,
- GdkEventCrossing *event,
- ENameSelectorList *list)
-{
- if (event->type == GDK_ENTER_NOTIFY && !gtk_widget_has_grab (GTK_WIDGET (list->priv->popup)))
- enl_popup_grab (list, (GdkEvent *) event);
-
- return TRUE;
-}
-
-static void
-enl_tree_select_node (ENameSelectorList *list,
- gint n)
-{
- EDestinationStore *store;
- ENameSelectorEntry *entry;
- GtkTreeSelection *selection;
- GtkTreeViewColumn *column;
- GtkTreeView *tree_view;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- entry = E_NAME_SELECTOR_ENTRY (list);
- tree_view = GTK_TREE_VIEW (list->priv->tree_view);
- store = e_name_selector_entry_peek_destination_store (entry);
- selection = gtk_tree_view_get_selection (tree_view);
- iter.stamp = e_destination_store_get_stamp (store);
- iter.user_data = GINT_TO_POINTER (n - 1);
-
- gtk_tree_selection_unselect_all (selection);
- gtk_tree_selection_select_iter (selection, &iter);
-
- column = gtk_tree_view_get_column (tree_view, 0);
- path = e_destination_store_get_path (GTK_TREE_MODEL (store), &iter);
- gtk_tree_view_scroll_to_cell (tree_view, path, column, FALSE, 0, 0);
- gtk_tree_view_set_cursor (tree_view, path, column, FALSE);
- gtk_widget_grab_focus (GTK_WIDGET (tree_view));
- /*Fixme: We should grab the focus to the column. How? */
-
- gtk_tree_path_free (path);
-}
-
-static gboolean
-enl_entry_key_press_event (ENameSelectorList *list,
- GdkEventKey *event,
- gpointer dummy)
-{
- ENameSelectorEntry *entry;
- EDestinationStore *store;
-
- entry = E_NAME_SELECTOR_ENTRY (list);
- store = e_name_selector_entry_peek_destination_store (entry);
-
- if ( (event->state & GDK_CONTROL_MASK) && (event->keyval == GDK_KEY_Down)) {
- enl_popup_position (list);
- gtk_widget_show_all (GTK_WIDGET (list->priv->popup));
- enl_popup_grab (list, (GdkEvent *) event);
- list->priv->rows = e_destination_store_get_destination_count (store);
- enl_popup_size (list);
- enl_tree_select_node (list, 1);
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-delete_row (GtkTreePath *path,
- ENameSelectorList *list)
-{
- ENameSelectorEntry *entry;
- EDestinationStore *store;
- GtkTreeIter iter;
- gint n, len;
- GtkTreeSelection *selection;
-
- entry = E_NAME_SELECTOR_ENTRY (list);
- store = e_name_selector_entry_peek_destination_store (entry);
-
- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
- return;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->tree_view));
- len = e_destination_store_get_destination_count (store);
- n = GPOINTER_TO_INT (iter.user_data);
-
- e_destination_store_remove_destination_nth (store, n);
-
- /* If the last one is deleted select the last but one or the deleted +1 */
- if (n == len -1)
- n -= 1;
-
- /* We deleted the last entry */
- if (len == 1) {
- enl_popup_ungrab (list);
- if (list->priv->menu)
- gtk_menu_popdown (GTK_MENU (list->priv->menu));
- gtk_widget_hide (GTK_WIDGET (list->priv->popup));
- return;
- }
-
- iter.stamp = e_destination_store_get_stamp (store);
- iter.user_data = GINT_TO_POINTER (n);
-
- gtk_tree_selection_unselect_all (selection);
- gtk_tree_selection_select_iter (selection, &iter);
-
- gtk_tree_path_free (path);
-
- list->priv->rows = e_destination_store_get_destination_count (store);
- enl_popup_size (list);
-}
-
-static void
-popup_activate_email (ENameSelectorEntry *name_selector_entry,
- GtkWidget *menu_item)
-{
- EDestination *destination;
- EContact *contact;
- gint email_num;
-
- destination = e_name_selector_entry_get_popup_destination (name_selector_entry);
- if (!destination)
- return;
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- email_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "order"));
- e_destination_set_contact (destination, contact, email_num);
-}
-
-static void
-popup_activate_list (EDestination *destination,
- GtkWidget *item)
-{
- gboolean status = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item));
-
- e_destination_set_ignored (destination, !status);
-}
-
-static void
-destination_set_list (GtkWidget *item,
- EDestination *destination)
-{
- EContact *contact;
- gboolean status = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item));
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- e_destination_set_ignored (destination, !status);
-}
-
-static void
-destination_set_email (GtkWidget *item,
- EDestination *destination)
-{
- gint email_num;
- EContact *contact;
-
- if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
- return;
- contact = e_destination_get_contact (destination);
- if (!contact)
- return;
-
- email_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "order"));
- e_destination_set_contact (destination, contact, email_num);
-}
-
-typedef struct {
- ENameSelectorList *list;
- GtkTreePath *path;
-}PopupDeleteRowInfo;
-
-static void
-popup_delete_row (GtkWidget *w,
- PopupDeleteRowInfo *row_info)
-{
- delete_row (row_info->path, row_info->list);
- g_free (row_info);
-}
-
-static void
-menu_deactivate (GtkMenuShell *junk,
- ENameSelectorList *list)
-{
- enl_popup_grab (list, NULL);
-}
-
-static gboolean
-enl_tree_button_press_event (GtkWidget *widget,
- GdkEventButton *event,
- ENameSelectorList *list)
-{
- GtkWidget *menu;
- EDestination *destination;
- ENameSelectorEntry *entry;
- EDestinationStore *store;
- EContact *contact;
- GtkWidget *menu_item;
- GList *email_list = NULL, *l;
- gint i;
- gint email_num, len;
- gchar *delete_label;
- GSList *group = NULL;
- gboolean is_list;
- gboolean show_menu = FALSE;
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GtkTreePath *path;
- PopupDeleteRowInfo *row_info;
- GtkTreeIter iter;
-
- entry = E_NAME_SELECTOR_ENTRY (list);
- tree_view = GTK_TREE_VIEW (list->priv->tree_view);
- store = e_name_selector_entry_peek_destination_store (entry);
-
- if (!gtk_widget_has_grab (GTK_WIDGET (list->priv->popup)))
- enl_popup_grab (list, (GdkEvent *) event);
-
- gtk_tree_view_get_dest_row_at_pos (
- tree_view, event->x, event->y, &path, NULL);
- selection = gtk_tree_view_get_selection (tree_view);
- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
- return FALSE;
-
- gtk_tree_selection_unselect_all (selection);
- gtk_tree_selection_select_iter (selection, &iter);
-
- if (event->button != 3) {
- return FALSE;
- }
-
- destination = e_destination_store_get_destination (store, &iter);
-
- if (!destination)
- return FALSE;
-
- contact = e_destination_get_contact (destination);
- if (!contact)
- return FALSE;
-
- if (list->priv->menu) {
- gtk_menu_popdown (GTK_MENU (list->priv->menu));
- }
- menu = gtk_menu_new ();
- g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivate), list);
- list->priv->menu = menu;
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time ());
-
- email_num = e_destination_get_email_num (destination);
-
- /* Addresses */
- is_list = e_contact_get (contact, E_CONTACT_IS_LIST) ? TRUE : FALSE;
- if (is_list) {
- const GList *dests = e_destination_list_get_dests (destination);
- GList *iters;
- gint length = g_list_length ((GList *) dests);
-
- for (iters = (GList *) dests; iters; iters = iters->next) {
- EDestination *dest = (EDestination *) iters->data;
- const gchar *email = e_destination_get_email (dest);
-
- if (!email || *email == '\0')
- continue;
-
- if (length > 1) {
- menu_item = gtk_check_menu_item_new_with_label (email);
- g_signal_connect (
- menu_item, "toggled",
- G_CALLBACK (destination_set_list), dest);
- } else {
- menu_item = gtk_menu_item_new_with_label (email);
- }
-
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- show_menu = TRUE;
-
- if (length > 1) {
- gtk_check_menu_item_set_active (
- GTK_CHECK_MENU_ITEM (menu_item),
- !e_destination_is_ignored (dest));
- g_signal_connect_swapped (
- menu_item, "activate",
- G_CALLBACK (popup_activate_list), dest);
- }
- }
-
- } else {
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- len = g_list_length (email_list);
-
- for (l = email_list, i = 0; l; l = g_list_next (l), i++) {
- gchar *email = l->data;
-
- if (!email || *email == '\0')
- continue;
-
- if (len > 1) {
- menu_item = gtk_radio_menu_item_new_with_label (group, email);
- group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
- g_signal_connect (
- menu_item, "toggled",
- G_CALLBACK (destination_set_email),
- destination);
- } else {
- menu_item = gtk_menu_item_new_with_label (email);
- }
-
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- show_menu = TRUE;
- g_object_set_data (G_OBJECT (menu_item), "order", GINT_TO_POINTER (i));
-
- if (i == email_num && len > 1) {
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
- g_signal_connect_swapped (
- menu_item, "activate",
- G_CALLBACK (popup_activate_email),
- entry);
- }
- }
- g_list_foreach (email_list, (GFunc) g_free, NULL);
- g_list_free (email_list);
- }
-
- /* Separator */
-
- if (show_menu) {
- menu_item = gtk_separator_menu_item_new ();
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
- }
-
- delete_label = g_strdup_printf (_("_Delete %s"), (gchar *) e_contact_get_const (contact, E_CONTACT_FILE_AS));
- menu_item = gtk_menu_item_new_with_mnemonic (delete_label);
- g_free (delete_label);
- gtk_widget_show (menu_item);
- gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
-
- row_info = g_new (PopupDeleteRowInfo, 1);
- row_info->list = list;
- row_info->path = path;
-
- g_signal_connect (
- menu_item, "activate",
- G_CALLBACK (popup_delete_row), row_info);
-
- return TRUE;
-
-}
-
-static gboolean
-enl_tree_key_press_event (GtkWidget *w,
- GdkEventKey *event,
- ENameSelectorList *list)
-{
- if (event->keyval == GDK_KEY_Escape) {
- enl_popup_ungrab (list);
- gtk_widget_hide ( GTK_WIDGET (list->priv->popup));
- return TRUE;
- } else if (event->keyval == GDK_KEY_Delete) {
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GList *paths;
-
- tree_view = GTK_TREE_VIEW (list->priv->tree_view);
- selection = gtk_tree_view_get_selection (tree_view);
- paths = gtk_tree_selection_get_selected_rows (selection, NULL);
- paths = g_list_reverse (paths);
- g_list_foreach (paths, (GFunc) delete_row, list);
- g_list_free (paths);
- } else if (event->keyval != GDK_KEY_Up && event->keyval != GDK_KEY_Down
- && event->keyval != GDK_KEY_Shift_R && event->keyval != GDK_KEY_Shift_L
- && event->keyval != GDK_KEY_Control_R && event->keyval != GDK_KEY_Control_L) {
- enl_popup_ungrab (list);
- gtk_widget_hide ( GTK_WIDGET (list->priv->popup));
- gtk_widget_event (GTK_WIDGET (list), (GdkEvent *) event);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-e_name_selector_list_expand_clicked (ENameSelectorList *list)
-{
- ENameSelectorEntry *entry;
- EDestinationStore *store;
-
- entry = E_NAME_SELECTOR_ENTRY (list);
- store = e_name_selector_entry_peek_destination_store (entry);
-
- if (!gtk_widget_get_visible (GTK_WIDGET (list->priv->popup))) {
- enl_popup_position (list);
- gtk_widget_show_all (GTK_WIDGET (list->priv->popup));
- enl_popup_grab (list, NULL);
- list->priv->rows = e_destination_store_get_destination_count (store);
- enl_popup_size (list);
- enl_tree_select_node (list, 1);
- }
- else {
- enl_popup_ungrab (list);
- if (list->priv->menu)
- gtk_menu_popdown (GTK_MENU (list->priv->menu));
- gtk_widget_hide (GTK_WIDGET (list->priv->popup));
- }
-}
-
-static void
-name_selector_list_realize (GtkWidget *widget)
-{
- ENameSelectorList *list;
- ENameSelectorEntry *entry;
- EDestinationStore *store;
-
- /* Chain up to parent's realize() method. */
- GTK_WIDGET_CLASS (e_name_selector_list_parent_class)->realize (widget);
-
- list = E_NAME_SELECTOR_LIST (widget);
- entry = E_NAME_SELECTOR_ENTRY (widget);
- store = e_name_selector_entry_peek_destination_store (entry);
-
- gtk_tree_view_set_model (
- GTK_TREE_VIEW (list->priv->tree_view), GTK_TREE_MODEL (store));
-}
-
-static void
-e_name_selector_list_class_init (ENameSelectorListClass *class)
-{
- GtkWidgetClass *widget_class;
-
- g_type_class_add_private (class, sizeof (ENameSelectorListPrivate));
-
- widget_class = GTK_WIDGET_CLASS (class);
- widget_class->realize = name_selector_list_realize;
-}
-
-static void
-e_name_selector_list_init (ENameSelectorList *list)
-{
- GtkCellRenderer *renderer;
- GtkWidget *scroll, *popup_frame, *vgrid;
- GtkTreeSelection *selection;
- GtkTreeViewColumn *column;
- ENameSelectorEntry *entry;
- EDestinationStore *store;
- GtkEntryCompletion *completion;
-
- list->priv = E_NAME_SELECTOR_LIST_GET_PRIVATE (list);
- list->priv->menu = NULL;
-
- entry = E_NAME_SELECTOR_ENTRY (list);
- store = e_name_selector_entry_peek_destination_store (entry);
-
- list->priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list->priv->tree_view), FALSE);
- gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (list->priv->tree_view), FALSE);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->tree_view));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
- gtk_tree_selection_unselect_all (selection);
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (list->priv->tree_view), FALSE);
-
- completion = gtk_entry_get_completion (GTK_ENTRY (list));
- gtk_entry_completion_set_inline_completion (completion, TRUE);
- gtk_entry_completion_set_popup_completion (completion, TRUE);
-
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes ("Name", renderer, "text", E_DESTINATION_STORE_COLUMN_ADDRESS, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (list->priv->tree_view), column);
- gtk_tree_view_column_set_clickable (column, TRUE);
-
- scroll = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (scroll),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_NONE);
- gtk_widget_set_size_request (
- gtk_scrolled_window_get_vscrollbar (
- GTK_SCROLLED_WINDOW (scroll)), -1, 0);
- gtk_widget_set_vexpand (scroll, TRUE);
- gtk_widget_set_valign (scroll, GTK_ALIGN_FILL);
-
- list->priv->popup = GTK_WINDOW (gtk_window_new (GTK_WINDOW_POPUP));
- gtk_window_set_resizable (GTK_WINDOW (list->priv->popup), FALSE);
-
- popup_frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (
- GTK_FRAME (popup_frame), GTK_SHADOW_ETCHED_IN);
-
- gtk_container_add (GTK_CONTAINER (list->priv->popup), popup_frame);
-
- vgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", FALSE,
- "row-spacing", 0,
- NULL);
- gtk_container_add (GTK_CONTAINER (popup_frame), vgrid);
-
- gtk_container_add (GTK_CONTAINER (scroll), list->priv->tree_view);
- gtk_container_add (GTK_CONTAINER (vgrid), scroll);
-
- g_signal_connect_after (
- GTK_WIDGET (list), "focus-in-event",
- G_CALLBACK (enl_entry_focus_in), NULL);
- g_signal_connect (
- GTK_WIDGET (list), "focus-out-event",
- G_CALLBACK (enl_entry_focus_out), NULL);
- g_signal_connect (
- GTK_WIDGET (list), "key-press-event",
- G_CALLBACK (enl_entry_key_press_event), NULL);
-
- g_signal_connect_after (
- list->priv->tree_view, "key-press-event",
- G_CALLBACK (enl_tree_key_press_event), list);
- g_signal_connect (
- list->priv->tree_view, "button-press-event",
- G_CALLBACK (enl_tree_button_press_event), list);
-
- g_signal_connect (
- list->priv->popup, "button-press-event",
- G_CALLBACK (enl_popup_button_press), list);
- g_signal_connect (
- list->priv->popup, "focus-out-event",
- G_CALLBACK (enl_popup_focus_out), list);
- g_signal_connect (
- list->priv->popup, "enter-notify-event",
- G_CALLBACK (enl_popup_enter_notify), list);
-
-}
-
-ENameSelectorList *
-e_name_selector_list_new (ESourceRegistry *registry)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
-
- return g_object_new (
- E_TYPE_NAME_SELECTOR_LIST,
- "registry", registry, NULL);
-}
+++ /dev/null
-/*
- * Single-line text entry widget for EDestinations.
- *
- * 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:
- * Srinivasa Ragavan <sragavan@novell.com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_NAME_SELECTOR_LIST_H
-#define E_NAME_SELECTOR_LIST_H
-
-#include <gtk/gtk.h>
-#include <libebook/libebook.h>
-
-#include <libedataserverui/e-contact-store.h>
-#include <libedataserverui/e-destination-store.h>
-#include <libedataserverui/e-tree-model-generator.h>
-#include <libedataserverui/e-name-selector-entry.h>
-
-/* Standard GObject macros */
-#define E_TYPE_NAME_SELECTOR_LIST \
- (e_name_selector_list_get_type ())
-#define E_NAME_SELECTOR_LIST(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_NAME_SELECTOR_LIST, ENameSelectorList))
-#define E_NAME_SELECTOR_LIST_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_NAME_SELECTOR_LIST, ENameSelectorListClass))
-#define E_IS_NAME_SELECTOR_LIST(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_NAME_SELECTOR_LIST))
-#define E_IS_NAME_SELECTOR_LIST_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_NAME_SELECTOR_LIST))
-#define E_NAME_SELECTOR_LIST_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_NAME_SELECTOR_LIST, ENameSelectorListClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ENameSelectorList ENameSelectorList;
-typedef struct _ENameSelectorListClass ENameSelectorListClass;
-typedef struct _ENameSelectorListPrivate ENameSelectorListPrivate;
-
-struct _ENameSelectorList {
- ENameSelectorEntry parent;
- ENameSelectorListPrivate *priv;
-};
-
-struct _ENameSelectorListClass {
- ENameSelectorEntryClass parent_class;
-};
-
-GType e_name_selector_list_get_type (void);
-ENameSelectorList *
- e_name_selector_list_new (ESourceRegistry *registry);
-void e_name_selector_list_expand_clicked
- (ENameSelectorList *list);
-
-G_END_DECLS
-
-#endif /* E_NAME_SELECTOR_LIST_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector-model.c - Model for contact selection.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-#include "e-name-selector-model.h"
-
-#define E_NAME_SELECTOR_MODEL_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_NAME_SELECTOR_MODEL, ENameSelectorModelPrivate))
-
-typedef struct {
- gchar *name;
- gchar *pretty_name;
-
- EDestinationStore *destination_store;
-}
-Section;
-
-struct _ENameSelectorModelPrivate {
- GArray *sections;
- EContactStore *contact_store;
- ETreeModelGenerator *contact_filter;
- GHashTable *destination_uid_hash;
-};
-
-static gint generate_contact_rows (EContactStore *contact_store, GtkTreeIter *iter,
- ENameSelectorModel *name_selector_model);
-static void override_email_address (EContactStore *contact_store, GtkTreeIter *iter,
- gint permutation_n, gint column, GValue *value,
- ENameSelectorModel *name_selector_model);
-static void free_section (ENameSelectorModel *name_selector_model, gint n);
-
-/* ------------------ *
- * Class/object setup *
- * ------------------ */
-
-/* Signals */
-
-enum {
- SECTION_ADDED,
- SECTION_REMOVED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-G_DEFINE_TYPE (ENameSelectorModel, e_name_selector_model, G_TYPE_OBJECT)
-
-static void
-e_name_selector_model_init (ENameSelectorModel *name_selector_model)
-{
- name_selector_model->priv =
- E_NAME_SELECTOR_MODEL_GET_PRIVATE (name_selector_model);
-
- name_selector_model->priv->sections = g_array_new (FALSE, FALSE, sizeof (Section));
- name_selector_model->priv->contact_store = e_contact_store_new ();
-
- name_selector_model->priv->contact_filter =
- e_tree_model_generator_new (GTK_TREE_MODEL (name_selector_model->priv->contact_store));
- e_tree_model_generator_set_generate_func (
- name_selector_model->priv->contact_filter,
- (ETreeModelGeneratorGenerateFunc) generate_contact_rows,
- name_selector_model, NULL);
- e_tree_model_generator_set_modify_func (name_selector_model->priv->contact_filter,
- (ETreeModelGeneratorModifyFunc) override_email_address,
- name_selector_model, NULL);
-
- g_object_unref (name_selector_model->priv->contact_store);
-
- name_selector_model->priv->destination_uid_hash = NULL;
-}
-
-static void
-name_selector_model_finalize (GObject *object)
-{
- ENameSelectorModelPrivate *priv;
- gint i;
-
- priv = E_NAME_SELECTOR_MODEL_GET_PRIVATE (object);
-
- for (i = 0; i < priv->sections->len; i++)
- free_section (E_NAME_SELECTOR_MODEL (object), i);
-
- g_array_free (priv->sections, TRUE);
- g_object_unref (priv->contact_filter);
-
- if (priv->destination_uid_hash)
- g_hash_table_destroy (priv->destination_uid_hash);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_name_selector_model_parent_class)->finalize (object);
-}
-
-static void
-e_name_selector_model_class_init (ENameSelectorModelClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ENameSelectorModelPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = name_selector_model_finalize;
-
- signals[SECTION_ADDED] = g_signal_new (
- "section-added",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ENameSelectorModelClass, section_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- signals[SECTION_REMOVED] = g_signal_new (
- "section-removed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ENameSelectorModelClass, section_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-}
-
-/**
- * e_name_selector_model_new:
- *
- * Creates a new #ENameSelectorModel.
- *
- * Returns: A new #ENameSelectorModel.
- **/
-ENameSelectorModel *
-e_name_selector_model_new (void)
-{
- return E_NAME_SELECTOR_MODEL (g_object_new (E_TYPE_NAME_SELECTOR_MODEL, NULL));
-}
-
-/* ---------------------------- *
- * GtkTreeModelFilter filtering *
- * ---------------------------- */
-
-static void
-deep_free_list (GList *list)
-{
- GList *l;
-
- for (l = list; l; l = g_list_next (l))
- g_free (l->data);
-
- g_list_free (list);
-}
-
-static gint
-generate_contact_rows (EContactStore *contact_store,
- GtkTreeIter *iter,
- ENameSelectorModel *name_selector_model)
-{
- EContact *contact;
- const gchar *contact_uid;
- gint n_rows, used_rows = 0;
- gint i;
-
- contact = e_contact_store_get_contact (contact_store, iter);
- g_assert (contact != NULL);
-
- contact_uid = e_contact_get_const (contact, E_CONTACT_UID);
- if (!contact_uid)
- return 0; /* Can happen with broken databases */
-
- for (i = 0; i < name_selector_model->priv->sections->len; i++) {
- Section *section;
- GList *destinations;
- GList *l;
-
- section = &g_array_index (name_selector_model->priv->sections, Section, i);
- destinations = e_destination_store_list_destinations (section->destination_store);
-
- for (l = destinations; l; l = g_list_next (l)) {
- EDestination *destination = l->data;
- const gchar *destination_uid;
-
- destination_uid = e_destination_get_contact_uid (destination);
- if (destination_uid && !strcmp (contact_uid, destination_uid)) {
- used_rows++;
- }
- }
-
- g_list_free (destinations);
- }
-
- if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
- n_rows = 1 - used_rows;
- } else {
- GList *email_list;
-
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- n_rows = g_list_length (email_list) - used_rows;
- deep_free_list (email_list);
- }
-
- g_return_val_if_fail (n_rows >= 0, 0);
-
- return n_rows;
-}
-
-static void
-override_email_address (EContactStore *contact_store,
- GtkTreeIter *iter,
- gint permutation_n,
- gint column,
- GValue *value,
- ENameSelectorModel *name_selector_model)
-{
- if (column == E_CONTACT_EMAIL_1) {
- EContact *contact;
- GList *email_list;
- gchar *email;
-
- contact = e_contact_store_get_contact (contact_store, iter);
- email_list = e_name_selector_model_get_contact_emails_without_used (name_selector_model, contact, TRUE);
- g_return_if_fail (g_list_length (email_list) <= permutation_n);
- email = g_strdup (g_list_nth_data (email_list, permutation_n));
- g_value_set_string (value, email);
- e_name_selector_model_free_emails_list (email_list);
- } else {
- gtk_tree_model_get_value (GTK_TREE_MODEL (contact_store), iter, column, value);
- }
-}
-
-/* --------------- *
- * Section helpers *
- * --------------- */
-
-typedef struct
-{
- ENameSelectorModel *name_selector_model;
- GHashTable *other_hash;
-}
-HashCompare;
-
-static void
-emit_destination_uid_changes_cb (gchar *uid_num,
- gpointer value,
- HashCompare *hash_compare)
-{
- EContactStore *contact_store = hash_compare->name_selector_model->priv->contact_store;
-
- if (!hash_compare->other_hash || !g_hash_table_lookup (hash_compare->other_hash, uid_num)) {
- GtkTreeIter iter;
- GtkTreePath *path;
- gchar *sep;
-
- sep = strrchr (uid_num, ':');
- g_return_if_fail (sep != NULL);
-
- *sep = '\0';
- if (e_contact_store_find_contact (contact_store, uid_num, &iter)) {
- *sep = ':';
-
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (contact_store), &iter);
- gtk_tree_model_row_changed (GTK_TREE_MODEL (contact_store), path, &iter);
- gtk_tree_path_free (path);
- } else {
- *sep = ':';
- }
- }
-}
-
-static void
-destinations_changed (ENameSelectorModel *name_selector_model)
-{
- GHashTable *destination_uid_hash_new;
- GHashTable *destination_uid_hash_old;
- HashCompare hash_compare;
- gint i;
-
- destination_uid_hash_new = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
- for (i = 0; i < name_selector_model->priv->sections->len; i++) {
- Section *section = &g_array_index (name_selector_model->priv->sections, Section, i);
- GList *destinations;
- GList *l;
-
- destinations = e_destination_store_list_destinations (section->destination_store);
-
- for (l = destinations; l; l = g_list_next (l)) {
- EDestination *destination = l->data;
- const gchar *destination_uid;
-
- destination_uid = e_destination_get_contact_uid (destination);
- if (destination_uid)
- g_hash_table_insert (
- destination_uid_hash_new,
- g_strdup_printf (
- "%s:%d", destination_uid,
- e_destination_get_email_num (destination)),
- GINT_TO_POINTER (TRUE));
- }
-
- g_list_free (destinations);
- }
-
- destination_uid_hash_old = name_selector_model->priv->destination_uid_hash;
- name_selector_model->priv->destination_uid_hash = destination_uid_hash_new;
-
- hash_compare.name_selector_model = name_selector_model;
-
- hash_compare.other_hash = destination_uid_hash_old;
- g_hash_table_foreach (
- destination_uid_hash_new,
- (GHFunc) emit_destination_uid_changes_cb,
- &hash_compare);
-
- if (destination_uid_hash_old) {
- hash_compare.other_hash = destination_uid_hash_new;
- g_hash_table_foreach (
- destination_uid_hash_old,
- (GHFunc) emit_destination_uid_changes_cb,
- &hash_compare);
-
- g_hash_table_destroy (destination_uid_hash_old);
- }
-}
-
-static void
-free_section (ENameSelectorModel *name_selector_model,
- gint n)
-{
- Section *section;
-
- g_assert (n >= 0);
- g_assert (n < name_selector_model->priv->sections->len);
-
- section = &g_array_index (name_selector_model->priv->sections, Section, n);
-
- g_signal_handlers_disconnect_matched (
- section->destination_store, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, name_selector_model);
-
- g_free (section->name);
- g_free (section->pretty_name);
- g_object_unref (section->destination_store);
-}
-
-static gint
-find_section_by_name (ENameSelectorModel *name_selector_model,
- const gchar *name)
-{
- gint i;
-
- g_assert (name != NULL);
-
- for (i = 0; i < name_selector_model->priv->sections->len; i++) {
- Section *section = &g_array_index (name_selector_model->priv->sections, Section, i);
-
- if (!strcmp (name, section->name))
- return i;
- }
-
- return -1;
-}
-
-/* ---------------------- *
- * ENameSelectorModel API *
- * ---------------------- */
-
-/**
- * e_name_selector_model_peek_contact_store:
- * @name_selector_model: an #ENameSelectorModel
- *
- * Gets the #EContactStore associated with @name_selector_model.
- *
- * Returns: An #EContactStore.
- **/
-EContactStore *
-e_name_selector_model_peek_contact_store (ENameSelectorModel *name_selector_model)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model), NULL);
-
- return name_selector_model->priv->contact_store;
-}
-
-/**
- * e_name_selector_model_peek_contact_filter:
- * @name_selector_model: an #ENameSelectorModel
- *
- * Gets the #ETreeModelGenerator being used to filter and/or extend the
- * list of contacts in @name_selector_model's #EContactStore.
- *
- * Returns: An #ETreeModelGenerator.
- **/
-ETreeModelGenerator *
-e_name_selector_model_peek_contact_filter (ENameSelectorModel *name_selector_model)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model), NULL);
-
- return name_selector_model->priv->contact_filter;
-}
-
-/**
- * e_name_selector_model_list_sections:
- * @name_selector_model: an #ENameSelectorModel
- *
- * Gets a list of the destination sections in @name_selector_model.
- *
- * Returns: A #GList of pointers to strings. The #GList and the
- * strings belong to the caller, and must be freed when no longer needed.
- **/
-GList *
-e_name_selector_model_list_sections (ENameSelectorModel *name_selector_model)
-{
- GList *section_names = NULL;
- gint i;
-
- g_return_val_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model), NULL);
-
- /* Do this backwards so we can use g_list_prepend () and get correct order */
- for (i = name_selector_model->priv->sections->len - 1; i >= 0; i--) {
- Section *section = &g_array_index (name_selector_model->priv->sections, Section, i);
- gchar *name;
-
- name = g_strdup (section->name);
- section_names = g_list_prepend (section_names, name);
- }
-
- return section_names;
-}
-
-/**
- * e_name_selector_model_add_section:
- * @name_selector_model: an #ENameSelectorModel
- * @name: internal name of this section
- * @pretty_name: user-visible name of this section
- * @destination_store: the #EDestinationStore to use to store the destinations for this
- * section, or %NULL if @name_selector_model should create its own.
- *
- * Adds a destination section to @name_selector_model.
- **/
-void
-e_name_selector_model_add_section (ENameSelectorModel *name_selector_model,
- const gchar *name,
- const gchar *pretty_name,
- EDestinationStore *destination_store)
-{
- Section section;
-
- g_return_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model));
- g_return_if_fail (name != NULL);
- g_return_if_fail (pretty_name != NULL);
-
- if (find_section_by_name (name_selector_model, name) >= 0) {
- g_warning ("ENameSelectorModel already has a section called '%s'!", name);
- return;
- }
-
- memset (§ion, 0, sizeof (Section));
-
- section.name = g_strdup (name);
- section.pretty_name = g_strdup (pretty_name);
-
- if (destination_store)
- section.destination_store = g_object_ref (destination_store);
- else
- section.destination_store = e_destination_store_new ();
-
- g_signal_connect_swapped (
- section.destination_store, "row-changed",
- G_CALLBACK (destinations_changed), name_selector_model);
- g_signal_connect_swapped (
- section.destination_store, "row-deleted",
- G_CALLBACK (destinations_changed), name_selector_model);
- g_signal_connect_swapped (
- section.destination_store, "row-inserted",
- G_CALLBACK (destinations_changed), name_selector_model);
-
- g_array_append_val (name_selector_model->priv->sections, section);
-
- destinations_changed (name_selector_model);
- g_signal_emit (name_selector_model, signals[SECTION_ADDED], 0, name);
-}
-
-/**
- * e_name_selector_model_remove_section:
- * @name_selector_model: an #ENameSelectorModel
- * @name: internal name of the section to remove
- *
- * Removes a destination section from @name_selector_model.
- **/
-void
-e_name_selector_model_remove_section (ENameSelectorModel *name_selector_model,
- const gchar *name)
-{
- gint n;
-
- g_return_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model));
- g_return_if_fail (name != NULL);
-
- n = find_section_by_name (name_selector_model, name);
- if (n < 0) {
- g_warning ("ENameSelectorModel does not have a section called '%s'!", name);
- return;
- }
-
- free_section (name_selector_model, n);
- g_array_remove_index_fast (name_selector_model->priv->sections, n); /* Order doesn't matter */
-
- destinations_changed (name_selector_model);
- g_signal_emit (name_selector_model, signals[SECTION_REMOVED], 0, name);
-}
-
-/**
- * e_name_selector_model_peek_section:
- * @name_selector_model: an #ENameSelectorModel
- * @name: internal name of the section to peek
- * @pretty_name: location in which to store a pointer to the user-visible name of the section,
- * or %NULL if undesired.
- * @destination_store: location in which to store a pointer to the #EDestinationStore being used
- * by the section, or %NULL if undesired
- *
- * Gets the parameters for a destination section.
- **/
-gboolean
-e_name_selector_model_peek_section (ENameSelectorModel *name_selector_model,
- const gchar *name,
- gchar **pretty_name,
- EDestinationStore **destination_store)
-{
- Section *section;
- gint n;
-
- g_return_val_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model), FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- n = find_section_by_name (name_selector_model, name);
- if (n < 0) {
- g_warning ("ENameSelectorModel does not have a section called '%s'!", name);
- return FALSE;
- }
-
- section = &g_array_index (name_selector_model->priv->sections, Section, n);
-
- if (pretty_name)
- *pretty_name = g_strdup (section->pretty_name);
- if (destination_store)
- *destination_store = section->destination_store;
-
- return TRUE;
-}
-
-/**
- * e_name_selector_model_get_contact_emails_without_used:
- * @name_selector_model: an #ENameSelectorModel
- * @contact: to get emails from
- * @remove_used: set to %TRUE to remove used from a list; or set to %FALSE to
- * set used indexes to %NULL and keep them in the returned list
- *
- * Returns list of all email from @contact, without all used
- * in any section. Each item is a string, an email address.
- * Returned list should be freed with @e_name_selector_model_free_emails_list.
- *
- * Since: 2.30
- **/
-GList *
-e_name_selector_model_get_contact_emails_without_used (ENameSelectorModel *name_selector_model,
- EContact *contact,
- gboolean remove_used)
-{
- GList *email_list;
- gint emails;
- gint i;
- const gchar *contact_uid;
-
- g_return_val_if_fail (name_selector_model != NULL, NULL);
- g_return_val_if_fail (E_IS_NAME_SELECTOR_MODEL (name_selector_model), NULL);
- g_return_val_if_fail (contact != NULL, NULL);
- g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
-
- contact_uid = e_contact_get_const (contact, E_CONTACT_UID);
- g_return_val_if_fail (contact_uid != NULL, NULL);
-
- email_list = e_contact_get (contact, E_CONTACT_EMAIL);
- emails = g_list_length (email_list);
-
- for (i = 0; i < name_selector_model->priv->sections->len; i++) {
- Section *section;
- GList *destinations;
- GList *l;
-
- section = &g_array_index (name_selector_model->priv->sections, Section, i);
- destinations = e_destination_store_list_destinations (section->destination_store);
-
- for (l = destinations; l; l = g_list_next (l)) {
- EDestination *destination = l->data;
- const gchar *destination_uid;
-
- destination_uid = e_destination_get_contact_uid (destination);
- if (destination_uid && !strcmp (contact_uid, destination_uid)) {
- gint email_num = e_destination_get_email_num (destination);
-
- if (email_num < 0 || email_num >= emails) {
- g_warning ("%s: Destination's email_num %d out of bounds 0..%d", G_STRFUNC, email_num, emails - 1);
- } else {
- GList *nth = g_list_nth (email_list, email_num);
-
- g_return_val_if_fail (nth != NULL, NULL);
-
- g_free (nth->data);
- nth->data = NULL;
- }
- }
- }
-
- g_list_free (destinations);
- }
-
- if (remove_used) {
- /* remove all with data NULL, which are those used already */
- do {
- emails = g_list_length (email_list);
- email_list = g_list_remove (email_list, NULL);
- } while (g_list_length (email_list) != emails);
- }
-
- return email_list;
-}
-
-/**
- * e_name_selector_model_free_emails_list:
- * @email_list: list of emails returned from @e_name_selector_model_get_contact_emails_without_used
- *
- * Frees a list of emails returned from @e_name_selector_model_get_contact_emails_without_used.
- *
- * Since: 2.30
- **/
-void
-e_name_selector_model_free_emails_list (GList *email_list)
-{
- deep_free_list (email_list);
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector-model.h - Model for contact selection.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_NAME_SELECTOR_MODEL_H
-#define E_NAME_SELECTOR_MODEL_H
-
-#include <libedataserverui/e-tree-model-generator.h>
-#include <libedataserverui/e-contact-store.h>
-#include <libedataserverui/e-destination-store.h>
-
-/* Standard GObject macros */
-#define E_TYPE_NAME_SELECTOR_MODEL \
- (e_name_selector_model_get_type ())
-#define E_NAME_SELECTOR_MODEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_NAME_SELECTOR_MODEL, ENameSelectorModel))
-#define E_NAME_SELECTOR_MODEL_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_NAME_SELECTOR_MODEL, ENameSelectorModelClass))
-#define E_IS_NAME_SELECTOR_MODEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_NAME_SELECTOR_MODEL))
-#define E_IS_NAME_SELECTOR_MODEL_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_NAME_SELECTOR_MODEL))
-#define E_NAME_SELECTOR_MODEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_NAME_SELECTOR_MODEL, ENameSelectorModelClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ENameSelectorModel ENameSelectorModel;
-typedef struct _ENameSelectorModelClass ENameSelectorModelClass;
-typedef struct _ENameSelectorModelPrivate ENameSelectorModelPrivate;
-
-struct _ENameSelectorModel {
- GObject parent;
- ENameSelectorModelPrivate *priv;
-};
-
-struct _ENameSelectorModelClass {
- GObjectClass parent_class;
-
- /* Signals */
- void (*section_added) (gchar *name);
- void (*section_removed) (gchar *name);
-};
-
-GType e_name_selector_model_get_type (void);
-ENameSelectorModel *
- e_name_selector_model_new (void);
-EContactStore * e_name_selector_model_peek_contact_store
- (ENameSelectorModel *name_selector_model);
-ETreeModelGenerator *
- e_name_selector_model_peek_contact_filter
- (ENameSelectorModel *name_selector_model);
-
-/* Deep copy of section names; free strings and list when you're done */
-GList * e_name_selector_model_list_sections
- (ENameSelectorModel *name_selector_model);
-
-/* pretty_name will be newly allocated, but destination_store must be reffed if you keep it */
-gboolean e_name_selector_model_peek_section
- (ENameSelectorModel *name_selector_model,
- const gchar *name,
- gchar **pretty_name,
- EDestinationStore **destination_store);
-void e_name_selector_model_add_section
- (ENameSelectorModel *name_selector_model,
- const gchar *name,
- const gchar *pretty_name,
- EDestinationStore *destination_store);
-void e_name_selector_model_remove_section
- (ENameSelectorModel *name_selector_model,
- const gchar *name);
-GList * e_name_selector_model_get_contact_emails_without_used
- (ENameSelectorModel *name_selector_model,
- EContact *contact,
- gboolean remove_used);
-void e_name_selector_model_free_emails_list
- (GList *email_list);
-
-G_END_DECLS
-
-#endif /* E_NAME_SELECTOR_MODEL_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector.c - Unified context for contact/destination selection UI.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n-lib.h>
-
-#include <libebook/libebook.h>
-
-#include <libedataserverui/e-client-utils.h>
-#include <libedataserverui/e-contact-store.h>
-#include <libedataserverui/e-destination-store.h>
-#include <libedataserverui/e-book-auth-util.h>
-#include "e-name-selector.h"
-
-#define E_NAME_SELECTOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_NAME_SELECTOR, ENameSelectorPrivate))
-
-typedef struct {
- gchar *name;
- ENameSelectorEntry *entry;
-} Section;
-
-typedef struct {
- EBookClient *client;
- guint is_completion_book : 1;
-} SourceBook;
-
-struct _ENameSelectorPrivate {
- ESourceRegistry *registry;
- ENameSelectorModel *model;
- ENameSelectorDialog *dialog;
-
- GArray *sections;
-
- gboolean books_loaded;
- GCancellable *cancellable;
- GArray *source_books;
-};
-
-enum {
- PROP_0,
- PROP_REGISTRY
-};
-
-G_DEFINE_TYPE (ENameSelector, e_name_selector, G_TYPE_OBJECT)
-
-static void
-reset_pointer_cb (gpointer data,
- GObject *where_was)
-{
- ENameSelector *name_selector = data;
- ENameSelectorPrivate *priv;
- guint ii;
-
- g_return_if_fail (E_IS_NAME_SELECTOR (name_selector));
-
- priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
-
- for (ii = 0; ii < priv->sections->len; ii++) {
- Section *section;
-
- section = &g_array_index (priv->sections, Section, ii);
- if (section->entry == (ENameSelectorEntry *) where_was)
- section->entry = NULL;
- }
-}
-
-static void
-name_selector_book_loaded_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- ENameSelector *name_selector = user_data;
- ESource *source = E_SOURCE (source_object);
- EBookClient *book_client;
- EClient *client = NULL;
- GArray *sections;
- SourceBook source_book;
- guint ii;
- GError *error = NULL;
-
- e_client_utils_open_new_finish (source, result, &client, &error);
-
- if (error != NULL) {
- if (!g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_REPOSITORY_OFFLINE)
- && !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OFFLINE_UNAVAILABLE)
- && !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)
- && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning (
- "ENameSelector: Could not load \"%s\": %s",
- e_source_get_display_name (source), error->message);
- g_error_free (error);
- goto exit;
- }
-
- book_client = E_BOOK_CLIENT (client);
- g_return_if_fail (E_IS_BOOK_CLIENT (book_client));
-
- source_book.client = book_client;
- source_book.is_completion_book = TRUE;
-
- g_array_append_val (name_selector->priv->source_books, source_book);
-
- sections = name_selector->priv->sections;
-
- for (ii = 0; ii < sections->len; ii++) {
- EContactStore *store;
- Section *section;
-
- section = &g_array_index (sections, Section, ii);
- if (section->entry == NULL)
- continue;
-
- store = e_name_selector_entry_peek_contact_store (
- section->entry);
- if (store != NULL)
- e_contact_store_add_client (store, book_client);
- }
-
- exit:
- g_object_unref (name_selector);
-}
-
-/**
- * e_name_selector_load_books:
- * @name_selector: an #ENameSelector
- *
- * Loads address books available for the @name_selector.
- * This can be called only once and it can be cancelled
- * by e_name_selector_cancel_loading().
- *
- * Since: 3.2
- **/
-void
-e_name_selector_load_books (ENameSelector *name_selector)
-{
- ESourceRegistry *registry;
- GList *list, *iter;
- const gchar *extension_name;
-
- g_return_if_fail (E_IS_NAME_SELECTOR (name_selector));
-
- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
- registry = e_name_selector_get_registry (name_selector);
- list = e_source_registry_list_sources (registry, extension_name);
-
- for (iter = list; iter != NULL; iter = g_list_next (iter)) {
- ESource *source = E_SOURCE (iter->data);
- ESourceAutocomplete *extension;
- const gchar *extension_name;
-
- extension_name = E_SOURCE_EXTENSION_AUTOCOMPLETE;
- extension = e_source_get_extension (source, extension_name);
-
- /* Skip disabled address books. */
- if (!e_source_registry_check_enabled (registry, source))
- continue;
-
- /* Only load address books with autocomplete enabled,
- * so as to avoid unnecessary authentication prompts. */
- if (!e_source_autocomplete_get_include_me (extension))
- continue;
-
- e_client_utils_open_new (
- source, E_CLIENT_SOURCE_TYPE_CONTACTS,
- TRUE, name_selector->priv->cancellable,
- name_selector_book_loaded_cb,
- g_object_ref (name_selector));
- }
-
- g_list_free_full (list, (GDestroyNotify) g_object_unref);
-}
-
-/**
- * e_name_selector_cancel_loading:
- * @name_selector: an #ENameSelector
- *
- * Cancels any pending address book load operations. This might be called
- * before an owner unrefs this @name_selector.
- *
- * Since: 3.2
- **/
-void
-e_name_selector_cancel_loading (ENameSelector *name_selector)
-{
- g_return_if_fail (E_IS_NAME_SELECTOR (name_selector));
- g_return_if_fail (name_selector->priv->cancellable != NULL);
-
- g_cancellable_cancel (name_selector->priv->cancellable);
-}
-
-static void
-name_selector_set_registry (ENameSelector *name_selector,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_return_if_fail (name_selector->priv->registry == NULL);
-
- name_selector->priv->registry = g_object_ref (registry);
-}
-
-static void
-name_selector_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- name_selector_set_registry (
- E_NAME_SELECTOR (object),
- g_value_get_object (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-name_selector_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_name_selector_get_registry (
- E_NAME_SELECTOR (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-name_selector_dispose (GObject *object)
-{
- ENameSelectorPrivate *priv;
- guint ii;
-
- priv = E_NAME_SELECTOR_GET_PRIVATE (object);
-
- if (priv->cancellable) {
- g_cancellable_cancel (priv->cancellable);
- g_object_unref (priv->cancellable);
- priv->cancellable = NULL;
- }
-
- for (ii = 0; ii < priv->source_books->len; ii++) {
- SourceBook *source_book;
-
- source_book = &g_array_index (
- priv->source_books, SourceBook, ii);
- if (source_book->client != NULL)
- g_object_unref (source_book->client);
- }
-
- for (ii = 0; ii < priv->sections->len; ii++) {
- Section *section;
-
- section = &g_array_index (priv->sections, Section, ii);
- if (section->entry)
- g_object_weak_unref (
- G_OBJECT (section->entry),
- reset_pointer_cb, object);
- g_free (section->name);
- }
-
- g_array_set_size (priv->source_books, 0);
- g_array_set_size (priv->sections, 0);
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_name_selector_parent_class)->dispose (object);
-}
-
-static void
-name_selector_finalize (GObject *object)
-{
- ENameSelectorPrivate *priv;
-
- priv = E_NAME_SELECTOR_GET_PRIVATE (object);
-
- g_array_free (priv->source_books, TRUE);
- g_array_free (priv->sections, TRUE);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_name_selector_parent_class)->finalize (object);
-}
-
-static void
-e_name_selector_class_init (ENameSelectorClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ENameSelectorPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = name_selector_set_property;
- object_class->get_property = name_selector_get_property;
- object_class->dispose = name_selector_dispose;
- object_class->finalize = name_selector_finalize;
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- "Registry",
- "Data source registry",
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-}
-
-static void
-e_name_selector_init (ENameSelector *name_selector)
-{
- GArray *sections;
- GArray *source_books;
-
- sections = g_array_new (FALSE, FALSE, sizeof (Section));
- source_books = g_array_new (FALSE, FALSE, sizeof (SourceBook));
-
- name_selector->priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
- name_selector->priv->sections = sections;
- name_selector->priv->model = e_name_selector_model_new ();
- name_selector->priv->source_books = source_books;
- name_selector->priv->cancellable = g_cancellable_new ();
- name_selector->priv->books_loaded = FALSE;
-}
-
-/**
- * e_name_selector_new:
- * @registry: an #ESourceRegistry
- *
- * Creates a new #ENameSelector.
- *
- * Returns: A new #ENameSelector.
- **/
-ENameSelector *
-e_name_selector_new (ESourceRegistry *registry)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
-
- return g_object_new (
- E_TYPE_NAME_SELECTOR,
- "registry", registry, NULL);
-}
-
-/**
- * e_name_selector_get_registry:
- * @name_selector: an #ENameSelector
- *
- * Returns the #ESourceRegistry passed to e_name_selector_new().
- *
- * Returns: the #ESourceRegistry
- *
- * Since: 3.6
- **/
-ESourceRegistry *
-e_name_selector_get_registry (ENameSelector *name_selector)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
-
- return name_selector->priv->registry;
-}
-
-/* ------- *
- * Helpers *
- * ------- */
-
-static gint
-add_section (ENameSelector *name_selector,
- const gchar *name)
-{
- GArray *array;
- Section section;
-
- g_assert (name != NULL);
-
- memset (§ion, 0, sizeof (Section));
- section.name = g_strdup (name);
-
- array = name_selector->priv->sections;
- g_array_append_val (array, section);
- return array->len - 1;
-}
-
-static gint
-find_section_by_name (ENameSelector *name_selector,
- const gchar *name)
-{
- GArray *array;
- gint i;
-
- g_assert (name != NULL);
-
- array = name_selector->priv->sections;
-
- for (i = 0; i < array->len; i++) {
- Section *section = &g_array_index (array, Section, i);
-
- if (!strcmp (name, section->name))
- return i;
- }
-
- return -1;
-}
-
-/* ----------------- *
- * ENameSelector API *
- * ----------------- */
-
-/**
- * e_name_selector_peek_model:
- * @name_selector: an #ENameSelector
- *
- * Gets the #ENameSelectorModel used by @name_selector.
- *
- * Returns: The #ENameSelectorModel used by @name_selector.
- **/
-ENameSelectorModel *
-e_name_selector_peek_model (ENameSelector *name_selector)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
-
- return name_selector->priv->model;
-}
-
-/**
- * e_name_selector_peek_dialog:
- * @name_selector: an #ENameSelector
- *
- * Gets the #ENameSelectorDialog used by @name_selector.
- *
- * Returns: The #ENameSelectorDialog used by @name_selector.
- **/
-ENameSelectorDialog *
-e_name_selector_peek_dialog (ENameSelector *name_selector)
-{
- g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
-
- if (name_selector->priv->dialog == NULL) {
- ESourceRegistry *registry;
- ENameSelectorDialog *dialog;
- ENameSelectorModel *model;
-
- registry = e_name_selector_get_registry (name_selector);
- dialog = e_name_selector_dialog_new (registry);
- name_selector->priv->dialog = dialog;
-
- model = e_name_selector_peek_model (name_selector);
- e_name_selector_dialog_set_model (dialog, model);
-
- g_signal_connect (
- dialog, "delete-event",
- G_CALLBACK (gtk_widget_hide_on_delete), name_selector);
- }
-
- return name_selector->priv->dialog;
-}
-
-/**
- * e_name_selector_show_dialog:
- * @name_selector: an #ENameSelector
- * @for_transient_widget: a widget parent or %NULL
- *
- * Shows the associated dialog, and sets the transient parent to the
- * GtkWindow top-level of "for_transient_widget if set (it should be)
- *
- * Since: 2.32
- **/
-void
-e_name_selector_show_dialog (ENameSelector *name_selector,
- GtkWidget *for_transient_widget)
-{
- GtkWindow *top = NULL;
- ENameSelectorDialog *dialog;
-
- g_return_if_fail (E_IS_NAME_SELECTOR (name_selector));
-
- dialog = e_name_selector_peek_dialog (name_selector);
- if (for_transient_widget)
- top = GTK_WINDOW (gtk_widget_get_toplevel (for_transient_widget));
- if (top)
- gtk_window_set_transient_for (GTK_WINDOW (dialog), top);
-
- gtk_widget_show (GTK_WIDGET (dialog));
-}
-
-/**
- * e_name_selector_peek_section_entry:
- * @name_selector: an #ENameSelector
- * @name: the name of the section to peek
- *
- * Gets the #ENameSelectorEntry for the section specified by @name.
- *
- * Returns: The #ENameSelectorEntry for the named section, or %NULL if it
- * doesn't exist in the #ENameSelectorModel.
- **/
-ENameSelectorEntry *
-e_name_selector_peek_section_entry (ENameSelector *name_selector,
- const gchar *name)
-{
- ENameSelectorPrivate *priv;
- ENameSelectorModel *model;
- EDestinationStore *destination_store;
- Section *section;
- gint n;
-
- g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
- g_return_val_if_fail (name != NULL, NULL);
-
- priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
- model = e_name_selector_peek_model (name_selector);
-
- if (!e_name_selector_model_peek_section (
- model, name, NULL, &destination_store))
- return NULL;
-
- n = find_section_by_name (name_selector, name);
- if (n < 0)
- n = add_section (name_selector, name);
-
- section = &g_array_index (name_selector->priv->sections, Section, n);
-
- if (!section->entry) {
- ESourceRegistry *registry;
- EContactStore *contact_store;
- gchar *text;
- gint i;
-
- registry = e_name_selector_get_registry (name_selector);
- section->entry = e_name_selector_entry_new (registry);
- g_object_weak_ref (G_OBJECT (section->entry), reset_pointer_cb, name_selector);
- if (pango_parse_markup (name, -1, '_', NULL,
- &text, NULL, NULL)) {
- atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (section->entry)), text);
- g_free (text);
- }
- e_name_selector_entry_set_destination_store (section->entry, destination_store);
-
- /* Create a contact store for the entry and assign our already-open books to it */
-
- contact_store = e_contact_store_new ();
-
- for (i = 0; i < priv->source_books->len; i++) {
- SourceBook *source_book = &g_array_index (priv->source_books, SourceBook, i);
-
- if (source_book->is_completion_book && source_book->client)
- e_contact_store_add_client (contact_store, source_book->client);
- }
-
- e_name_selector_entry_set_contact_store (section->entry, contact_store);
- g_object_unref (contact_store);
- }
-
- return section->entry;
-}
-
-/**
- * e_name_selector_peek_section_list:
- * @name_selector: an #ENameSelector
- * @name: the name of the section to peek
- *
- * Gets the #ENameSelectorList for the section specified by @name.
- *
- * Returns: The #ENameSelectorList for the named section, or %NULL if it
- * doesn't exist in the #ENameSelectorModel.
- **/
-
-ENameSelectorList *
-e_name_selector_peek_section_list (ENameSelector *name_selector,
- const gchar *name)
-{
- ENameSelectorPrivate *priv;
- ENameSelectorModel *model;
- EDestinationStore *destination_store;
- Section *section;
- gint n;
-
- g_return_val_if_fail (E_IS_NAME_SELECTOR (name_selector), NULL);
- g_return_val_if_fail (name != NULL, NULL);
-
- priv = E_NAME_SELECTOR_GET_PRIVATE (name_selector);
- model = e_name_selector_peek_model (name_selector);
-
- if (!e_name_selector_model_peek_section (
- model, name, NULL, &destination_store))
- return NULL;
-
- n = find_section_by_name (name_selector, name);
- if (n < 0)
- n = add_section (name_selector, name);
-
- section = &g_array_index (name_selector->priv->sections, Section, n);
-
- if (!section->entry) {
- EContactStore *contact_store;
- ESourceRegistry *registry;
- gchar *text;
- gint i;
-
- registry = name_selector->priv->registry;
- section->entry = (ENameSelectorEntry *)
- e_name_selector_list_new (registry);
- g_object_weak_ref (G_OBJECT (section->entry), reset_pointer_cb, name_selector);
- if (pango_parse_markup (name, -1, '_', NULL,
- &text, NULL, NULL)) {
- atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (section->entry)), text);
- g_free (text);
- }
- e_name_selector_entry_set_destination_store (section->entry, destination_store);
-
- /* Create a contact store for the entry and assign our already-open books to it */
-
- contact_store = e_contact_store_new ();
- for (i = 0; i < priv->source_books->len; i++) {
- SourceBook *source_book = &g_array_index (priv->source_books, SourceBook, i);
-
- if (source_book->is_completion_book && source_book->client)
- e_contact_store_add_client (contact_store, source_book->client);
- }
-
- e_name_selector_entry_set_contact_store (section->entry, contact_store);
- g_object_unref (contact_store);
- }
-
- return (ENameSelectorList *) section->entry;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-name-selector.h - Unified context for contact/destination selection UI.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_NAME_SELECTOR_H
-#define E_NAME_SELECTOR_H
-
-#include <libedataserver/libedataserver.h>
-
-#include <libedataserverui/e-name-selector-model.h>
-#include <libedataserverui/e-name-selector-dialog.h>
-#include <libedataserverui/e-name-selector-entry.h>
-#include <libedataserverui/e-name-selector-list.h>
-
-/* Standard GObject macros */
-#define E_TYPE_NAME_SELECTOR \
- (e_name_selector_get_type ())
-#define E_NAME_SELECTOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_NAME_SELECTOR, ENameSelector))
-#define E_NAME_SELECTOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_NAME_SELECTOR, ENameSelectorClass))
-#define E_IS_NAME_SELECTOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_NAME_SELECTOR))
-#define E_IS_NAME_SELECTOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_NAME_SELECTOR))
-#define E_NAME_SELECTOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_NAME_SELECTOR, ENameSelectorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ENameSelector ENameSelector;
-typedef struct _ENameSelectorClass ENameSelectorClass;
-typedef struct _ENameSelectorPrivate ENameSelectorPrivate;
-
-struct _ENameSelector {
- GObject parent;
- ENameSelectorPrivate *priv;
-};
-
-struct _ENameSelectorClass {
- GObjectClass parent_class;
-};
-
-GType e_name_selector_get_type (void);
-ENameSelector * e_name_selector_new (ESourceRegistry *registry);
-ESourceRegistry *
- e_name_selector_get_registry (ENameSelector *name_selector);
-ENameSelectorModel *
- e_name_selector_peek_model (ENameSelector *name_selector);
-ENameSelectorDialog *
- e_name_selector_peek_dialog (ENameSelector *name_selector);
-ENameSelectorEntry *
- e_name_selector_peek_section_entry
- (ENameSelector *name_selector,
- const gchar *name);
-ENameSelectorList *
- e_name_selector_peek_section_list
- (ENameSelector *name_selector,
- const gchar *name);
-void e_name_selector_show_dialog (ENameSelector *name_selector,
- GtkWidget *for_transient_widget);
-void e_name_selector_load_books (ENameSelector *name_selector);
-void e_name_selector_cancel_loading (ENameSelector *name_selector);
-
-G_END_DECLS
-
-#endif /* E_NAME_SELECTOR_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-passwords.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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- */
-
-/*
- * This looks a lot more complicated than it is, and than you'd think
- * it would need to be. There is however, method to the madness.
- *
- * The code most cope with being called from any thread at any time,
- * recursively from the main thread, and then serialising every
- * request so that sane and correct values are always returned, and
- * duplicate requests are never made.
- *
- * To this end, every call is marshalled and queued and a dispatch
- * method invoked until that request is satisfied. If mainloop
- * recursion occurs, then the sub-call will necessarily return out of
- * order, but will not be processed out of order.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n-lib.h>
-
-#include "e-passwords.h"
-#include "libedataserver/e-data-server-util.h"
-#include "libedataserver/e-flag.h"
-#include "libedataserver/e-url.h"
-
-#define d(x)
-
-typedef struct _EPassMsg EPassMsg;
-
-struct _EPassMsg {
- void (*dispatch) (EPassMsg *);
- EFlag *done;
-
- /* input */
- GtkWindow *parent;
- const gchar *component;
- const gchar *key;
- const gchar *title;
- const gchar *prompt;
- const gchar *oldpass;
- guint32 flags;
-
- /* output */
- gboolean *remember;
- gchar *password;
- GError *error;
-
- /* work variables */
- GtkWidget *entry;
- GtkWidget *check;
- guint ismain:1;
- guint noreply:1; /* supress replies; when calling
- * dispatch functions from others */
-};
-
-G_LOCK_DEFINE_STATIC (passwords);
-static GThread *main_thread = NULL;
-static GHashTable *password_cache = NULL;
-static GtkDialog *password_dialog = NULL;
-static GQueue message_queue = G_QUEUE_INIT;
-static gint idle_id;
-static gint ep_online_state = TRUE;
-
-#define KEY_FILE_GROUP_PREFIX "Passwords-"
-static GKeyFile *key_file = NULL;
-
-static gboolean
-check_key_file (const gchar *funcname)
-{
- if (!key_file)
- g_message ("%s: Failed to create key file!", funcname);
-
- return key_file != NULL;
-}
-
-static gchar *
-ep_key_file_get_filename (void)
-{
- return g_build_filename (
- e_get_user_config_dir (), "credentials", "Passwords", NULL);
-}
-
-static gchar *
-ep_key_file_get_group (const gchar *component)
-{
- return g_strconcat (KEY_FILE_GROUP_PREFIX, component, NULL);
-}
-
-static gchar *
-ep_key_file_normalize_key (const gchar *key)
-{
- /* XXX Previous code converted all slashes and equal signs in the
- * key to underscores for use with "gnome-config" functions. While
- * it may not be necessary to convert slashes for use with GKeyFile,
- * we continue to do the same for backward-compatibility. */
-
- gchar *normalized_key, *cp;
-
- normalized_key = g_strdup (key);
- for (cp = normalized_key; *cp != '\0'; cp++)
- if (*cp == '/' || *cp == '=')
- *cp = '_';
-
- return normalized_key;
-}
-
-static void
-ep_key_file_load (void)
-{
- gchar *filename;
- GError *error = NULL;
-
- if (!check_key_file (G_STRFUNC))
- return;
-
- filename = ep_key_file_get_filename ();
-
- if (!g_file_test (filename, G_FILE_TEST_EXISTS))
- goto exit;
-
- g_key_file_load_from_file (
- key_file, filename, G_KEY_FILE_KEEP_COMMENTS |
- G_KEY_FILE_KEEP_TRANSLATIONS, &error);
-
- if (error != NULL) {
- g_warning ("%s: %s", filename, error->message);
- g_error_free (error);
- }
-
-exit:
- g_free (filename);
-}
-
-static void
-ep_key_file_save (void)
-{
- gchar *contents;
- gchar *filename;
- gchar *pathname;
- gsize length = 0;
- GError *error = NULL;
-
- if (!check_key_file (G_STRFUNC))
- return;
-
- filename = ep_key_file_get_filename ();
- contents = g_key_file_to_data (key_file, &length, &error);
- pathname = g_path_get_dirname (filename);
-
- if (!error) {
- g_mkdir_with_parents (pathname, 0700);
- g_file_set_contents (filename, contents, length, &error);
- }
-
- g_free (pathname);
-
- if (error != NULL) {
- g_warning ("%s: %s", filename, error->message);
- g_error_free (error);
- }
-
- g_free (contents);
- g_free (filename);
-}
-
-static gchar *
-ep_password_encode (const gchar *password)
-{
- /* XXX The previous Base64 encoding function did not encode the
- * password's trailing nul byte. This makes decoding the Base64
- * string into a nul-terminated password more difficult, but we
- * continue to do it this way for backward-compatibility. */
-
- gsize length = strlen (password);
- return g_base64_encode ((const guchar *) password, length);
-}
-
-static gchar *
-ep_password_decode (const gchar *encoded_password)
-{
- /* XXX The previous Base64 encoding function did not encode the
- * password's trailing nul byte, so we have to append a nul byte
- * to the decoded data to make it a nul-terminated string. */
-
- gchar *password;
- gsize length = 0;
-
- password = (gchar *) g_base64_decode (encoded_password, &length);
- password = g_realloc (password, length + 1);
- password[length] = '\0';
-
- return password;
-}
-
-static gboolean
-ep_idle_dispatch (gpointer data)
-{
- EPassMsg *msg;
-
- /* As soon as a password window is up we stop; it will
- re-invoke us when it has been closed down */
- G_LOCK (passwords);
- while (password_dialog == NULL && (msg = g_queue_pop_head (&message_queue)) != NULL) {
- G_UNLOCK (passwords);
-
- msg->dispatch (msg);
-
- G_LOCK (passwords);
- }
-
- idle_id = 0;
- G_UNLOCK (passwords);
-
- return FALSE;
-}
-
-static EPassMsg *
-ep_msg_new (void (*dispatch) (EPassMsg *))
-{
- EPassMsg *msg;
-
- e_passwords_init ();
-
- msg = g_malloc0 (sizeof (*msg));
- msg->dispatch = dispatch;
- msg->done = e_flag_new ();
- msg->ismain = (g_thread_self () == main_thread);
-
- return msg;
-}
-
-static void
-ep_msg_free (EPassMsg *msg)
-{
- /* XXX We really should be passing this back to the caller, but
- * doing so will require breaking the password API. */
- if (msg->error != NULL) {
- g_warning ("%s", msg->error->message);
- g_error_free (msg->error);
- }
-
- e_flag_free (msg->done);
- g_free (msg->password);
- g_free (msg);
-}
-
-static void
-ep_msg_send (EPassMsg *msg)
-{
- gint needidle = 0;
-
- G_LOCK (passwords);
- g_queue_push_tail (&message_queue, msg);
- if (!idle_id) {
- if (!msg->ismain)
- idle_id = g_idle_add (ep_idle_dispatch, NULL);
- else
- needidle = 1;
- }
- G_UNLOCK (passwords);
-
- if (msg->ismain) {
- if (needidle)
- ep_idle_dispatch (NULL);
- while (!e_flag_is_set (msg->done))
- g_main_context_iteration (NULL, TRUE);
- } else
- e_flag_wait (msg->done);
-}
-
-/* the functions that actually do the work */
-
-static void
-ep_clear_passwords_keyfile (EPassMsg *msg)
-{
- gchar *group;
- GError *error = NULL;
-
- if (!check_key_file (G_STRFUNC))
- return;
-
- group = ep_key_file_get_group (msg->component);
-
- if (g_key_file_remove_group (key_file, group, &error))
- ep_key_file_save ();
-
- /* Not finding the requested group is acceptable, but we still
- * want to leave an informational message on the terminal. */
- else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
-
- } else if (error != NULL)
- g_propagate_error (&msg->error, error);
-
- g_free (group);
-}
-
-static void
-ep_clear_passwords (EPassMsg *msg)
-{
- ep_clear_passwords_keyfile (msg);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_forget_passwords_keyfile (EPassMsg *msg)
-{
- gchar **groups;
- gsize length = 0, ii;
-
- if (!check_key_file (G_STRFUNC))
- return;
-
- groups = g_key_file_get_groups (key_file, &length);
-
- if (!groups)
- return;
-
- for (ii = 0; ii < length; ii++) {
- GError *error = NULL;
-
- if (!g_str_has_prefix (groups[ii], KEY_FILE_GROUP_PREFIX))
- continue;
-
- g_key_file_remove_group (key_file, groups[ii], &error);
-
- /* Not finding the requested group is acceptable, but we still
- * want to leave an informational message on the terminal. */
- if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
-
- /* Issue a warning if anything else goes wrong. */
- } else if (error != NULL) {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
- }
- ep_key_file_save ();
- g_strfreev (groups);
-}
-
-static void
-ep_forget_passwords (EPassMsg *msg)
-{
- g_hash_table_remove_all (password_cache);
-
- ep_forget_passwords_keyfile (msg);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_remember_password_keyfile (EPassMsg *msg)
-{
- gchar *group, *key, *password;
-
- password = g_hash_table_lookup (password_cache, msg->key);
- if (password == NULL) {
- g_warning ("Password for key \"%s\" not found", msg->key);
- return;
- }
-
- group = ep_key_file_get_group (msg->component);
- key = ep_key_file_normalize_key (msg->key);
- password = ep_password_encode (password);
-
- g_hash_table_remove (password_cache, msg->key);
- if (check_key_file (G_STRFUNC)) {
- g_key_file_set_string (key_file, group, key, password);
- ep_key_file_save ();
- }
-
- g_free (group);
- g_free (key);
- g_free (password);
-}
-
-static void
-ep_remember_password (EPassMsg *msg)
-{
- ep_remember_password_keyfile (msg);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_forget_password_keyfile (EPassMsg *msg)
-{
- gchar *group, *key;
- GError *error = NULL;
-
- if (!check_key_file (G_STRFUNC))
- return;
-
- group = ep_key_file_get_group (msg->component);
- key = ep_key_file_normalize_key (msg->key);
-
- if (g_key_file_remove_key (key_file, group, key, &error))
- ep_key_file_save ();
-
- /* Not finding the requested key is acceptable, but we still
- * want to leave an informational message on the terminal. */
- else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
-
- /* Not finding the requested group is also acceptable. */
- } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
-
- } else if (error != NULL)
- g_propagate_error (&msg->error, error);
-
- g_free (group);
- g_free (key);
-}
-
-static void
-ep_forget_password (EPassMsg *msg)
-{
- g_hash_table_remove (password_cache, msg->key);
-
- ep_forget_password_keyfile (msg);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_get_password_keyfile (EPassMsg *msg)
-{
- gchar *group, *key, *password;
- GError *error = NULL;
-
- if (!check_key_file (G_STRFUNC))
- return;
-
- group = ep_key_file_get_group (msg->component);
- key = ep_key_file_normalize_key (msg->key);
-
- password = g_key_file_get_string (key_file, group, key, &error);
- if (password != NULL) {
- msg->password = ep_password_decode (password);
- g_free (password);
-
- /* Not finding the requested key is acceptable, but we still
- * want to leave an informational message on the terminal. */
- } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
-
- /* Not finding the requested group is also acceptable. */
- } else if (g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) {
- g_message ("%s", error->message);
- g_error_free (error);
-
- } else if (error != NULL)
- g_propagate_error (&msg->error, error);
-
- g_free (group);
- g_free (key);
-}
-
-static void
-ep_get_password (EPassMsg *msg)
-{
- gchar *password;
-
- /* Check the in-memory cache first. */
- password = g_hash_table_lookup (password_cache, msg->key);
- if (password != NULL) {
- msg->password = g_strdup (password);
-
- } else
- ep_get_password_keyfile (msg);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_add_password (EPassMsg *msg)
-{
- g_hash_table_insert (
- password_cache, g_strdup (msg->key),
- g_strdup (msg->oldpass));
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void ep_ask_password (EPassMsg *msg);
-
-static void
-pass_response (GtkDialog *dialog,
- gint response,
- gpointer data)
-{
- EPassMsg *msg = data;
- gint type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
- GList *iter, *trash = NULL;
-
- if (response == GTK_RESPONSE_OK) {
- msg->password = g_strdup (gtk_entry_get_text ((GtkEntry *)msg->entry));
-
- if (type != E_PASSWORDS_REMEMBER_NEVER) {
- gint noreply = msg->noreply;
-
- *msg->remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (msg->check));
-
- msg->noreply = 1;
-
- if (*msg->remember || type == E_PASSWORDS_REMEMBER_FOREVER) {
- msg->oldpass = msg->password;
- ep_add_password (msg);
- }
- if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER)
- ep_remember_password (msg);
-
- msg->noreply = noreply;
- }
- }
-
- gtk_widget_destroy ((GtkWidget *)dialog);
- password_dialog = NULL;
-
- /* ok, here things get interesting, we suck up any pending
- * operations on this specific password, and return the same
- * result or ignore other operations */
-
- G_LOCK (passwords);
- for (iter = g_queue_peek_head_link (&message_queue); iter != NULL; iter = iter->next) {
- EPassMsg *pending = iter->data;
-
- if ((pending->dispatch == ep_forget_password
- || pending->dispatch == ep_get_password
- || pending->dispatch == ep_ask_password)
- && (strcmp (pending->component, msg->component) == 0
- && strcmp (pending->key, msg->key) == 0)) {
-
- /* Satisfy the pending operation. */
- pending->password = g_strdup (msg->password);
- e_flag_set (pending->done);
-
- /* Mark the queue node for deletion. */
- trash = g_list_prepend (trash, iter);
- }
- }
-
- /* Expunge the message queue. */
- for (iter = trash; iter != NULL; iter = iter->next)
- g_queue_delete_link (&message_queue, iter->data);
- g_list_free (trash);
-
- G_UNLOCK (passwords);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-
- ep_idle_dispatch (NULL);
-}
-
-static gboolean
-update_capslock_state (GtkDialog *dialog,
- GdkEvent *event,
- GtkWidget *label)
-{
- GdkModifierType mask = 0;
- GdkWindow *window;
- gchar *markup = NULL;
- GdkDeviceManager *device_manager;
- GdkDevice *device;
-
- device_manager = gdk_display_get_device_manager (gtk_widget_get_display (label));
- device = gdk_device_manager_get_client_pointer (device_manager);
- window = gtk_widget_get_window (GTK_WIDGET (dialog));
- gdk_window_get_device_position (window, device, NULL, NULL, &mask);
-
- /* The space acts as a vertical placeholder. */
- markup = g_markup_printf_escaped (
- "<small>%s</small>", (mask & GDK_LOCK_MASK) ?
- _("You have the Caps Lock key on.") : " ");
- gtk_label_set_markup (GTK_LABEL (label), markup);
- g_free (markup);
-
- return FALSE;
-}
-
-static void
-ep_ask_password (EPassMsg *msg)
-{
- GtkWidget *widget;
- GtkWidget *container;
- GtkWidget *action_area;
- GtkWidget *content_area;
- gint type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
- guint noreply = msg->noreply;
- gboolean visible;
- AtkObject *a11y;
-
- msg->noreply = 1;
-
- widget = gtk_dialog_new_with_buttons (
- msg->title, msg->parent, 0,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
-#if !GTK_CHECK_VERSION(2,90,7)
- g_object_set (widget, "has-separator", FALSE, NULL);
-#endif
- gtk_dialog_set_default_response (
- GTK_DIALOG (widget), GTK_RESPONSE_OK);
- gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
- gtk_window_set_transient_for (GTK_WINDOW (widget), msg->parent);
- gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER_ON_PARENT);
- gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
- password_dialog = GTK_DIALOG (widget);
-
- action_area = gtk_dialog_get_action_area (password_dialog);
- content_area = gtk_dialog_get_content_area (password_dialog);
-
- /* Override GtkDialog defaults */
- gtk_box_set_spacing (GTK_BOX (action_area), 12);
- gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
- gtk_box_set_spacing (GTK_BOX (content_area), 12);
- gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
-
- /* Grid */
- container = gtk_grid_new ();
- gtk_grid_set_column_spacing (GTK_GRID (container), 12);
- gtk_grid_set_row_spacing (GTK_GRID (container), 6);
- gtk_widget_show (container);
-
- gtk_box_pack_start (
- GTK_BOX (content_area), container, FALSE, TRUE, 0);
-
- /* Password Image */
- widget = gtk_image_new_from_icon_name (
- "dialog-password", GTK_ICON_SIZE_DIALOG);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
- g_object_set (G_OBJECT (widget),
- "halign", GTK_ALIGN_FILL,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
-
- gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 3);
-
- /* Password Label */
- widget = gtk_label_new (NULL);
- gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
- gtk_label_set_markup (GTK_LABEL (widget), msg->prompt);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1);
-
- /* Password Entry */
- widget = gtk_entry_new ();
- a11y = gtk_widget_get_accessible (widget);
- visible = !(msg->flags & E_PASSWORDS_SECRET);
- atk_object_set_description (a11y, msg->prompt);
- gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
- gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
- gtk_widget_grab_focus (widget);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
- msg->entry = widget;
-
- if ((msg->flags & E_PASSWORDS_REPROMPT)) {
- ep_get_password (msg);
- if (msg->password != NULL) {
- gtk_entry_set_text (GTK_ENTRY (widget), msg->password);
- g_free (msg->password);
- msg->password = NULL;
- }
- }
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
-
- /* Caps Lock Label */
- widget = gtk_label_new (NULL);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
-
- g_signal_connect (
- password_dialog, "key-release-event",
- G_CALLBACK (update_capslock_state), widget);
- g_signal_connect (
- password_dialog, "focus-in-event",
- G_CALLBACK (update_capslock_state), widget);
-
- /* static password, shouldn't be remembered between sessions,
- but will be remembered within the session beyond our control */
- if (type != E_PASSWORDS_REMEMBER_NEVER) {
- if (msg->flags & E_PASSWORDS_PASSPHRASE) {
- widget = gtk_check_button_new_with_mnemonic (
- (type == E_PASSWORDS_REMEMBER_FOREVER)
- ? _("_Remember this passphrase")
- : _("_Remember this passphrase for"
- " the remainder of this session"));
- } else {
- widget = gtk_check_button_new_with_mnemonic (
- (type == E_PASSWORDS_REMEMBER_FOREVER)
- ? _("_Remember this password")
- : _("_Remember this password for"
- " the remainder of this session"));
- }
-
- gtk_toggle_button_set_active (
- GTK_TOGGLE_BUTTON (widget), *msg->remember);
- if (msg->flags & E_PASSWORDS_DISABLE_REMEMBER)
- gtk_widget_set_sensitive (widget, FALSE);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
- msg->check = widget;
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1);
- }
-
- msg->noreply = noreply;
-
- g_signal_connect (
- password_dialog, "response",
- G_CALLBACK (pass_response), msg);
-
- if (msg->parent) {
- gtk_dialog_run (GTK_DIALOG (password_dialog));
- } else {
- gtk_window_present (GTK_WINDOW (password_dialog));
- /* workaround GTK+ bug (see Gnome's bugzilla bug #624229) */
- gtk_grab_add (GTK_WIDGET (password_dialog));
- }
-}
-
-/**
- * e_passwords_init:
- *
- * Initializes the e_passwords routines. Must be called before any other
- * e_passwords_* function.
- **/
-void
-e_passwords_init (void)
-{
- G_LOCK (passwords);
-
- if (password_cache == NULL) {
- password_cache = g_hash_table_new_full (
- g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
- main_thread = g_thread_self ();
-
- /* Load the keyfile even if we're using the keyring.
- * We might be able to extract passwords from it. */
- key_file = g_key_file_new ();
- ep_key_file_load ();
-
- }
-
- G_UNLOCK (passwords);
-}
-
-/**
- * e_passwords_cancel:
- *
- * Cancel any outstanding password operations and close any dialogues
- * currently being shown.
- **/
-void
-e_passwords_cancel (void)
-{
- EPassMsg *msg;
-
- G_LOCK (passwords);
- while ((msg = g_queue_pop_head (&message_queue)) != NULL)
- e_flag_set (msg->done);
- G_UNLOCK (passwords);
-
- if (password_dialog)
- gtk_dialog_response (password_dialog, GTK_RESPONSE_CANCEL);
-}
-
-/**
- * e_passwords_shutdown:
- *
- * Cleanup routine to call before exiting.
- **/
-void
-e_passwords_shutdown (void)
-{
- EPassMsg *msg;
-
- G_LOCK (passwords);
-
- while ((msg = g_queue_pop_head (&message_queue)) != NULL)
- e_flag_set (msg->done);
-
- if (password_cache != NULL) {
- g_hash_table_destroy (password_cache);
- password_cache = NULL;
- }
-
-
- G_UNLOCK (passwords);
-
- if (password_dialog != NULL)
- gtk_dialog_response (password_dialog, GTK_RESPONSE_CANCEL);
-}
-
-/**
- * e_passwords_set_online:
- * @state:
- *
- * Set the offline-state of the application. This is a work-around
- * for having the backends fully offline aware, and returns a
- * cancellation response instead of prompting for passwords.
- *
- * FIXME: This is not a permanent api, review post 2.0.
- **/
-void
-e_passwords_set_online (gint state)
-{
- ep_online_state = state;
- /* TODO: we could check that a request is open and close it, or maybe who cares */
-}
-
-/**
- * e_passwords_forget_passwords:
- *
- * Forgets all cached passwords, in memory and on disk.
- **/
-void
-e_passwords_forget_passwords (void)
-{
- EPassMsg *msg = ep_msg_new (ep_forget_passwords);
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_clear_passwords:
- *
- * Forgets all disk cached passwords for the component.
- **/
-void
-e_passwords_clear_passwords (const gchar *component_name)
-{
- EPassMsg *msg = ep_msg_new (ep_clear_passwords);
-
- msg->component = component_name;
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_remember_password:
- * @key: the key
- *
- * Saves the password associated with @key to disk.
- **/
-void
-e_passwords_remember_password (const gchar *component_name,
- const gchar *key)
-{
- EPassMsg *msg;
-
- g_return_if_fail (component_name != NULL);
- g_return_if_fail (key != NULL);
-
- msg = ep_msg_new (ep_remember_password);
- msg->component = component_name;
- msg->key = key;
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_forget_password:
- * @key: the key
- *
- * Forgets the password associated with @key, in memory and on disk.
- **/
-void
-e_passwords_forget_password (const gchar *component_name,
- const gchar *key)
-{
- EPassMsg *msg;
-
- g_return_if_fail (component_name != NULL);
- g_return_if_fail (key != NULL);
-
- msg = ep_msg_new (ep_forget_password);
- msg->component = component_name;
- msg->key = key;
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_get_password:
- * @key: the key
- *
- * Returns: the password associated with @key, or %NULL. Caller
- * must free the returned password.
- **/
-gchar *
-e_passwords_get_password (const gchar *component_name,
- const gchar *key)
-{
- EPassMsg *msg;
- gchar *passwd;
-
- g_return_val_if_fail (component_name != NULL, NULL);
- g_return_val_if_fail (key != NULL, NULL);
-
- msg = ep_msg_new (ep_get_password);
- msg->component = component_name;
- msg->key = key;
-
- ep_msg_send (msg);
-
- passwd = msg->password;
- msg->password = NULL;
- ep_msg_free (msg);
-
- return passwd;
-}
-
-/**
- * e_passwords_add_password:
- * @key: a key
- * @passwd: the password for @key
- *
- * This stores the @key/@passwd pair in the current session's password
- * hash.
- **/
-void
-e_passwords_add_password (const gchar *key,
- const gchar *passwd)
-{
- EPassMsg *msg;
-
- g_return_if_fail (key != NULL);
- g_return_if_fail (passwd != NULL);
-
- msg = ep_msg_new (ep_add_password);
- msg->key = key;
- msg->oldpass = passwd;
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_ask_password:
- * @title: title for the password dialog
- * @component_name: the name of the component for which we're storing
- * the password (e.g. Mail, Addressbook, etc.)
- * @key: key to store the password under
- * @prompt: prompt string
- * @type: whether or not to offer to remember the password,
- * and for how long.
- * @remember: on input, the default state of the remember checkbox.
- * on output, the state of the checkbox when the dialog was closed.
- * @parent: parent window of the dialog, or %NULL
- *
- * Asks the user for a password.
- *
- * Returns: the password, which the caller must free, or %NULL if
- * the user cancelled the operation. *@remember will be set if the
- * return value is non-%NULL and @remember_type is not
- * E_PASSWORDS_DO_NOT_REMEMBER.
- **/
-gchar *
-e_passwords_ask_password (const gchar *title,
- const gchar *component_name,
- const gchar *key,
- const gchar *prompt,
- EPasswordsRememberType type,
- gboolean *remember,
- GtkWindow *parent)
-{
- gchar *passwd;
- EPassMsg *msg;
-
- g_return_val_if_fail (component_name != NULL, NULL);
- g_return_val_if_fail (key != NULL, NULL);
-
- if ((type & E_PASSWORDS_ONLINE) && !ep_online_state)
- return NULL;
-
- msg = ep_msg_new (ep_ask_password);
- msg->title = title;
- msg->component = component_name;
- msg->key = key;
- msg->prompt = prompt;
- msg->flags = type;
- msg->remember = remember;
- msg->parent = parent;
-
- ep_msg_send (msg);
- passwd = msg->password;
- msg->password = NULL;
- ep_msg_free (msg);
-
- return passwd;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- * e-passwords.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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- */
-
-/*
- * This looks a lot more complicated than it is, and than you'd think
- * it would need to be. There is however, method to the madness.
- *
- * The code must cope with being called from any thread at any time,
- * recursively from the main thread, and then serialising every
- * request so that sane and correct values are always returned, and
- * duplicate requests are never made.
- *
- * To this end, every call is marshalled and queued and a dispatch
- * method invoked until that request is satisfied. If mainloop
- * recursion occurs, then the sub-call will necessarily return out of
- * order, but will not be processed out of order.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n-lib.h>
-
-/* XXX Yeah, yeah... */
-#define SECRET_API_SUBJECT_TO_CHANGE
-
-#include <libsecret/secret.h>
-
-#include <libedataserver/libedataserver.h>
-
-#include "e-passwords.h"
-
-#define d(x)
-
-typedef struct _EPassMsg EPassMsg;
-
-struct _EPassMsg {
- void (*dispatch) (EPassMsg *);
- EFlag *done;
-
- /* input */
- GtkWindow *parent;
- const gchar *key;
- const gchar *title;
- const gchar *prompt;
- const gchar *oldpass;
- guint32 flags;
-
- /* output */
- gboolean *remember;
- gchar *password;
- GError *error;
-
- /* work variables */
- GtkWidget *entry;
- GtkWidget *check;
- guint ismain : 1;
- guint noreply:1; /* supress replies; when calling
- * dispatch functions from others */
-};
-
-/* XXX probably want to share this with evalution-source-registry-migrate-sources.c */
-static const SecretSchema e_passwords_schema = {
- "org.gnome.Evolution.Password",
- SECRET_SCHEMA_DONT_MATCH_NAME,
- {
- { "application", SECRET_SCHEMA_ATTRIBUTE_STRING, },
- { "user", SECRET_SCHEMA_ATTRIBUTE_STRING, },
- { "server", SECRET_SCHEMA_ATTRIBUTE_STRING, },
- { "protocol", SECRET_SCHEMA_ATTRIBUTE_STRING, },
- }
-};
-
-G_LOCK_DEFINE_STATIC (passwords);
-static GThread *main_thread = NULL;
-static GHashTable *password_cache = NULL;
-static GtkDialog *password_dialog = NULL;
-static GQueue message_queue = G_QUEUE_INIT;
-static gint idle_id;
-static gint ep_online_state = TRUE;
-
-static EUri *
-ep_keyring_uri_new (const gchar *string,
- GError **error)
-{
- EUri *uri;
-
- uri = e_uri_new (string);
- g_return_val_if_fail (uri != NULL, NULL);
-
- /* LDAP URIs do not have usernames, so use the URI as the username. */
- if (uri->user == NULL && uri->protocol != NULL &&
- (strcmp (uri->protocol, "ldap") == 0|| strcmp (uri->protocol, "google") == 0))
- uri->user = g_strdelimit (g_strdup (string), "/=", '_');
-
- /* Make sure the URI has the required components. */
- if (uri->user == NULL && uri->host == NULL) {
- g_set_error_literal (
- error, G_IO_ERROR,
- G_IO_ERROR_INVALID_ARGUMENT,
- _("Keyring key is unusable: no user or host name"));
- e_uri_free (uri);
- uri = NULL;
- }
-
- return uri;
-}
-
-static gboolean
-ep_idle_dispatch (gpointer data)
-{
- EPassMsg *msg;
-
- /* As soon as a password window is up we stop; it will
- * re - invoke us when it has been closed down */
- G_LOCK (passwords);
- while (password_dialog == NULL && (msg = g_queue_pop_head (&message_queue)) != NULL) {
- G_UNLOCK (passwords);
-
- msg->dispatch (msg);
-
- G_LOCK (passwords);
- }
-
- idle_id = 0;
- G_UNLOCK (passwords);
-
- return FALSE;
-}
-
-static EPassMsg *
-ep_msg_new (void (*dispatch) (EPassMsg *))
-{
- EPassMsg *msg;
-
- e_passwords_init ();
-
- msg = g_malloc0 (sizeof (*msg));
- msg->dispatch = dispatch;
- msg->done = e_flag_new ();
- msg->ismain = (g_thread_self () == main_thread);
-
- return msg;
-}
-
-static void
-ep_msg_free (EPassMsg *msg)
-{
- /* XXX We really should be passing this back to the caller, but
- * doing so will require breaking the password API. */
- if (msg->error != NULL) {
- g_warning ("%s", msg->error->message);
- g_error_free (msg->error);
- }
-
- e_flag_free (msg->done);
- g_free (msg->password);
- g_free (msg);
-}
-
-static void
-ep_msg_send (EPassMsg *msg)
-{
- gint needidle = 0;
-
- G_LOCK (passwords);
- g_queue_push_tail (&message_queue, msg);
- if (!idle_id) {
- if (!msg->ismain)
- idle_id = g_idle_add (ep_idle_dispatch, NULL);
- else
- needidle = 1;
- }
- G_UNLOCK (passwords);
-
- if (msg->ismain) {
- if (needidle)
- ep_idle_dispatch (NULL);
- while (!e_flag_is_set (msg->done))
- g_main_context_iteration (NULL, TRUE);
- } else
- e_flag_wait (msg->done);
-}
-
-/* the functions that actually do the work */
-
-static void
-ep_clear_passwords (EPassMsg *msg)
-{
- GError *error = NULL;
-
- /* Find all Evolution passwords and delete them. */
- secret_password_clear_sync (
- &e_passwords_schema, NULL, &error,
- "application", "Evolution", NULL);
-
- if (error != NULL)
- g_propagate_error (&msg->error, error);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_remember_password (EPassMsg *msg)
-{
- gchar *password;
- EUri *uri;
- GError *error = NULL;
-
- password = g_hash_table_lookup (password_cache, msg->key);
- if (password == NULL) {
- g_warning ("Password for key \"%s\" not found", msg->key);
- goto exit;
- }
-
- uri = ep_keyring_uri_new (msg->key, &msg->error);
- if (uri == NULL)
- goto exit;
-
- secret_password_store_sync (
- &e_passwords_schema,
- SECRET_COLLECTION_DEFAULT,
- msg->key, password,
- NULL, &error,
- "application", "Evolution",
- "user", uri->user,
- "server", uri->host,
- "protocol", uri->protocol,
- NULL);
-
- /* Only remove the password from the session hash
- * if the keyring insertion was successful. */
- if (error == NULL)
- g_hash_table_remove (password_cache, msg->key);
- else
- g_propagate_error (&msg->error, error);
-
- e_uri_free (uri);
-
-exit:
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_forget_password (EPassMsg *msg)
-{
- EUri *uri;
- GError *error = NULL;
-
- g_hash_table_remove (password_cache, msg->key);
-
- uri = ep_keyring_uri_new (msg->key, &msg->error);
- if (uri == NULL)
- goto exit;
-
- /* Find all Evolution passwords matching the URI and delete them.
- *
- * XXX We didn't always store protocols in the keyring, so for
- * backward-compatibility we need to lookup passwords by user
- * and host only (no protocol). But we do send the protocol
- * to ep_keyring_delete_passwords(), which also knows about
- * the backward-compatibility issue and will filter the list
- * appropriately. */
- secret_password_clear_sync (
- &e_passwords_schema, NULL, &error,
- "application", "Evolution",
- "user", uri->user,
- "server", uri->host,
- NULL);
-
- if (error != NULL)
- g_propagate_error (&msg->error, error);
-
- e_uri_free (uri);
-
-exit:
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_get_password (EPassMsg *msg)
-{
- EUri *uri;
- gchar *password;
- GError *error = NULL;
-
- /* Check the in-memory cache first. */
- password = g_hash_table_lookup (password_cache, msg->key);
- if (password != NULL) {
- msg->password = g_strdup (password);
- goto exit;
- }
-
- uri = ep_keyring_uri_new (msg->key, &msg->error);
- if (uri == NULL)
- goto exit;
-
- msg->password = secret_password_lookup_sync (
- &e_passwords_schema, NULL, &error,
- "application", "Evolution",
- "user", uri->user,
- "server", uri->host,
- "protocol", uri->protocol,
- NULL);
-
- if (msg->password != NULL)
- goto done;
-
- /* Clear the previous error, if there was one.
- * It's likely to occur again. */
- if (error != NULL)
- g_clear_error (&error);
-
- /* XXX We didn't always store protocols in the keyring, so for
- * backward-compatibility we also need to lookup passwords
- * by user and host only (no protocol). */
- msg->password = secret_password_lookup_sync (
- &e_passwords_schema, NULL, &error,
- "application", "Evolution",
- "user", uri->user,
- "server", uri->host,
- NULL);
-
-done:
- if (error != NULL)
- g_propagate_error (&msg->error, error);
-
- e_uri_free (uri);
-
-exit:
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void
-ep_add_password (EPassMsg *msg)
-{
- g_hash_table_insert (
- password_cache, g_strdup (msg->key),
- g_strdup (msg->oldpass));
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-}
-
-static void ep_ask_password (EPassMsg *msg);
-
-static void
-pass_response (GtkDialog *dialog,
- gint response,
- gpointer data)
-{
- EPassMsg *msg = data;
- gint type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
- GList *iter, *trash = NULL;
-
- if (response == GTK_RESPONSE_OK) {
- msg->password = g_strdup (gtk_entry_get_text ((GtkEntry *) msg->entry));
-
- if (type != E_PASSWORDS_REMEMBER_NEVER) {
- gint noreply = msg->noreply;
-
- *msg->remember = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (msg->check));
-
- msg->noreply = 1;
-
- if (*msg->remember || type == E_PASSWORDS_REMEMBER_FOREVER) {
- msg->oldpass = msg->password;
- ep_add_password (msg);
- }
- if (*msg->remember && type == E_PASSWORDS_REMEMBER_FOREVER)
- ep_remember_password (msg);
-
- msg->noreply = noreply;
- }
- }
-
- gtk_widget_destroy ((GtkWidget *) dialog);
- password_dialog = NULL;
-
- /* ok, here things get interesting, we suck up any pending
- * operations on this specific password, and return the same
- * result or ignore other operations */
-
- G_LOCK (passwords);
- for (iter = g_queue_peek_head_link (&message_queue); iter != NULL; iter = iter->next) {
- EPassMsg *pending = iter->data;
-
- if ((pending->dispatch == ep_forget_password
- || pending->dispatch == ep_get_password
- || pending->dispatch == ep_ask_password)
- && strcmp (pending->key, msg->key) == 0) {
-
- /* Satisfy the pending operation. */
- pending->password = g_strdup (msg->password);
- e_flag_set (pending->done);
-
- /* Mark the queue node for deletion. */
- trash = g_list_prepend (trash, iter);
- }
- }
-
- /* Expunge the message queue. */
- for (iter = trash; iter != NULL; iter = iter->next)
- g_queue_delete_link (&message_queue, iter->data);
- g_list_free (trash);
-
- G_UNLOCK (passwords);
-
- if (!msg->noreply)
- e_flag_set (msg->done);
-
- ep_idle_dispatch (NULL);
-}
-
-static gboolean
-update_capslock_state (GtkDialog *dialog,
- GdkEvent *event,
- GtkWidget *label)
-{
- GdkModifierType mask = 0;
- GdkWindow *window;
- gchar *markup = NULL;
- GdkDeviceManager *device_manager;
- GdkDevice *device;
-
- device_manager = gdk_display_get_device_manager (gtk_widget_get_display (label));
- device = gdk_device_manager_get_client_pointer (device_manager);
- window = gtk_widget_get_window (GTK_WIDGET (dialog));
- gdk_window_get_device_position (window, device, NULL, NULL, &mask);
-
- /* The space acts as a vertical placeholder. */
- markup = g_markup_printf_escaped (
- "<small>%s</small>", (mask & GDK_LOCK_MASK) ?
- _("You have the Caps Lock key on.") : " ");
- gtk_label_set_markup (GTK_LABEL (label), markup);
- g_free (markup);
-
- return FALSE;
-}
-
-static void
-ep_ask_password (EPassMsg *msg)
-{
- GtkWidget *widget;
- GtkWidget *container;
- GtkWidget *action_area;
- GtkWidget *content_area;
- gint type = msg->flags & E_PASSWORDS_REMEMBER_MASK;
- guint noreply = msg->noreply;
- gboolean visible;
- AtkObject *a11y;
-
- msg->noreply = 1;
-
- widget = gtk_dialog_new_with_buttons (
- msg->title, msg->parent, 0,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_default_response (
- GTK_DIALOG (widget), GTK_RESPONSE_OK);
- gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
- gtk_window_set_transient_for (GTK_WINDOW (widget), msg->parent);
- gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER_ON_PARENT);
- gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
- password_dialog = GTK_DIALOG (widget);
-
- action_area = gtk_dialog_get_action_area (password_dialog);
- content_area = gtk_dialog_get_content_area (password_dialog);
-
- /* Override GtkDialog defaults */
- gtk_box_set_spacing (GTK_BOX (action_area), 12);
- gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
- gtk_box_set_spacing (GTK_BOX (content_area), 12);
- gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
-
- /* Grid */
- container = gtk_grid_new ();
- gtk_grid_set_column_spacing (GTK_GRID (container), 12);
- gtk_grid_set_row_spacing (GTK_GRID (container), 6);
- gtk_widget_show (container);
-
- gtk_box_pack_start (
- GTK_BOX (content_area), container, FALSE, TRUE, 0);
-
- /* Password Image */
- widget = gtk_image_new_from_icon_name (
- "dialog-password", GTK_ICON_SIZE_DIALOG);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
- g_object_set (G_OBJECT (widget),
- "halign", GTK_ALIGN_FILL,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
-
- gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 3);
-
- /* Password Label */
- widget = gtk_label_new (NULL);
- gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
- gtk_label_set_markup (GTK_LABEL (widget), msg->prompt);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1);
-
- /* Password Entry */
- widget = gtk_entry_new ();
- a11y = gtk_widget_get_accessible (widget);
- visible = !(msg->flags & E_PASSWORDS_SECRET);
- atk_object_set_description (a11y, msg->prompt);
- gtk_entry_set_visibility (GTK_ENTRY (widget), visible);
- gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE);
- gtk_widget_grab_focus (widget);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
- msg->entry = widget;
-
- if ((msg->flags & E_PASSWORDS_REPROMPT)) {
- ep_get_password (msg);
- if (msg->password != NULL) {
- gtk_entry_set_text (GTK_ENTRY (widget), msg->password);
- g_free (msg->password);
- msg->password = NULL;
- }
- }
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1);
-
- /* Caps Lock Label */
- widget = gtk_label_new (NULL);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1);
-
- g_signal_connect (
- password_dialog, "key-release-event",
- G_CALLBACK (update_capslock_state), widget);
- g_signal_connect (
- password_dialog, "focus-in-event",
- G_CALLBACK (update_capslock_state), widget);
-
- /* static password, shouldn't be remembered between sessions,
- * but will be remembered within the session beyond our control */
- if (type != E_PASSWORDS_REMEMBER_NEVER) {
- if (msg->flags & E_PASSWORDS_PASSPHRASE) {
- widget = gtk_check_button_new_with_mnemonic (
- (type == E_PASSWORDS_REMEMBER_FOREVER)
- ? _("_Remember this passphrase")
- : _("_Remember this passphrase for"
- " the remainder of this session"));
- } else {
- widget = gtk_check_button_new_with_mnemonic (
- (type == E_PASSWORDS_REMEMBER_FOREVER)
- ? _("_Remember this password")
- : _("_Remember this password for"
- " the remainder of this session"));
- }
-
- gtk_toggle_button_set_active (
- GTK_TOGGLE_BUTTON (widget), *msg->remember);
- if (msg->flags & E_PASSWORDS_DISABLE_REMEMBER)
- gtk_widget_set_sensitive (widget, FALSE);
- g_object_set (G_OBJECT (widget),
- "hexpand", TRUE,
- "halign", GTK_ALIGN_FILL,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_widget_show (widget);
- msg->check = widget;
-
- gtk_grid_attach (GTK_GRID (container), widget, 1, 3, 1, 1);
- }
-
- msg->noreply = noreply;
-
- g_signal_connect (
- password_dialog, "response",
- G_CALLBACK (pass_response), msg);
-
- if (msg->parent) {
- gtk_dialog_run (GTK_DIALOG (password_dialog));
- } else {
- gtk_window_present (GTK_WINDOW (password_dialog));
- /* workaround GTK+ bug (see Gnome's bugzilla bug #624229) */
- gtk_grab_add (GTK_WIDGET (password_dialog));
- }
-}
-
-/**
- * e_passwords_init:
- *
- * Initializes the e_passwords routines. Must be called before any other
- * e_passwords_* function.
- **/
-void
-e_passwords_init (void)
-{
- G_LOCK (passwords);
-
- if (password_cache == NULL) {
- password_cache = g_hash_table_new_full (
- g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) g_free);
- main_thread = g_thread_self ();
- }
-
- G_UNLOCK (passwords);
-}
-
-/**
- * e_passwords_cancel:
- *
- * Cancel any outstanding password operations and close any dialogues
- * currently being shown.
- **/
-void
-e_passwords_cancel (void)
-{
- EPassMsg *msg;
-
- G_LOCK (passwords);
- while ((msg = g_queue_pop_head (&message_queue)) != NULL)
- e_flag_set (msg->done);
- G_UNLOCK (passwords);
-
- if (password_dialog)
- gtk_dialog_response (password_dialog, GTK_RESPONSE_CANCEL);
-}
-
-/**
- * e_passwords_shutdown:
- *
- * Cleanup routine to call before exiting.
- **/
-void
-e_passwords_shutdown (void)
-{
- EPassMsg *msg;
-
- G_LOCK (passwords);
-
- while ((msg = g_queue_pop_head (&message_queue)) != NULL)
- e_flag_set (msg->done);
-
- if (password_cache != NULL) {
- g_hash_table_destroy (password_cache);
- password_cache = NULL;
- }
-
- G_UNLOCK (passwords);
-
- if (password_dialog != NULL)
- gtk_dialog_response (password_dialog, GTK_RESPONSE_CANCEL);
-}
-
-/**
- * e_passwords_set_online:
- * @state:
- *
- * Set the offline-state of the application. This is a work-around
- * for having the backends fully offline aware, and returns a
- * cancellation response instead of prompting for passwords.
- *
- * FIXME: This is not a permanent api, review post 2.0.
- **/
-void
-e_passwords_set_online (gint state)
-{
- ep_online_state = state;
- /* TODO: we could check that a request is open and close it, or maybe who cares */
-}
-
-/**
- * e_passwords_forget_passwords:
- *
- * Forgets all cached passwords, in memory and on disk.
- **/
-void
-e_passwords_forget_passwords (void)
-{
- EPassMsg *msg = ep_msg_new (ep_clear_passwords);
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_clear_passwords:
- *
- * Forgets all disk cached passwords for the component.
- **/
-void
-e_passwords_clear_passwords (const gchar *unused)
-{
- EPassMsg *msg = ep_msg_new (ep_clear_passwords);
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_remember_password:
- * @key: the key
- *
- * Saves the password associated with @key to disk.
- **/
-void
-e_passwords_remember_password (const gchar *unused,
- const gchar *key)
-{
- EPassMsg *msg;
-
- g_return_if_fail (key != NULL);
-
- msg = ep_msg_new (ep_remember_password);
- msg->key = key;
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_forget_password:
- * @key: the key
- *
- * Forgets the password associated with @key, in memory and on disk.
- **/
-void
-e_passwords_forget_password (const gchar *unused,
- const gchar *key)
-{
- EPassMsg *msg;
-
- g_return_if_fail (key != NULL);
-
- msg = ep_msg_new (ep_forget_password);
- msg->key = key;
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_get_password:
- * @key: the key
- *
- * Returns: the password associated with @key, or %NULL. Caller
- * must free the returned password.
- **/
-gchar *
-e_passwords_get_password (const gchar *unused,
- const gchar *key)
-{
- EPassMsg *msg;
- gchar *passwd;
-
- g_return_val_if_fail (key != NULL, NULL);
-
- msg = ep_msg_new (ep_get_password);
- msg->key = key;
-
- ep_msg_send (msg);
-
- passwd = msg->password;
- msg->password = NULL;
- ep_msg_free (msg);
-
- return passwd;
-}
-
-/**
- * e_passwords_add_password:
- * @key: a key
- * @passwd: the password for @key
- *
- * This stores the @key/@passwd pair in the current session's password
- * hash.
- **/
-void
-e_passwords_add_password (const gchar *key,
- const gchar *passwd)
-{
- EPassMsg *msg;
-
- g_return_if_fail (key != NULL);
- g_return_if_fail (passwd != NULL);
-
- msg = ep_msg_new (ep_add_password);
- msg->key = key;
- msg->oldpass = passwd;
-
- ep_msg_send (msg);
- ep_msg_free (msg);
-}
-
-/**
- * e_passwords_ask_password:
- * @title: title for the password dialog
- * @unused: this argument is no longer used
- * @key: key to store the password under
- * @prompt: prompt string
- * @remember_type: whether or not to offer to remember the password,
- * and for how long.
- * @remember: on input, the default state of the remember checkbox.
- * on output, the state of the checkbox when the dialog was closed.
- * @parent: parent window of the dialog, or %NULL
- *
- * Asks the user for a password.
- *
- * Returns: the password, which the caller must free, or %NULL if
- * the user cancelled the operation. *@remember will be set if the
- * return value is non-%NULL and @remember_type is not
- * E_PASSWORDS_DO_NOT_REMEMBER.
- **/
-gchar *
-e_passwords_ask_password (const gchar *title,
- const gchar *unused,
- const gchar *key,
- const gchar *prompt,
- EPasswordsRememberType remember_type,
- gboolean *remember,
- GtkWindow *parent)
-{
- gchar *passwd;
- EPassMsg *msg;
-
- g_return_val_if_fail (key != NULL, NULL);
-
- if ((remember_type & E_PASSWORDS_ONLINE) && !ep_online_state)
- return NULL;
-
- msg = ep_msg_new (ep_ask_password);
- msg->title = title;
- msg->key = key;
- msg->prompt = prompt;
- msg->flags = remember_type;
- msg->remember = remember;
- msg->parent = parent;
-
- ep_msg_send (msg);
- passwd = msg->password;
- msg->password = NULL;
- ep_msg_free (msg);
-
- return passwd;
-}
+++ /dev/null
-/*
- * e-passwords.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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef EDS_DISABLE_DEPRECATED
-
-#ifndef _E_PASSWORD_H_
-#define _E_PASSWORD_H_
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-/*
- * initialization is now implicit when you call any of the functions
- * below, although this is only correct if the functions are called
- * from the main thread.
- *
- * e_passwords_shutdown should be called at exit time to synch the
- * password on-disk storage, and to free up in-memory storage. */
-void e_passwords_init (void);
-
-void e_passwords_shutdown (void);
-void e_passwords_cancel (void);
-void e_passwords_set_online (gint state);
-void e_passwords_remember_password (const gchar *unused, const gchar *key);
-void e_passwords_add_password (const gchar *key, const gchar *passwd);
-gchar *e_passwords_get_password (const gchar *unused, const gchar *key);
-void e_passwords_forget_password (const gchar *unused, const gchar *key);
-void e_passwords_forget_passwords (void);
-void e_passwords_clear_passwords (const gchar *unused);
-
-typedef enum {
- E_PASSWORDS_REMEMBER_NEVER,
- E_PASSWORDS_REMEMBER_SESSION,
- E_PASSWORDS_REMEMBER_FOREVER,
- E_PASSWORDS_REMEMBER_MASK = 0xf,
-
- /* option bits */
- E_PASSWORDS_SECRET = 1 << 8,
- E_PASSWORDS_REPROMPT = 1 << 9,
- E_PASSWORDS_ONLINE = 1<<10, /* only ask if we're online */
- E_PASSWORDS_DISABLE_REMEMBER = 1<<11, /* disable the 'remember password' checkbox */
- E_PASSWORDS_PASSPHRASE = 1<<12 /* We are asking a passphrase */
-} EPasswordsRememberType;
-
-gchar * e_passwords_ask_password (const gchar *title,
- const gchar *unused,
- const gchar *key,
- const gchar *prompt,
- EPasswordsRememberType remember_type,
- gboolean *remember,
- GtkWindow *parent);
-
-G_END_DECLS
-
-#endif /* _E_PASSWORD_H_ */
-
-#endif /* EDS_DISABLE_DEPRECATED */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source-combo-box.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 Lesser 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 Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-source-combo-box.h"
-#include "e-cell-renderer-color.h"
-
-#define E_SOURCE_COMBO_BOX_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBoxPrivate))
-
-struct _ESourceComboBoxPrivate {
- ESourceRegistry *registry;
- gchar *extension_name;
-
- gulong source_added_handler_id;
- gulong source_removed_handler_id;
- gulong source_enabled_handler_id;
- gulong source_disabled_handler_id;
-
- gboolean show_colors;
-};
-
-enum {
- PROP_0,
- PROP_EXTENSION_NAME,
- PROP_REGISTRY,
- PROP_SHOW_COLORS
-};
-
-enum {
- COLUMN_COLOR, /* GDK_TYPE_COLOR */
- COLUMN_NAME, /* G_TYPE_STRING */
- COLUMN_SENSITIVE, /* G_TYPE_BOOLEAN */
- COLUMN_UID, /* G_TYPE_STRING */
- NUM_COLUMNS
-};
-
-G_DEFINE_TYPE (ESourceComboBox, e_source_combo_box, GTK_TYPE_COMBO_BOX)
-
-static gboolean
-source_combo_box_traverse (GNode *node,
- ESourceComboBox *combo_box)
-{
- ESource *source;
- ESourceSelectable *extension = NULL;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GString *indented;
- GdkColor color;
- const gchar *ext_name;
- const gchar *display_name;
- const gchar *uid;
- gboolean sensitive = FALSE;
- gboolean use_color = FALSE;
- guint depth;
-
- /* Skip the root node. */
- if (G_NODE_IS_ROOT (node))
- return FALSE;
-
- ext_name = e_source_combo_box_get_extension_name (combo_box);
-
- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box));
- gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-
- source = E_SOURCE (node->data);
- uid = e_source_get_uid (source);
- display_name = e_source_get_display_name (source);
-
- indented = g_string_new (NULL);
-
- depth = g_node_depth (node);
- g_warn_if_fail (depth > 1);
- while (--depth > 1)
- g_string_append (indented, " ");
- g_string_append (indented, display_name);
-
- if (ext_name != NULL && e_source_has_extension (source, ext_name)) {
- extension = e_source_get_extension (source, ext_name);
- sensitive = TRUE;
- }
-
- if (E_IS_SOURCE_SELECTABLE (extension)) {
- const gchar *color_spec;
-
- color_spec = e_source_selectable_get_color (extension);
- if (color_spec != NULL && *color_spec != '\0')
- use_color = gdk_color_parse (color_spec, &color);
- }
-
- gtk_list_store_set (
- GTK_LIST_STORE (model), &iter,
- COLUMN_COLOR, use_color ? &color : NULL,
- COLUMN_NAME, indented->str,
- COLUMN_SENSITIVE, sensitive,
- COLUMN_UID, uid,
- -1);
-
- g_string_free (indented, TRUE);
-
- return FALSE;
-}
-
-static void
-source_combo_box_build_model (ESourceComboBox *combo_box)
-{
- ESourceRegistry *registry;
- GtkComboBox *gtk_combo_box;
- GtkTreeModel *model;
- GNode *root;
- const gchar *active_id;
- const gchar *extension_name;
-
- registry = e_source_combo_box_get_registry (combo_box);
- extension_name = e_source_combo_box_get_extension_name (combo_box);
-
- gtk_combo_box = GTK_COMBO_BOX (combo_box);
- model = gtk_combo_box_get_model (gtk_combo_box);
-
- /* Constructor properties trigger this function before the
- * list store is configured. Detect it and return silently. */
- if (model == NULL)
- return;
-
- /* Remember the active ID so we can try to restore it. */
- active_id = gtk_combo_box_get_active_id (gtk_combo_box);
-
- gtk_list_store_clear (GTK_LIST_STORE (model));
-
- /* If we have no registry, leave the combo box empty. */
- if (registry == NULL)
- return;
-
- /* If we have no extension name, leave the combo box empty. */
- if (extension_name == NULL)
- return;
-
- root = e_source_registry_build_display_tree (registry, extension_name);
-
- g_node_traverse (
- root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) source_combo_box_traverse,
- combo_box);
-
- e_source_registry_free_display_tree (root);
-
- /* Restore the active ID, or else set it to something reasonable. */
- gtk_combo_box_set_active_id (gtk_combo_box, active_id);
- if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL) {
- ESource *source;
-
- source = e_source_registry_ref_default_for_extension_name (
- registry, extension_name);
- if (source != NULL) {
- e_source_combo_box_set_active (combo_box, source);
- g_object_unref (source);
- }
- }
-}
-
-static void
-source_combo_box_source_added_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceComboBox *combo_box)
-{
- source_combo_box_build_model (combo_box);
-}
-
-static void
-source_combo_box_source_removed_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceComboBox *combo_box)
-{
- source_combo_box_build_model (combo_box);
-}
-
-static void
-source_combo_box_source_enabled_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceComboBox *combo_box)
-{
- source_combo_box_build_model (combo_box);
-}
-
-static void
-source_combo_box_source_disabled_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceComboBox *combo_box)
-{
- source_combo_box_build_model (combo_box);
-}
-
-static void
-source_combo_box_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_EXTENSION_NAME:
- e_source_combo_box_set_extension_name (
- E_SOURCE_COMBO_BOX (object),
- g_value_get_string (value));
- return;
-
- case PROP_REGISTRY:
- e_source_combo_box_set_registry (
- E_SOURCE_COMBO_BOX (object),
- g_value_get_object (value));
- return;
-
- case PROP_SHOW_COLORS:
- e_source_combo_box_set_show_colors (
- E_SOURCE_COMBO_BOX (object),
- g_value_get_boolean (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_combo_box_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_EXTENSION_NAME:
- g_value_set_string (
- value,
- e_source_combo_box_get_extension_name (
- E_SOURCE_COMBO_BOX (object)));
- return;
-
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_source_combo_box_get_registry (
- E_SOURCE_COMBO_BOX (object)));
- return;
-
- case PROP_SHOW_COLORS:
- g_value_set_boolean (
- value,
- e_source_combo_box_get_show_colors (
- E_SOURCE_COMBO_BOX (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_combo_box_dispose (GObject *object)
-{
- ESourceComboBoxPrivate *priv;
-
- priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
-
- if (priv->registry != NULL) {
- g_signal_handler_disconnect (
- priv->registry,
- priv->source_added_handler_id);
- g_signal_handler_disconnect (
- priv->registry,
- priv->source_removed_handler_id);
- g_signal_handler_disconnect (
- priv->registry,
- priv->source_enabled_handler_id);
- g_signal_handler_disconnect (
- priv->registry,
- priv->source_disabled_handler_id);
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- /* Chain up to parent's "dispose" method. */
- G_OBJECT_CLASS (e_source_combo_box_parent_class)->dispose (object);
-}
-
-static void
-source_combo_box_finalize (GObject *object)
-{
- ESourceComboBoxPrivate *priv;
-
- priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object);
-
- g_free (priv->extension_name);
-
- /* Chain up to parent's "finalize" method. */
- G_OBJECT_CLASS (e_source_combo_box_parent_class)->finalize (object);
-}
-
-static void
-source_combo_box_constructed (GObject *object)
-{
- ESourceComboBox *combo_box;
- GtkCellRenderer *renderer;
- GtkCellLayout *layout;
- GtkListStore *store;
-
- combo_box = E_SOURCE_COMBO_BOX (object);
-
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_source_combo_box_parent_class)->constructed (object);
-
- store = gtk_list_store_new (
- NUM_COLUMNS,
- GDK_TYPE_COLOR, /* COLUMN_COLOR */
- G_TYPE_STRING, /* COLUMN_NAME */
- G_TYPE_BOOLEAN, /* COLUMN_SENSITIVE */
- G_TYPE_STRING); /* COLUMN_UID */
- gtk_combo_box_set_model (
- GTK_COMBO_BOX (combo_box),
- GTK_TREE_MODEL (store));
- g_object_unref (store);
-
- gtk_combo_box_set_id_column (GTK_COMBO_BOX (combo_box), COLUMN_UID);
-
- layout = GTK_CELL_LAYOUT (combo_box);
-
- renderer = e_cell_renderer_color_new ();
- gtk_cell_layout_pack_start (layout, renderer, FALSE);
- gtk_cell_layout_set_attributes (
- layout, renderer,
- "color", COLUMN_COLOR,
- "sensitive", COLUMN_SENSITIVE,
- NULL);
-
- g_object_bind_property (
- combo_box, "show-colors",
- renderer, "visible",
- G_BINDING_SYNC_CREATE);
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (layout, renderer, TRUE);
- gtk_cell_layout_set_attributes (
- layout, renderer,
- "text", COLUMN_NAME,
- "sensitive", COLUMN_SENSITIVE,
- NULL);
-
- source_combo_box_build_model (combo_box);
-}
-
-static void
-e_source_combo_box_class_init (ESourceComboBoxClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- g_type_class_add_private (class, sizeof (ESourceComboBoxPrivate));
-
- object_class->set_property = source_combo_box_set_property;
- object_class->get_property = source_combo_box_get_property;
- object_class->dispose = source_combo_box_dispose;
- object_class->finalize = source_combo_box_finalize;
- object_class->constructed = source_combo_box_constructed;
-
- g_object_class_install_property (
- object_class,
- PROP_EXTENSION_NAME,
- g_param_spec_string (
- "extension-name",
- "Extension Name",
- "ESource extension name to filter",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT));
-
- /* XXX Don't use G_PARAM_CONSTRUCT_ONLY here. We need to allow
- * for this class to be instantiated by a GtkBuilder with no
- * special construct parameters, and then subsequently give
- * it an ESourceRegistry. */
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- "Registry",
- "Data source registry",
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_COLORS,
- g_param_spec_boolean (
- "show-colors",
- "Show Colors",
- "Whether to show colors next to names",
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_STRINGS));
-}
-
-static void
-e_source_combo_box_init (ESourceComboBox *combo_box)
-{
- combo_box->priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (combo_box);
-
-}
-
-/**
- * e_source_combo_box_new:
- * @registry: an #ESourceRegistry, or %NULL
- * @extension_name: an #ESource extension name
- *
- * Creates a new #ESourceComboBox widget that lets the user pick an #ESource
- * from the provided #ESourceRegistry. The displayed sources are restricted
- * to those which have an @extension_name extension.
- *
- * Returns: a new #ESourceComboBox
- *
- * Since: 2.22
- **/
-GtkWidget *
-e_source_combo_box_new (ESourceRegistry *registry,
- const gchar *extension_name)
-{
- if (registry != NULL)
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
-
- return g_object_new (
- E_TYPE_SOURCE_COMBO_BOX, "registry", registry,
- "extension-name", extension_name, NULL);
-}
-
-/**
- * e_source_combo_box_get_registry:
- * @combo_box: an #ESourceComboBox
- *
- * Returns the #ESourceRegistry used to populate @combo_box.
- *
- * Returns: the #ESourceRegistry, or %NULL
- *
- * Since: 3.6
- **/
-ESourceRegistry *
-e_source_combo_box_get_registry (ESourceComboBox *combo_box)
-{
- g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL);
-
- return combo_box->priv->registry;
-}
-
-/**
- * e_source_combo_box_set_registry:
- * @combo_box: an #ESourceComboBox
- * @registry: an #ESourceRegistry
- *
- * Sets the #ESourceRegistry used to populate @combo_box.
- *
- * This function is intended for cases where @combo_box is instantiated
- * by a #GtkBuilder and has to be given an #ESourceRegistry after it is
- * fully constructed.
- *
- * Since: 3.6
- **/
-void
-e_source_combo_box_set_registry (ESourceComboBox *combo_box,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
-
- if (combo_box->priv->registry == registry)
- return;
-
- if (registry != NULL) {
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_object_ref (registry);
- }
-
- if (combo_box->priv->registry != NULL) {
- g_signal_handler_disconnect (
- combo_box->priv->registry,
- combo_box->priv->source_added_handler_id);
- g_signal_handler_disconnect (
- combo_box->priv->registry,
- combo_box->priv->source_removed_handler_id);
- g_signal_handler_disconnect (
- combo_box->priv->registry,
- combo_box->priv->source_enabled_handler_id);
- g_signal_handler_disconnect (
- combo_box->priv->registry,
- combo_box->priv->source_disabled_handler_id);
- g_object_unref (combo_box->priv->registry);
- }
-
- combo_box->priv->registry = registry;
-
- combo_box->priv->source_added_handler_id = 0;
- combo_box->priv->source_removed_handler_id = 0;
- combo_box->priv->source_enabled_handler_id = 0;
- combo_box->priv->source_disabled_handler_id = 0;
-
- if (registry != NULL) {
- gulong handler_id;
-
- handler_id = g_signal_connect (
- registry, "source-added",
- G_CALLBACK (source_combo_box_source_added_cb),
- combo_box);
- combo_box->priv->source_added_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- registry, "source-removed",
- G_CALLBACK (source_combo_box_source_removed_cb),
- combo_box);
- combo_box->priv->source_removed_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- registry, "source-enabled",
- G_CALLBACK (source_combo_box_source_enabled_cb),
- combo_box);
- combo_box->priv->source_enabled_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- registry, "source-disabled",
- G_CALLBACK (source_combo_box_source_disabled_cb),
- combo_box);
- combo_box->priv->source_disabled_handler_id = handler_id;
- }
-
- source_combo_box_build_model (combo_box);
-
- g_object_notify (G_OBJECT (combo_box), "registry");
-}
-
-/**
- * e_source_combo_box_get_extension_name:
- * @combo_box: an #ESourceComboBox
- *
- * Returns the extension name used to filter which data sources are
- * shown in @combo_box.
- *
- * Returns: the #ESource extension name
- *
- * Since: 3.6
- **/
-const gchar *
-e_source_combo_box_get_extension_name (ESourceComboBox *combo_box)
-{
- g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL);
-
- return combo_box->priv->extension_name;
-}
-
-/**
- * e_source_combo_box_set_extension_name:
- * @combo_box: an #ESourceComboBox
- * @extension_name: an #ESource extension name
- *
- * Sets the extension name used to filter which data sources are shown in
- * @combo_box.
- *
- * Since: 3.6
- **/
-void
-e_source_combo_box_set_extension_name (ESourceComboBox *combo_box,
- const gchar *extension_name)
-{
- g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
-
- if (g_strcmp0 (combo_box->priv->extension_name, extension_name) == 0)
- return;
-
- g_free (combo_box->priv->extension_name);
- combo_box->priv->extension_name = g_strdup (extension_name);
-
- source_combo_box_build_model (combo_box);
-
- g_object_notify (G_OBJECT (combo_box), "extension-name");
-}
-
-/**
- * e_source_combo_box_get_show_colors:
- * @combo_box: an #ESourceComboBox
- *
- * Returns whether colors are shown next to data sources.
- *
- * Returns: %TRUE if colors are being shown
- *
- * Since: 3.6
- **/
-gboolean
-e_source_combo_box_get_show_colors (ESourceComboBox *combo_box)
-{
- g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), FALSE);
-
- return combo_box->priv->show_colors;
-}
-
-/**
- * e_source_combo_box_set_show_colors:
- * @combo_box: an #ESourceComboBox
- * @show_colors: whether to show colors
- *
- * Sets whether to show colors next to data sources.
- *
- * Since: 3.6
- **/
-void
-e_source_combo_box_set_show_colors (ESourceComboBox *combo_box,
- gboolean show_colors)
-{
- g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
-
- if ((show_colors ? 1 : 0) == (combo_box->priv->show_colors ? 1 : 0))
- return;
-
- combo_box->priv->show_colors = show_colors;
-
- source_combo_box_build_model (combo_box);
-
- g_object_notify (G_OBJECT (combo_box), "show-colors");
-}
-
-/**
- * e_source_combo_box_ref_active:
- * @combo_box: an #ESourceComboBox
- *
- * Returns the #ESource corresponding to the currently active item,
- * or %NULL if there is no active item.
- *
- * The returned #ESource is referenced for thread-safety and must be
- * unreferenced with g_object_unref() when finished with it.
- *
- * Returns: an #ESource or %NULL
- *
- * Since: 3.6
- **/
-ESource *
-e_source_combo_box_ref_active (ESourceComboBox *combo_box)
-{
- ESourceRegistry *registry;
- GtkComboBox *gtk_combo_box;
- const gchar *active_id;
-
- g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL);
-
- registry = e_source_combo_box_get_registry (combo_box);
-
- gtk_combo_box = GTK_COMBO_BOX (combo_box);
- active_id = gtk_combo_box_get_active_id (gtk_combo_box);
-
- if (active_id == NULL)
- return NULL;
-
- return e_source_registry_ref_source (registry, active_id);
-}
-
-/**
- * e_source_combo_box_set_active:
- * @combo_box: an #ESourceComboBox
- * @source: an #ESource
- *
- * Sets the active item to the one corresponding to @source.
- *
- * Since: 2.22
- **/
-void
-e_source_combo_box_set_active (ESourceComboBox *combo_box,
- ESource *source)
-{
- GtkComboBox *gtk_combo_box;
- const gchar *uid;
-
- g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box));
- g_return_if_fail (E_IS_SOURCE (source));
-
- uid = e_source_get_uid (source);
-
- gtk_combo_box = GTK_COMBO_BOX (combo_box);
- gtk_combo_box_set_active_id (gtk_combo_box, uid);
-}
-
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source-combo-box.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 Lesser 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 Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_SOURCE_COMBO_BOX_H
-#define E_SOURCE_COMBO_BOX_H
-
-#include <gtk/gtk.h>
-#include <libedataserver/libedataserver.h>
-
-#define E_TYPE_SOURCE_COMBO_BOX \
- (e_source_combo_box_get_type ())
-#define E_SOURCE_COMBO_BOX(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBox))
-#define E_SOURCE_COMBO_BOX_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBoxClass))
-#define E_IS_SOURCE_COMBO_BOX(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SOURCE_COMBO_BOX))
-#define E_IS_SOURCE_COMBO_BOX_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE ((cls), E_TYPE_SOURCE_COMBO_BOX))
-#define E_SOURCE_COMBO_BOX_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBox))
-
-G_BEGIN_DECLS
-
-typedef struct _ESourceComboBox ESourceComboBox;
-typedef struct _ESourceComboBoxClass ESourceComboBoxClass;
-typedef struct _ESourceComboBoxPrivate ESourceComboBoxPrivate;
-
-/**
- * ESourceComboBox:
- *
- * Since: 2.22
- **/
-struct _ESourceComboBox {
- GtkComboBox parent;
- ESourceComboBoxPrivate *priv;
-};
-
-struct _ESourceComboBoxClass {
- GtkComboBoxClass parent_class;
-};
-
-GType e_source_combo_box_get_type (void);
-GtkWidget * e_source_combo_box_new (ESourceRegistry *registry,
- const gchar *extension_name);
-ESourceRegistry *
- e_source_combo_box_get_registry (ESourceComboBox *combo_box);
-void e_source_combo_box_set_registry (ESourceComboBox *combo_box,
- ESourceRegistry *registry);
-const gchar * e_source_combo_box_get_extension_name
- (ESourceComboBox *combo_box);
-void e_source_combo_box_set_extension_name
- (ESourceComboBox *combo_box,
- const gchar *extension_name);
-gboolean e_source_combo_box_get_show_colors
- (ESourceComboBox *combo_box);
-void e_source_combo_box_set_show_colors
- (ESourceComboBox *combo_box,
- gboolean show_colors);
-ESource * e_source_combo_box_ref_active (ESourceComboBox *combo_box);
-void e_source_combo_box_set_active (ESourceComboBox *combo_box,
- ESource *source);
-
-G_END_DECLS
-
-#endif /* E_SOURCE_COMBO_BOX_H */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source-selector-dialog.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 the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Author: Rodrigo Moya <rodrigo@novell.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-#include "e-source-selector.h"
-#include "e-source-selector-dialog.h"
-
-#define E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_SOURCE_SELECTOR_DIALOG, ESourceSelectorDialogPrivate))
-
-struct _ESourceSelectorDialogPrivate {
- GtkWidget *selector;
- ESourceRegistry *registry;
- ESource *selected_source;
- gchar *extension_name;
-};
-
-enum {
- PROP_0,
- PROP_EXTENSION_NAME,
- PROP_REGISTRY,
- PROP_SELECTOR
-};
-
-G_DEFINE_TYPE (
- ESourceSelectorDialog,
- e_source_selector_dialog,
- GTK_TYPE_DIALOG)
-
-static void
-source_selector_dialog_row_activated_cb (GtkTreeView *tree_view,
- GtkTreePath *path,
- GtkTreeViewColumn *column,
- GtkWidget *dialog)
-{
- gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-}
-
-static void
-primary_selection_changed_cb (ESourceSelector *selector,
- ESourceSelectorDialog *dialog)
-{
- ESourceSelectorDialogPrivate *priv = dialog->priv;
-
- if (priv->selected_source != NULL)
- g_object_unref (priv->selected_source);
- priv->selected_source =
- e_source_selector_ref_primary_selection (selector);
-
- /* FIXME Add an API for "except-source" or to
- * get the ESourceSelector from outside. */
- if (priv->selected_source != NULL) {
- ESource *except_source;
-
- except_source = g_object_get_data (
- G_OBJECT (dialog), "except-source");
-
- if (except_source != NULL)
- if (e_source_equal (except_source, priv->selected_source)) {
- g_object_unref (priv->selected_source);
- priv->selected_source = NULL;
- }
- }
-
- gtk_dialog_set_response_sensitive (
- GTK_DIALOG (dialog), GTK_RESPONSE_OK,
- (priv->selected_source != NULL));
-}
-
-static void
-source_selector_dialog_set_extension_name (ESourceSelectorDialog *dialog,
- const gchar *extension_name)
-{
- g_return_if_fail (extension_name != NULL);
- g_return_if_fail (dialog->priv->extension_name == NULL);
-
- dialog->priv->extension_name = g_strdup (extension_name);
-}
-
-static void
-source_selector_dialog_set_registry (ESourceSelectorDialog *dialog,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_return_if_fail (dialog->priv->registry == NULL);
-
- dialog->priv->registry = g_object_ref (registry);
-}
-
-static void
-source_selector_dialog_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_EXTENSION_NAME:
- source_selector_dialog_set_extension_name (
- E_SOURCE_SELECTOR_DIALOG (object),
- g_value_get_string (value));
- return;
-
- case PROP_REGISTRY:
- source_selector_dialog_set_registry (
- E_SOURCE_SELECTOR_DIALOG (object),
- g_value_get_object (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_selector_dialog_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_EXTENSION_NAME:
- g_value_set_string (
- value,
- e_source_selector_dialog_get_extension_name (
- E_SOURCE_SELECTOR_DIALOG (object)));
- return;
-
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_source_selector_dialog_get_registry (
- E_SOURCE_SELECTOR_DIALOG (object)));
- return;
-
- case PROP_SELECTOR:
- g_value_set_object (
- value,
- e_source_selector_dialog_get_selector (
- E_SOURCE_SELECTOR_DIALOG (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_selector_dialog_dispose (GObject *object)
-{
- ESourceSelectorDialogPrivate *priv;
-
- priv = E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE (object);
-
- if (priv->registry != NULL) {
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- if (priv->selected_source != NULL) {
- g_object_unref (priv->selected_source);
- priv->selected_source = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_source_selector_dialog_parent_class)->dispose (object);
-}
-
-static void
-source_selector_dialog_finalize (GObject *object)
-{
- ESourceSelectorDialogPrivate *priv;
-
- priv = E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE (object);
-
- g_free (priv->extension_name);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_source_selector_dialog_parent_class)->finalize (object);
-}
-
-static void
-source_selector_dialog_constructed (GObject *object)
-{
- ESourceSelectorDialog *dialog;
- GtkWidget *label, *hgrid;
- GtkWidget *container;
- GtkWidget *widget;
- gchar *label_text;
-
- dialog = E_SOURCE_SELECTOR_DIALOG (object);
-
- container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-
- widget = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", FALSE,
- "row-spacing", 12,
- NULL);
- gtk_container_set_border_width (GTK_CONTAINER (widget), 12);
- gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
- gtk_widget_show (widget);
-
- container = widget;
-
- label_text = g_strdup_printf ("<b>%s</b>", _("_Destination"));
- label = gtk_label_new_with_mnemonic (label_text);
- gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
- gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
- gtk_container_add (GTK_CONTAINER (container), label);
- gtk_widget_show (label);
- g_free (label_text);
-
- hgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_HORIZONTAL,
- "row-homogeneous", FALSE,
- "column-spacing", 12,
- "vexpand", TRUE,
- "valign", GTK_ALIGN_FILL,
- NULL);
- gtk_container_add (GTK_CONTAINER (container), hgrid);
- gtk_widget_show (hgrid);
-
- widget = gtk_label_new ("");
- gtk_container_add (GTK_CONTAINER (hgrid), widget);
- gtk_widget_show (widget);
-
- widget = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
- gtk_widget_set_hexpand (widget, TRUE);
- gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
- gtk_widget_set_vexpand (widget, TRUE);
- gtk_widget_set_valign (widget, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (hgrid), widget);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = e_source_selector_new (
- dialog->priv->registry,
- dialog->priv->extension_name);
- e_source_selector_set_show_toggles (E_SOURCE_SELECTOR (widget), FALSE);
- gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
- gtk_container_add (GTK_CONTAINER (container), widget);
- dialog->priv->selector = widget;
- gtk_widget_show (widget);
-
- g_signal_connect (
- widget, "row_activated",
- G_CALLBACK (source_selector_dialog_row_activated_cb), dialog);
- g_signal_connect (
- widget, "primary_selection_changed",
- G_CALLBACK (primary_selection_changed_cb), dialog);
-}
-
-static void
-e_source_selector_dialog_class_init (ESourceSelectorDialogClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ESourceSelectorDialogPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = source_selector_dialog_set_property;
- object_class->get_property = source_selector_dialog_get_property;
- object_class->dispose = source_selector_dialog_dispose;
- object_class->finalize = source_selector_dialog_finalize;
- object_class->constructed = source_selector_dialog_constructed;
-
- g_object_class_install_property (
- object_class,
- PROP_EXTENSION_NAME,
- g_param_spec_string (
- "extension-name",
- NULL,
- NULL,
- NULL,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- NULL,
- NULL,
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (
- object_class,
- PROP_SELECTOR,
- g_param_spec_object (
- "selector",
- NULL,
- NULL,
- E_TYPE_SOURCE_SELECTOR,
- G_PARAM_READABLE));
-}
-
-static void
-e_source_selector_dialog_init (ESourceSelectorDialog *dialog)
-{
- GtkWidget *action_area;
- GtkWidget *content_area;
-
- dialog->priv = E_SOURCE_SELECTOR_DIALOG_GET_PRIVATE (dialog);
-
- action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
- content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
-
- gtk_window_set_title (GTK_WINDOW (dialog), _("Select destination"));
- gtk_window_set_default_size (GTK_WINDOW (dialog), 320, 240);
-
- gtk_widget_ensure_style (GTK_WIDGET (dialog));
- gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
- gtk_container_set_border_width (GTK_CONTAINER (action_area), 12);
-
- gtk_dialog_add_buttons (
- GTK_DIALOG (dialog),
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
- gtk_dialog_set_default_response (
- GTK_DIALOG (dialog), GTK_RESPONSE_OK);
- gtk_dialog_set_response_sensitive (
- GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
-}
-
-/**
- * e_source_selector_dialog_new:
- * @parent: a parent window
- * @registry: an #ESourceRegistry
- * @extension_name: the name of an #ESource extension
- *
- * Displays a list of sources from @registry having an extension named
- * @extension_name in a dialog window. The sources are grouped by backend
- * or groupware account, which are described by the parent source.
- *
- * Returns: a new #ESourceSelectorDialog
- **/
-GtkWidget *
-e_source_selector_dialog_new (GtkWindow *parent,
- ESourceRegistry *registry,
- const gchar *extension_name)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
- g_return_val_if_fail (extension_name != NULL, NULL);
-
- return g_object_new (
- E_TYPE_SOURCE_SELECTOR_DIALOG,
- "transient-for", parent,
- "registry", registry,
- "extension-name", extension_name,
- NULL);
-}
-
-/**
- * e_source_selector_dialog_get_registry:
- * @dialog: an #ESourceSelectorDialog
- *
- * Returns the #ESourceRegistry passed to e_source_selector_dialog_new().
- *
- * Returns: the #ESourceRegistry for @dialog
- *
- * Since: 3.6
- **/
-ESourceRegistry *
-e_source_selector_dialog_get_registry (ESourceSelectorDialog *dialog)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
-
- return dialog->priv->registry;
-}
-
-/**
- * e_source_selector_dialog_get_extension_name:
- * @dialog: an #ESourceSelectorDialog
- *
- * Returns the extension name passed to e_source_selector_dialog_new().
- *
- * Returns: the extension name for @dialog
- *
- * Since: 3.6
- **/
-const gchar *
-e_source_selector_dialog_get_extension_name (ESourceSelectorDialog *dialog)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
-
- return dialog->priv->extension_name;
-}
-
-/**
- * e_source_selector_dialog_get_selector:
- * @dialog: an #ESourceSelectorDialog
- *
- * Returns the #ESourceSelector widget embedded in @dialog.
- *
- * Returns: the #ESourceSelector widget
- *
- * Since: 3.6
- **/
-ESourceSelector *
-e_source_selector_dialog_get_selector (ESourceSelectorDialog *dialog)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
-
- return E_SOURCE_SELECTOR (dialog->priv->selector);
-}
-
-/**
- * e_source_selector_dialog_peek_primary_selection:
- * @dialog: an #ESourceSelectorDialog
- *
- * Peek the currently selected source in the given @dialog.
- *
- * Returns: the selected #ESource
- */
-ESource *
-e_source_selector_dialog_peek_primary_selection (ESourceSelectorDialog *dialog)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR_DIALOG (dialog), NULL);
-
- return dialog->priv->selected_source;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source-selector-dialog.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 the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Author: Rodrigo Moya <rodrigo@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_SOURCE_SELECTOR_DIALOG_H
-#define E_SOURCE_SELECTOR_DIALOG_H
-
-#include <gtk/gtk.h>
-#include <libedataserverui/e-source-selector.h>
-
-/* Standard GObject macros */
-#define E_TYPE_SOURCE_SELECTOR_DIALOG \
- (e_source_selector_dialog_get_type ())
-#define E_SOURCE_SELECTOR_DIALOG(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_SOURCE_SELECTOR_DIALOG, ESourceSelectorDialog))
-#define E_SOURCE_SELECTOR_DIALOG_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_SOURCE_SELECTOR_DIALOG, ESourceSelectorDialogClass))
-#define E_IS_SOURCE_SELECTOR_DIALOG(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_SOURCE_SELECTOR_DIALOG))
-#define E_IS_SOURCE_SELECTOR_DIALOG_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_SOURCE_SELECTOR_DIALOG))
-#define E_SOURCE_SELECTOR_DIALOG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_SOURCE_SELECTOR_DIALOG, ESourceSelectorDialogClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ESourceSelectorDialog ESourceSelectorDialog;
-typedef struct _ESourceSelectorDialogClass ESourceSelectorDialogClass;
-typedef struct _ESourceSelectorDialogPrivate ESourceSelectorDialogPrivate;
-
-struct _ESourceSelectorDialog {
- GtkDialog parent;
- ESourceSelectorDialogPrivate *priv;
-};
-
-struct _ESourceSelectorDialogClass {
- GtkDialogClass parent_class;
-};
-
-GType e_source_selector_dialog_get_type (void);
-GtkWidget * e_source_selector_dialog_new (GtkWindow *parent,
- ESourceRegistry *registry,
- const gchar *extension_name);
-ESourceRegistry *
- e_source_selector_dialog_get_registry
- (ESourceSelectorDialog *dialog);
-const gchar * e_source_selector_dialog_get_extension_name
- (ESourceSelectorDialog *dialog);
-ESourceSelector *
- e_source_selector_dialog_get_selector
- (ESourceSelectorDialog *dialog);
-ESource * e_source_selector_dialog_peek_primary_selection
- (ESourceSelectorDialog *dialog);
-
-G_END_DECLS
-
-#endif /* E_SOURCE_SELECTOR_DIALOG_H */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source-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 the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Author: Ettore Perazzoli <ettore@ximian.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include "e-cell-renderer-color.h"
-#include "e-data-server-ui-marshal.h"
-#include "e-source-selector.h"
-
-#define E_SOURCE_SELECTOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_SOURCE_SELECTOR, ESourceSelectorPrivate))
-
-typedef struct _AsyncContext AsyncContext;
-
-struct _ESourceSelectorPrivate {
- ESourceRegistry *registry;
- GHashTable *source_index;
- gchar *extension_name;
-
- GtkTreeRowReference *saved_primary_selection;
-
- /* ESource -> GSource */
- GHashTable *pending_writes;
- GMainContext *main_context;
-
- gboolean toggled_last;
- gboolean select_new;
- gboolean show_colors;
- gboolean show_toggles;
-};
-
-struct _AsyncContext {
- ESourceSelector *selector;
- ESource *source;
-};
-
-enum {
- PROP_0,
- PROP_EXTENSION_NAME,
- PROP_PRIMARY_SELECTION,
- PROP_REGISTRY,
- PROP_SHOW_COLORS,
- PROP_SHOW_TOGGLES
-};
-
-enum {
- SELECTION_CHANGED,
- PRIMARY_SELECTION_CHANGED,
- POPUP_EVENT,
- DATA_DROPPED,
- NUM_SIGNALS
-};
-
-enum {
- COLUMN_NAME,
- COLUMN_COLOR,
- COLUMN_ACTIVE,
- COLUMN_SHOW_COLOR,
- COLUMN_SHOW_TOGGLE,
- COLUMN_WEIGHT,
- COLUMN_SOURCE,
- NUM_COLUMNS
-};
-
-static guint signals[NUM_SIGNALS];
-
-G_DEFINE_TYPE (ESourceSelector, e_source_selector, GTK_TYPE_TREE_VIEW)
-
-/* ESafeToggleRenderer does not emit 'toggled' signal
- * on 'activate' when mouse is not over the toggle. */
-
-typedef GtkCellRendererToggle ECellRendererSafeToggle;
-typedef GtkCellRendererToggleClass ECellRendererSafeToggleClass;
-
-/* Forward Declarations */
-GType e_cell_renderer_safe_toggle_get_type (void);
-
-G_DEFINE_TYPE (
- ECellRendererSafeToggle,
- e_cell_renderer_safe_toggle,
- GTK_TYPE_CELL_RENDERER_TOGGLE)
-
-static gboolean
-safe_toggle_activate (GtkCellRenderer *cell,
- GdkEvent *event,
- GtkWidget *widget,
- const gchar *path,
- const GdkRectangle *background_area,
- const GdkRectangle *cell_area,
- GtkCellRendererState flags)
-{
- gboolean point_in_cell_area = TRUE;
-
- if (event->type == GDK_BUTTON_PRESS && cell_area != NULL) {
- cairo_region_t *region;
-
- region = cairo_region_create_rectangle (cell_area);
- point_in_cell_area = cairo_region_contains_point (
- region, event->button.x, event->button.y);
- cairo_region_destroy (region);
- }
-
- if (!point_in_cell_area)
- return FALSE;
-
- return GTK_CELL_RENDERER_CLASS (
- e_cell_renderer_safe_toggle_parent_class)->activate (
- cell, event, widget, path, background_area, cell_area, flags);
-}
-
-static void
-e_cell_renderer_safe_toggle_class_init (ECellRendererSafeToggleClass *class)
-{
- GtkCellRendererClass *cell_renderer_class;
-
- cell_renderer_class = GTK_CELL_RENDERER_CLASS (class);
- cell_renderer_class->activate = safe_toggle_activate;
-}
-
-static void
-e_cell_renderer_safe_toggle_init (ECellRendererSafeToggle *obj)
-{
-}
-
-static GtkCellRenderer *
-e_cell_renderer_safe_toggle_new (void)
-{
- return g_object_new (e_cell_renderer_safe_toggle_get_type (), NULL);
-}
-
-static void
-clear_saved_primary_selection (ESourceSelector *selector)
-{
- gtk_tree_row_reference_free (selector->priv->saved_primary_selection);
- selector->priv->saved_primary_selection = NULL;
-}
-
-static void
-async_context_free (AsyncContext *async_context)
-{
- if (async_context->selector != NULL)
- g_object_unref (async_context->selector);
-
- if (async_context->source != NULL)
- g_object_unref (async_context->source);
-
- g_slice_free (AsyncContext, async_context);
-}
-
-static void
-pending_writes_destroy_source (GSource *source)
-{
- g_source_destroy (source);
- g_source_unref (source);
-}
-
-static void
-source_selector_write_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- ESource *source;
- ESourceSelector *selector;
- GError *error = NULL;
-
- source = E_SOURCE (source_object);
- selector = E_SOURCE_SELECTOR (user_data);
-
- e_source_write_finish (source, result, &error);
-
- /* FIXME Display the error in the selector somehow? */
- if (error != NULL) {
- g_warning ("%s: %s", G_STRFUNC, error->message);
- g_error_free (error);
- }
-
- g_object_unref (selector);
-}
-
-static gboolean
-source_selector_write_idle_cb (gpointer user_data)
-{
- AsyncContext *async_context = user_data;
- GHashTable *pending_writes;
-
- /* XXX This operation is not cancellable. */
- e_source_write (
- async_context->source, NULL,
- source_selector_write_done_cb,
- g_object_ref (async_context->selector));
-
- pending_writes = async_context->selector->priv->pending_writes;
- g_hash_table_remove (pending_writes, async_context->source);
-
- return FALSE;
-}
-
-static void
-source_selector_cancel_write (ESourceSelector *selector,
- ESource *source)
-{
- GHashTable *pending_writes;
-
- /* Cancel any pending writes for this ESource so as not
- * to overwrite whatever change we're being notified of. */
- pending_writes = selector->priv->pending_writes;
- g_hash_table_remove (pending_writes, source);
-}
-
-static void
-source_selector_update_row (ESourceSelector *selector,
- ESource *source)
-{
- GHashTable *source_index;
- ESourceExtension *extension = NULL;
- GtkTreeRowReference *reference;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
- const gchar *extension_name;
- const gchar *display_name;
- gboolean selected;
-
- source_index = selector->priv->source_index;
- reference = g_hash_table_lookup (source_index, source);
-
- /* This function runs when ANY ESource in the registry changes.
- * If the ESource is not in our tree model then return silently. */
- if (reference == NULL)
- return;
-
- /* If we do have a row reference, it should be valid. */
- g_return_if_fail (gtk_tree_row_reference_valid (reference));
-
- model = gtk_tree_row_reference_get_model (reference);
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
-
- display_name = e_source_get_display_name (source);
-
- extension_name = e_source_selector_get_extension_name (selector);
- selected = e_source_selector_source_is_selected (selector, source);
-
- if (e_source_has_extension (source, extension_name))
- extension = e_source_get_extension (source, extension_name);
-
- if (extension != NULL) {
- GdkColor color;
- const gchar *color_spec = NULL;
- gboolean show_color = FALSE;
- gboolean show_toggle;
-
- show_color =
- E_IS_SOURCE_SELECTABLE (extension) &&
- e_source_selector_get_show_colors (selector);
-
- if (show_color)
- color_spec = e_source_selectable_get_color (
- E_SOURCE_SELECTABLE (extension));
-
- if (color_spec != NULL && *color_spec != '\0')
- show_color = gdk_color_parse (color_spec, &color);
-
- show_toggle = e_source_selector_get_show_toggles (selector);
-
- gtk_tree_store_set (
- GTK_TREE_STORE (model), &iter,
- COLUMN_NAME, display_name,
- COLUMN_COLOR, show_color ? &color : NULL,
- COLUMN_ACTIVE, selected,
- COLUMN_SHOW_COLOR, show_color,
- COLUMN_SHOW_TOGGLE, show_toggle,
- COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
- COLUMN_SOURCE, source,
- -1);
- } else {
- gtk_tree_store_set (
- GTK_TREE_STORE (model), &iter,
- COLUMN_NAME, display_name,
- COLUMN_COLOR, NULL,
- COLUMN_ACTIVE, FALSE,
- COLUMN_SHOW_COLOR, FALSE,
- COLUMN_SHOW_TOGGLE, FALSE,
- COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
- COLUMN_SOURCE, source,
- -1);
- }
-}
-
-static gboolean
-source_selector_traverse (GNode *node,
- ESourceSelector *selector)
-{
- ESource *source;
- GHashTable *source_index;
- GtkTreeRowReference *reference = NULL;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- /* Skip the root node. */
- if (G_NODE_IS_ROOT (node))
- return FALSE;
-
- source_index = selector->priv->source_index;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
-
- if (node->parent != NULL && node->parent->data != NULL)
- reference = g_hash_table_lookup (
- source_index, node->parent->data);
-
- if (gtk_tree_row_reference_valid (reference)) {
- GtkTreeIter parent;
-
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_model_get_iter (model, &parent, path);
- gtk_tree_path_free (path);
-
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent);
- } else
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
-
- source = E_SOURCE (node->data);
-
- path = gtk_tree_model_get_path (model, &iter);
- reference = gtk_tree_row_reference_new (model, path);
- g_hash_table_insert (source_index, g_object_ref (source), reference);
- gtk_tree_path_free (path);
-
- source_selector_update_row (selector, source);
-
- return FALSE;
-}
-
-static void
-source_selector_save_expanded (GtkTreeView *tree_view,
- GtkTreePath *path,
- GQueue *queue)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- ESource *source;
-
- model = gtk_tree_view_get_model (tree_view);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
- g_queue_push_tail (queue, source);
-}
-
-static void
-source_selector_build_model (ESourceSelector *selector)
-{
- ESourceRegistry *registry;
- GQueue queue = G_QUEUE_INIT;
- GHashTable *source_index;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- ESource *selected;
- const gchar *extension_name;
- GNode *root;
-
- tree_view = GTK_TREE_VIEW (selector);
-
- registry = e_source_selector_get_registry (selector);
- extension_name = e_source_selector_get_extension_name (selector);
-
- /* Make sure we have what we need to build the model, since
- * this can get called early in the initialization phase. */
- if (registry == NULL || extension_name == NULL)
- return;
-
- source_index = selector->priv->source_index;
- selected = e_source_selector_ref_primary_selection (selector);
-
- /* Save expanded sources to restore later. */
- gtk_tree_view_map_expanded_rows (
- tree_view, (GtkTreeViewMappingFunc)
- source_selector_save_expanded, &queue);
-
- model = gtk_tree_view_get_model (tree_view);
- gtk_tree_store_clear (GTK_TREE_STORE (model));
-
- g_hash_table_remove_all (source_index);
-
- root = e_source_registry_build_display_tree (registry, extension_name);
-
- g_node_traverse (
- root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) source_selector_traverse,
- selector);
-
- e_source_registry_free_display_tree (root);
-
- /* Restore previously expanded sources. */
- while (!g_queue_is_empty (&queue)) {
- GtkTreeRowReference *reference;
- ESource *source;
-
- source = g_queue_pop_head (&queue);
- reference = g_hash_table_lookup (source_index, source);
-
- if (gtk_tree_row_reference_valid (reference)) {
- GtkTreePath *path;
-
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_view_expand_to_path (tree_view, path);
- gtk_tree_path_free (path);
- }
-
- g_object_unref (source);
- }
-
- /* Restore the primary selection. */
- if (selected != NULL) {
- e_source_selector_set_primary_selection (selector, selected);
- g_object_unref (selected);
- }
-
- /* Make sure we have a primary selection. If not, pick one. */
- selected = e_source_selector_ref_primary_selection (selector);
- if (selected == NULL) {
- selected = e_source_registry_ref_default_for_extension_name (
- registry, extension_name);
- e_source_selector_set_primary_selection (selector, selected);
- }
- g_object_unref (selected);
-}
-
-static void
-source_selector_expand_to_source (ESourceSelector *selector,
- ESource *source)
-{
- GHashTable *source_index;
- GtkTreeRowReference *reference;
- GtkTreePath *path;
-
- source_index = selector->priv->source_index;
- reference = g_hash_table_lookup (source_index, source);
-
- /* If the ESource is not in our tree model then return silently. */
- if (reference == NULL)
- return;
-
- /* If we do have a row reference, it should be valid. */
- g_return_if_fail (gtk_tree_row_reference_valid (reference));
-
- /* Expand the tree view to the path containing the ESource */
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_view_expand_to_path (GTK_TREE_VIEW (selector), path);
- gtk_tree_path_free (path);
-}
-
-static void
-source_selector_source_added_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceSelector *selector)
-{
- source_selector_build_model (selector);
-
- source_selector_expand_to_source (selector, source);
-}
-
-static void
-source_selector_source_changed_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceSelector *selector)
-{
- source_selector_cancel_write (selector, source);
-
- source_selector_update_row (selector, source);
-}
-
-static void
-source_selector_source_removed_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceSelector *selector)
-{
- source_selector_build_model (selector);
-}
-
-static void
-source_selector_source_enabled_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceSelector *selector)
-{
- source_selector_build_model (selector);
-
- source_selector_expand_to_source (selector, source);
-}
-
-static void
-source_selector_source_disabled_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceSelector *selector)
-{
- source_selector_build_model (selector);
-}
-
-static gboolean
-same_source_name_exists (ESourceSelector *selector,
- const gchar *display_name)
-{
- GHashTable *source_index;
- GHashTableIter iter;
- gpointer key;
-
- source_index = selector->priv->source_index;
- g_hash_table_iter_init (&iter, source_index);
-
- while (g_hash_table_iter_next (&iter, &key, NULL)) {
- ESource *source = E_SOURCE (key);
- const gchar *source_name;
-
- source_name = e_source_get_display_name (source);
- if (g_strcmp0 (display_name, source_name) == 0)
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-selection_func (GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currently_selected,
- ESourceSelector *selector)
-{
- ESource *source;
- GtkTreeIter iter;
- const gchar *extension_name;
-
- if (selector->priv->toggled_last) {
- selector->priv->toggled_last = FALSE;
- return FALSE;
- }
-
- if (path_currently_selected)
- return TRUE;
-
- if (!gtk_tree_model_get_iter (model, &iter, path))
- return FALSE;
-
- extension_name = e_source_selector_get_extension_name (selector);
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- if (!e_source_has_extension (source, extension_name)) {
- g_object_unref (source);
- return FALSE;
- }
-
- clear_saved_primary_selection (selector);
-
- g_object_unref (source);
-
- return TRUE;
-}
-
-static void
-text_cell_edited_cb (ESourceSelector *selector,
- const gchar *path_string,
- const gchar *new_name)
-{
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
- ESource *source;
-
- tree_view = GTK_TREE_VIEW (selector);
- model = gtk_tree_view_get_model (tree_view);
- path = gtk_tree_path_new_from_string (path_string);
-
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
- gtk_tree_path_free (path);
-
- if (new_name == NULL || *new_name == '\0')
- return;
-
- if (same_source_name_exists (selector, new_name))
- return;
-
- e_source_set_display_name (source, new_name);
-
- e_source_selector_queue_write (selector, source);
-}
-
-static void
-cell_toggled_callback (GtkCellRendererToggle *renderer,
- const gchar *path_string,
- ESourceSelector *selector)
-{
- ESource *source;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
- path = gtk_tree_path_new_from_string (path_string);
-
- if (!gtk_tree_model_get_iter (model, &iter, path)) {
- gtk_tree_path_free (path);
- return;
- }
-
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- if (e_source_selector_source_is_selected (selector, source))
- e_source_selector_unselect_source (selector, source);
- else
- e_source_selector_select_source (selector, source);
-
- selector->priv->toggled_last = TRUE;
-
- gtk_tree_path_free (path);
-
- g_object_unref (source);
-}
-
-static void
-selection_changed_callback (GtkTreeSelection *selection,
- ESourceSelector *selector)
-{
- g_signal_emit (selector, signals[PRIMARY_SELECTION_CHANGED], 0);
- g_object_notify (G_OBJECT (selector), "primary-selection");
-}
-
-static void
-source_selector_set_extension_name (ESourceSelector *selector,
- const gchar *extension_name)
-{
- g_return_if_fail (extension_name != NULL);
- g_return_if_fail (selector->priv->extension_name == NULL);
-
- selector->priv->extension_name = g_strdup (extension_name);
-}
-
-static void
-source_selector_set_registry (ESourceSelector *selector,
- ESourceRegistry *registry)
-{
- g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
- g_return_if_fail (selector->priv->registry == NULL);
-
- selector->priv->registry = g_object_ref (registry);
-}
-
-static void
-source_selector_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_EXTENSION_NAME:
- source_selector_set_extension_name (
- E_SOURCE_SELECTOR (object),
- g_value_get_string (value));
- return;
-
- case PROP_PRIMARY_SELECTION:
- e_source_selector_set_primary_selection (
- E_SOURCE_SELECTOR (object),
- g_value_get_object (value));
- return;
-
- case PROP_REGISTRY:
- source_selector_set_registry (
- E_SOURCE_SELECTOR (object),
- g_value_get_object (value));
- return;
-
- case PROP_SHOW_COLORS:
- e_source_selector_set_show_colors (
- E_SOURCE_SELECTOR (object),
- g_value_get_boolean (value));
- return;
-
- case PROP_SHOW_TOGGLES:
- e_source_selector_set_show_toggles (
- E_SOURCE_SELECTOR (object),
- g_value_get_boolean (value));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_selector_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_EXTENSION_NAME:
- g_value_set_string (
- value,
- e_source_selector_get_extension_name (
- E_SOURCE_SELECTOR (object)));
- return;
-
- case PROP_PRIMARY_SELECTION:
- g_value_take_object (
- value,
- e_source_selector_ref_primary_selection (
- E_SOURCE_SELECTOR (object)));
- return;
-
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_source_selector_get_registry (
- E_SOURCE_SELECTOR (object)));
- return;
-
- case PROP_SHOW_COLORS:
- g_value_set_boolean (
- value,
- e_source_selector_get_show_colors (
- E_SOURCE_SELECTOR (object)));
- return;
-
- case PROP_SHOW_TOGGLES:
- g_value_set_boolean (
- value,
- e_source_selector_get_show_toggles (
- E_SOURCE_SELECTOR (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_selector_dispose (GObject *object)
-{
- ESourceSelectorPrivate *priv;
-
- priv = E_SOURCE_SELECTOR_GET_PRIVATE (object);
-
- if (priv->registry != NULL) {
- g_signal_handlers_disconnect_matched (
- priv->registry,
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, object);
- g_object_unref (priv->registry);
- priv->registry = NULL;
- }
-
- g_hash_table_remove_all (priv->source_index);
- g_hash_table_remove_all (priv->pending_writes);
-
- clear_saved_primary_selection (E_SOURCE_SELECTOR (object));
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_source_selector_parent_class)->dispose (object);
-}
-
-static void
-source_selector_finalize (GObject *object)
-{
- ESourceSelectorPrivate *priv;
-
- priv = E_SOURCE_SELECTOR_GET_PRIVATE (object);
-
- g_hash_table_destroy (priv->source_index);
- g_hash_table_destroy (priv->pending_writes);
-
- g_free (priv->extension_name);
-
- if (priv->main_context != NULL)
- g_main_context_unref (priv->main_context);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_source_selector_parent_class)->finalize (object);
-}
-
-static void
-source_selector_constructed (GObject *object)
-{
- ESourceRegistry *registry;
- ESourceSelector *selector;
-
- selector = E_SOURCE_SELECTOR (object);
- registry = e_source_selector_get_registry (selector);
-
- g_signal_connect (
- registry, "source-added",
- G_CALLBACK (source_selector_source_added_cb), selector);
-
- g_signal_connect (
- registry, "source-changed",
- G_CALLBACK (source_selector_source_changed_cb), selector);
-
- g_signal_connect (
- registry, "source-removed",
- G_CALLBACK (source_selector_source_removed_cb), selector);
-
- g_signal_connect (
- registry, "source-enabled",
- G_CALLBACK (source_selector_source_enabled_cb), selector);
-
- g_signal_connect (
- registry, "source-disabled",
- G_CALLBACK (source_selector_source_disabled_cb), selector);
-
- source_selector_build_model (selector);
-
- gtk_tree_view_expand_all (GTK_TREE_VIEW (selector));
-}
-
-static gboolean
-source_selector_button_press_event (GtkWidget *widget,
- GdkEventButton *event)
-{
- ESourceSelector *selector;
- GtkWidgetClass *widget_class;
- GtkTreePath *path;
- ESource *source = NULL;
- ESource *primary;
- gboolean right_click = FALSE;
- gboolean triple_click = FALSE;
- gboolean row_exists;
- gboolean res = FALSE;
-
- selector = E_SOURCE_SELECTOR (widget);
-
- selector->priv->toggled_last = FALSE;
-
- /* Triple-clicking a source selects it exclusively. */
-
- if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
- right_click = TRUE;
- else if (event->button == 1 && event->type == GDK_3BUTTON_PRESS)
- triple_click = TRUE;
- else
- goto chainup;
-
- row_exists = gtk_tree_view_get_path_at_pos (
- GTK_TREE_VIEW (widget), event->x, event->y,
- &path, NULL, NULL, NULL);
-
- /* Get the source/group */
- if (row_exists) {
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
-
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
- }
-
- if (source == NULL)
- goto chainup;
-
- primary = e_source_selector_ref_primary_selection (selector);
- if (source != primary)
- e_source_selector_set_primary_selection (selector, source);
- if (primary != NULL)
- g_object_unref (primary);
-
- if (right_click)
- g_signal_emit (
- widget, signals[POPUP_EVENT], 0, source, event, &res);
-
- if (triple_click) {
- e_source_selector_select_exclusive (selector, source);
- res = TRUE;
- }
-
- g_object_unref (source);
-
- return res;
-
-chainup:
-
- /* Chain up to parent's button_press_event() method. */
- widget_class = GTK_WIDGET_CLASS (e_source_selector_parent_class);
- return widget_class->button_press_event (widget, event);
-}
-
-static void
-source_selector_drag_leave (GtkWidget *widget,
- GdkDragContext *context,
- guint time_)
-{
- GtkTreeView *tree_view;
- GtkTreeViewDropPosition pos;
-
- tree_view = GTK_TREE_VIEW (widget);
- pos = GTK_TREE_VIEW_DROP_BEFORE;
-
- gtk_tree_view_set_drag_dest_row (tree_view, NULL, pos);
-}
-
-static gboolean
-source_selector_drag_motion (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time_)
-{
- ESource *source = NULL;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *path = NULL;
- GtkTreeIter iter;
- GtkTreeViewDropPosition pos;
- GdkDragAction action = 0;
-
- tree_view = GTK_TREE_VIEW (widget);
- model = gtk_tree_view_get_model (tree_view);
-
- if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
- goto exit;
-
- if (!gtk_tree_model_get_iter (model, &iter, path))
- goto exit;
-
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- if (!e_source_get_writable (source))
- goto exit;
-
- pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
- gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
-
- if (gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE)
- action = GDK_ACTION_MOVE;
- else
- action = gdk_drag_context_get_suggested_action (context);
-
-exit:
- if (path != NULL)
- gtk_tree_path_free (path);
-
- if (source != NULL)
- g_object_unref (source);
-
- gdk_drag_status (context, action, time_);
-
- return TRUE;
-}
-
-static gboolean
-source_selector_drag_drop (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time_)
-{
- ESource *source;
- ESourceSelector *selector;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
- const gchar *extension_name;
- gboolean drop_zone;
- gboolean valid;
-
- tree_view = GTK_TREE_VIEW (widget);
- model = gtk_tree_view_get_model (tree_view);
-
- if (!gtk_tree_view_get_path_at_pos (
- tree_view, x, y, &path, NULL, NULL, NULL))
- return FALSE;
-
- valid = gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
- g_return_val_if_fail (valid, FALSE);
-
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- selector = E_SOURCE_SELECTOR (widget);
- extension_name = e_source_selector_get_extension_name (selector);
- drop_zone = e_source_has_extension (source, extension_name);
-
- g_object_unref (source);
-
- return drop_zone;
-}
-
-static void
-source_selector_drag_data_received (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection_data,
- guint info,
- guint time_)
-{
- ESource *source = NULL;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *path = NULL;
- GtkTreeIter iter;
- GdkDragAction action;
- gboolean delete;
- gboolean success = FALSE;
-
- tree_view = GTK_TREE_VIEW (widget);
- model = gtk_tree_view_get_model (tree_view);
-
- action = gdk_drag_context_get_selected_action (context);
- delete = (action == GDK_ACTION_MOVE);
-
- if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
- goto exit;
-
- if (!gtk_tree_model_get_iter (model, &iter, path))
- goto exit;
-
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- if (!e_source_get_writable (source))
- goto exit;
-
- g_signal_emit (
- widget, signals[DATA_DROPPED], 0, selection_data,
- source, gdk_drag_context_get_selected_action (context),
- info, &success);
-
-exit:
- if (path != NULL)
- gtk_tree_path_free (path);
-
- if (source != NULL)
- g_object_unref (source);
-
- gtk_drag_finish (context, success, delete, time_);
-}
-
-static gboolean
-source_selector_popup_menu (GtkWidget *widget)
-{
- ESourceSelector *selector;
- ESource *source;
- gboolean res = FALSE;
-
- selector = E_SOURCE_SELECTOR (widget);
- source = e_source_selector_ref_primary_selection (selector);
- g_signal_emit (selector, signals[POPUP_EVENT], 0, source, NULL, &res);
-
- if (source != NULL)
- g_object_unref (source);
-
- return res;
-}
-
-static gboolean
-source_selector_test_collapse_row (GtkTreeView *tree_view,
- GtkTreeIter *iter,
- GtkTreePath *path)
-{
- ESourceSelectorPrivate *priv;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter child_iter;
-
- priv = E_SOURCE_SELECTOR_GET_PRIVATE (tree_view);
-
- /* Clear this because something else has been clicked on now */
- priv->toggled_last = FALSE;
-
- if (priv->saved_primary_selection)
- return FALSE;
-
- selection = gtk_tree_view_get_selection (tree_view);
-
- if (!gtk_tree_selection_get_selected (selection, &model, &child_iter))
- return FALSE;
-
- if (gtk_tree_store_is_ancestor (GTK_TREE_STORE (model), iter, &child_iter)) {
- GtkTreeRowReference *reference;
- GtkTreePath *child_path;
-
- child_path = gtk_tree_model_get_path (model, &child_iter);
- reference = gtk_tree_row_reference_new (model, child_path);
- priv->saved_primary_selection = reference;
- gtk_tree_path_free (child_path);
- }
-
- return FALSE;
-}
-
-static void
-source_selector_row_expanded (GtkTreeView *tree_view,
- GtkTreeIter *iter,
- GtkTreePath *path)
-{
- ESourceSelectorPrivate *priv;
- GtkTreeModel *model;
- GtkTreePath *child_path;
- GtkTreeIter child_iter;
-
- priv = E_SOURCE_SELECTOR_GET_PRIVATE (tree_view);
-
- if (!priv->saved_primary_selection)
- return;
-
- model = gtk_tree_view_get_model (tree_view);
-
- child_path = gtk_tree_row_reference_get_path (
- priv->saved_primary_selection);
- gtk_tree_model_get_iter (model, &child_iter, child_path);
-
- if (gtk_tree_store_is_ancestor (GTK_TREE_STORE (model), iter, &child_iter)) {
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (tree_view);
- gtk_tree_selection_select_iter (selection, &child_iter);
-
- clear_saved_primary_selection (E_SOURCE_SELECTOR (tree_view));
- }
-
- gtk_tree_path_free (child_path);
-}
-
-static gboolean
-source_selector_get_source_selected (ESourceSelector *selector,
- ESource *source)
-{
- ESourceSelectable *extension;
- const gchar *extension_name;
- gboolean selected = TRUE;
-
- extension_name = e_source_selector_get_extension_name (selector);
-
- if (!e_source_has_extension (source, extension_name))
- return FALSE;
-
- extension = e_source_get_extension (source, extension_name);
-
- if (E_IS_SOURCE_SELECTABLE (extension))
- selected = e_source_selectable_get_selected (extension);
-
- return selected;
-}
-
-static void
-source_selector_set_source_selected (ESourceSelector *selector,
- ESource *source,
- gboolean selected)
-{
- ESourceSelectable *extension;
- const gchar *extension_name;
-
- extension_name = e_source_selector_get_extension_name (selector);
-
- if (!e_source_has_extension (source, extension_name))
- return;
-
- extension = e_source_get_extension (source, extension_name);
-
- if (!E_IS_SOURCE_SELECTABLE (extension))
- return;
-
- if (selected != e_source_selectable_get_selected (extension)) {
- e_source_selectable_set_selected (extension, selected);
- e_source_selector_queue_write (selector, source);
- }
-}
-
-static gboolean
-ess_bool_accumulator (GSignalInvocationHint *ihint,
- GValue *out,
- const GValue *in,
- gpointer data)
-{
- gboolean v_boolean;
-
- v_boolean = g_value_get_boolean (in);
- g_value_set_boolean (out, v_boolean);
-
- return !v_boolean;
-}
-
-static void
-e_source_selector_class_init (ESourceSelectorClass *class)
-{
- GObjectClass *object_class;
- GtkWidgetClass *widget_class;
- GtkTreeViewClass *tree_view_class;
-
- g_type_class_add_private (class, sizeof (ESourceSelectorPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = source_selector_set_property;
- object_class->get_property = source_selector_get_property;
- object_class->dispose = source_selector_dispose;
- object_class->finalize = source_selector_finalize;
- object_class->constructed = source_selector_constructed;
-
- widget_class = GTK_WIDGET_CLASS (class);
- widget_class->button_press_event = source_selector_button_press_event;
- widget_class->drag_leave = source_selector_drag_leave;
- widget_class->drag_motion = source_selector_drag_motion;
- widget_class->drag_drop = source_selector_drag_drop;
- widget_class->drag_data_received = source_selector_drag_data_received;
- widget_class->popup_menu = source_selector_popup_menu;
-
- tree_view_class = GTK_TREE_VIEW_CLASS (class);
- tree_view_class->test_collapse_row = source_selector_test_collapse_row;
- tree_view_class->row_expanded = source_selector_row_expanded;
-
- class->get_source_selected = source_selector_get_source_selected;
- class->set_source_selected = source_selector_set_source_selected;
-
- g_object_class_install_property (
- object_class,
- PROP_EXTENSION_NAME,
- g_param_spec_string (
- "extension-name",
- NULL,
- NULL,
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_PRIMARY_SELECTION,
- g_param_spec_object (
- "primary-selection",
- NULL,
- NULL,
- E_TYPE_SOURCE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- NULL,
- NULL,
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_COLORS,
- g_param_spec_boolean (
- "show-colors",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (
- object_class,
- PROP_SHOW_TOGGLES,
- g_param_spec_boolean (
- "show-toggles",
- NULL,
- NULL,
- TRUE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- signals[SELECTION_CHANGED] = g_signal_new (
- "selection-changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceSelectorClass, selection_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- /* XXX Consider this signal deprecated. Connect
- * to "notify::primary-selection" instead. */
- signals[PRIMARY_SELECTION_CHANGED] = g_signal_new (
- "primary-selection-changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceSelectorClass, primary_selection_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[POPUP_EVENT] = g_signal_new (
- "popup-event",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceSelectorClass, popup_event),
- ess_bool_accumulator, NULL,
- e_data_server_ui_marshal_BOOLEAN__OBJECT_BOXED,
- G_TYPE_BOOLEAN, 2, G_TYPE_OBJECT,
- GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
-
- signals[DATA_DROPPED] = g_signal_new (
- "data-dropped",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ESourceSelectorClass, data_dropped),
- NULL, NULL,
- e_data_server_ui_marshal_BOOLEAN__BOXED_OBJECT_FLAGS_UINT,
- G_TYPE_BOOLEAN, 4,
- GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
- E_TYPE_SOURCE,
- GDK_TYPE_DRAG_ACTION,
- G_TYPE_UINT);
-}
-
-static void
-e_source_selector_init (ESourceSelector *selector)
-{
- GHashTable *pending_writes;
- GtkTreeViewColumn *column;
- GtkTreeSelection *selection;
- GtkCellRenderer *renderer;
- GtkTreeStore *tree_store;
- GtkTreeView *tree_view;
-
- pending_writes = g_hash_table_new_full (
- (GHashFunc) g_direct_hash,
- (GEqualFunc) g_direct_equal,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) pending_writes_destroy_source);
-
- selector->priv = E_SOURCE_SELECTOR_GET_PRIVATE (selector);
-
- selector->priv->pending_writes = pending_writes;
-
- selector->priv->main_context = g_main_context_get_thread_default ();
- if (selector->priv->main_context != NULL)
- g_main_context_ref (selector->priv->main_context);
-
- tree_view = GTK_TREE_VIEW (selector);
-
- gtk_tree_view_set_search_column (tree_view, COLUMN_SOURCE);
- gtk_tree_view_set_enable_search (tree_view, TRUE);
-
- selector->priv->toggled_last = FALSE;
- selector->priv->select_new = FALSE;
- selector->priv->show_colors = TRUE;
- selector->priv->show_toggles = TRUE;
-
- selector->priv->source_index = g_hash_table_new_full (
- (GHashFunc) e_source_hash,
- (GEqualFunc) e_source_equal,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) gtk_tree_row_reference_free);
-
- tree_store = gtk_tree_store_new (
- NUM_COLUMNS,
- G_TYPE_STRING, /* COLUMN_NAME */
- GDK_TYPE_COLOR, /* COLUMN_COLOR */
- G_TYPE_BOOLEAN, /* COLUMN_ACTIVE */
- G_TYPE_BOOLEAN, /* COLUMN_SHOW_COLOR */
- G_TYPE_BOOLEAN, /* COLUMN_SHOW_TOGGLE */
- G_TYPE_INT, /* COLUMN_WEIGHT */
- E_TYPE_SOURCE); /* COLUMN_SOURCE */
-
- gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (tree_store));
-
- column = gtk_tree_view_column_new ();
- gtk_tree_view_append_column (tree_view, column);
-
- renderer = e_cell_renderer_color_new ();
- g_object_set (
- G_OBJECT (renderer), "mode",
- GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "color", COLUMN_COLOR);
- gtk_tree_view_column_add_attribute (
- column, renderer, "visible", COLUMN_SHOW_COLOR);
-
- renderer = e_cell_renderer_safe_toggle_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "active", COLUMN_ACTIVE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "visible", COLUMN_SHOW_TOGGLE);
- g_signal_connect (
- renderer, "toggled",
- G_CALLBACK (cell_toggled_callback), selector);
-
- renderer = gtk_cell_renderer_text_new ();
- g_object_set (
- G_OBJECT (renderer),
- "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- g_signal_connect_swapped (
- renderer, "edited",
- G_CALLBACK (text_cell_edited_cb), selector);
- gtk_tree_view_column_pack_start (column, renderer, TRUE);
- gtk_tree_view_column_set_attributes (
- column, renderer,
- "text", COLUMN_NAME,
- "weight", COLUMN_WEIGHT,
- NULL);
-
- selection = gtk_tree_view_get_selection (tree_view);
- gtk_tree_selection_set_select_function (
- selection, (GtkTreeSelectionFunc)
- selection_func, selector, NULL);
- g_signal_connect_object (
- selection, "changed",
- G_CALLBACK (selection_changed_callback),
- G_OBJECT (selector), 0);
-
- gtk_tree_view_set_headers_visible (tree_view, FALSE);
-}
-
-/**
- * e_source_selector_new:
- * @registry: an #ESourceRegistry
- * @extension_name: the name of an #ESource extension
- *
- * Displays a list of sources from @registry having an extension named
- * @extension_name. The sources are grouped by backend or groupware
- * account, which are described by the parent source.
- *
- * Returns: a new #ESourceSelector
- **/
-GtkWidget *
-e_source_selector_new (ESourceRegistry *registry,
- const gchar *extension_name)
-{
- g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
- g_return_val_if_fail (extension_name != NULL, NULL);
-
- return g_object_new (
- E_TYPE_SOURCE_SELECTOR, "registry", registry,
- "extension-name", extension_name, NULL);
-}
-
-/**
- * e_source_selector_get_registry:
- * @selector: an #ESourceSelector
- *
- * Returns the #ESourceRegistry that @selector is getting sources from.
- *
- * Returns: an #ESourceRegistry
- *
- * Since: 3.6
- **/
-ESourceRegistry *
-e_source_selector_get_registry (ESourceSelector *selector)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), NULL);
-
- return selector->priv->registry;
-}
-
-/**
- * e_source_selector_get_extension_name:
- * @selector: an #ESourceSelector
- *
- * Returns the extension name used to filter which sources are displayed.
- *
- * Returns: the #ESource extension name
- *
- * Since: 3.6
- **/
-const gchar *
-e_source_selector_get_extension_name (ESourceSelector *selector)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), NULL);
-
- return selector->priv->extension_name;
-}
-
-/**
- * e_source_selector_get_show_colors:
- * @selector: an #ESourceSelector
- *
- * Returns whether colors are shown next to data sources.
- *
- * Returns: %TRUE if colors are being shown
- *
- * Since: 3.6
- **/
-gboolean
-e_source_selector_get_show_colors (ESourceSelector *selector)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), FALSE);
-
- return selector->priv->show_colors;
-}
-
-/**
- * e_source_selector_set_show_colors:
- * @selector: an #ESourceSelector
- * @show_colors: whether to show colors
- *
- * Sets whether to show colors next to data sources.
- *
- * Since: 3.6
- **/
-void
-e_source_selector_set_show_colors (ESourceSelector *selector,
- gboolean show_colors)
-{
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
-
- if ((show_colors ? 1 : 0) == (selector->priv->show_colors ? 1 : 0))
- return;
-
- selector->priv->show_colors = show_colors;
-
- g_object_notify (G_OBJECT (selector), "show-colors");
-
- source_selector_build_model (selector);
-}
-
-/**
- * e_source_selector_get_show_toggles:
- * @selector: an #ESourceSelector
- *
- * Returns whether toggles are shown next to data sources.
- *
- * Returns: %TRUE if toggles are being shown
- *
- * Since: 3.6
- **/
-gboolean
-e_source_selector_get_show_toggles (ESourceSelector *selector)
-{
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), FALSE);
-
- return selector->priv->show_toggles;
-}
-
-/**
- * e_source_selector_set_show_toggles:
- * @selector: an #ESourceSelector
- * @show_toggles: whether to show toggles
- *
- * Sets whether to show toggles next to data sources.
- *
- * Since: 3.6
- **/
-void
-e_source_selector_set_show_toggles (ESourceSelector *selector,
- gboolean show_toggles)
-{
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
-
- if ((show_toggles ? 1 : 0) == (selector->priv->show_toggles ? 1 : 0))
- return;
-
- selector->priv->show_toggles = show_toggles;
-
- g_object_notify (G_OBJECT (selector), "show-toggles");
-
- source_selector_build_model (selector);
-}
-
-/* Helper for e_source_selector_get_selection() */
-static gboolean
-source_selector_check_selected (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer user_data)
-{
- ESource *source;
-
- struct {
- ESourceSelector *selector;
- GSList *list;
- } *closure = user_data;
-
- gtk_tree_model_get (model, iter, COLUMN_SOURCE, &source, -1);
-
- if (e_source_selector_source_is_selected (closure->selector, source))
- closure->list = g_slist_prepend (closure->list, source);
- else
- g_object_unref (source);
-
- return FALSE;
-}
-
-/**
- * e_source_selector_get_selection:
- * @selector: an #ESourceSelector
- *
- * Get the list of selected sources, i.e. those that were enabled through the
- * corresponding checkboxes in the tree.
- *
- * Returns: A list of the ESources currently selected. The sources will
- * be in the same order as they appear on the screen, and the list should be
- * freed using e_source_selector_free_selection().
- **/
-GSList *
-e_source_selector_get_selection (ESourceSelector *selector)
-{
- struct {
- ESourceSelector *selector;
- GSList *list;
- } closure;
-
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), NULL);
-
- closure.selector = selector;
- closure.list = NULL;
-
- gtk_tree_model_foreach (
- gtk_tree_view_get_model (GTK_TREE_VIEW (selector)),
- (GtkTreeModelForeachFunc) source_selector_check_selected,
- &closure);
-
- return g_slist_reverse (closure.list);
-}
-
-/**
- * e_source_list_free_selection:
- * @list: A selection list returned by e_source_selector_get_selection().
- *
- * Free the selection list.
- **/
-void
-e_source_selector_free_selection (GSList *list)
-{
- g_slist_foreach (list, (GFunc) g_object_unref, NULL);
- g_slist_free (list);
-}
-
-/**
- * e_source_selector_set_select_new:
- * @selector: An #ESourceSelector widget
- * @state: A gboolean
- *
- * Set whether or not to select new sources added to @selector.
- **/
-void
-e_source_selector_set_select_new (ESourceSelector *selector,
- gboolean state)
-{
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
-
- selector->priv->select_new = state;
-}
-
-/**
- * e_source_selector_select_source:
- * @selector: An #ESourceSelector widget
- * @source: An #ESource.
- *
- * Select @source in @selector.
- **/
-void
-e_source_selector_select_source (ESourceSelector *selector,
- ESource *source)
-{
- ESourceSelectorClass *class;
- GtkTreeRowReference *reference;
- GHashTable *source_index;
-
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
- g_return_if_fail (E_IS_SOURCE (source));
-
- /* Make sure the ESource is in our tree model. */
- source_index = selector->priv->source_index;
- reference = g_hash_table_lookup (source_index, source);
- g_return_if_fail (gtk_tree_row_reference_valid (reference));
-
- class = E_SOURCE_SELECTOR_GET_CLASS (selector);
- g_return_if_fail (class->set_source_selected != NULL);
-
- class->set_source_selected (selector, source, TRUE);
-
- g_signal_emit (selector, signals[SELECTION_CHANGED], 0);
-}
-
-/**
- * e_source_selector_unselect_source:
- * @selector: An #ESourceSelector widget
- * @source: An #ESource.
- *
- * Unselect @source in @selector.
- **/
-void
-e_source_selector_unselect_source (ESourceSelector *selector,
- ESource *source)
-{
- ESourceSelectorClass *class;
- GtkTreeRowReference *reference;
- GHashTable *source_index;
-
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
- g_return_if_fail (E_IS_SOURCE (source));
-
- /* Make sure the ESource is in our tree model. */
- source_index = selector->priv->source_index;
- reference = g_hash_table_lookup (source_index, source);
- g_return_if_fail (gtk_tree_row_reference_valid (reference));
-
- class = E_SOURCE_SELECTOR_GET_CLASS (selector);
- g_return_if_fail (class->set_source_selected != NULL);
-
- class->set_source_selected (selector, source, FALSE);
-
- g_signal_emit (selector, signals[SELECTION_CHANGED], 0);
-}
-
-/**
- * e_source_selector_select_exclusive:
- * @selector: An #ESourceSelector widget
- * @source: An #ESource.
- *
- * Select @source in @selector and unselect all others.
- *
- * Since: 2.30
- **/
-void
-e_source_selector_select_exclusive (ESourceSelector *selector,
- ESource *source)
-{
- ESourceSelectorClass *class;
- GHashTable *source_index;
- GHashTableIter iter;
- gpointer key;
-
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
- g_return_if_fail (E_IS_SOURCE (source));
-
- class = E_SOURCE_SELECTOR_GET_CLASS (selector);
- g_return_if_fail (class->set_source_selected != NULL);
-
- source_index = selector->priv->source_index;
- g_hash_table_iter_init (&iter, source_index);
-
- while (g_hash_table_iter_next (&iter, &key, NULL)) {
- gboolean selected = e_source_equal (key, source);
- class->set_source_selected (selector, key, selected);
- }
-
- g_signal_emit (selector, signals[SELECTION_CHANGED], 0);
-}
-
-/**
- * e_source_selector_source_is_selected:
- * @selector: An #ESourceSelector widget
- * @source: An #ESource.
- *
- * Check whether @source is selected in @selector.
- *
- * Returns: %TRUE if @source is currently selected, %FALSE otherwise.
- **/
-gboolean
-e_source_selector_source_is_selected (ESourceSelector *selector,
- ESource *source)
-{
- ESourceSelectorClass *class;
- GtkTreeRowReference *reference;
- GHashTable *source_index;
-
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), FALSE);
- g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
-
- /* Make sure the ESource is in our tree model. */
- source_index = selector->priv->source_index;
- reference = g_hash_table_lookup (source_index, source);
- g_return_val_if_fail (gtk_tree_row_reference_valid (reference), FALSE);
-
- class = E_SOURCE_SELECTOR_GET_CLASS (selector);
- g_return_val_if_fail (class->get_source_selected != NULL, FALSE);
-
- return class->get_source_selected (selector, source);
-}
-
-/**
- * e_source_selector_edit_primary_selection:
- * @selector: An #ESourceSelector widget
- *
- * Allows the user to rename the primary selected source by opening an
- * entry box directly in @selector.
- *
- * Since: 2.26
- **/
-void
-e_source_selector_edit_primary_selection (ESourceSelector *selector)
-{
- GtkTreeRowReference *reference;
- GtkTreeSelection *selection;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *path = NULL;
- GtkTreeIter iter;
- GList *list;
-
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
-
- tree_view = GTK_TREE_VIEW (selector);
- column = gtk_tree_view_get_column (tree_view, 0);
- reference = selector->priv->saved_primary_selection;
- selection = gtk_tree_view_get_selection (tree_view);
-
- if (reference != NULL)
- path = gtk_tree_row_reference_get_path (reference);
- else if (gtk_tree_selection_get_selected (selection, &model, &iter))
- path = gtk_tree_model_get_path (model, &iter);
-
- if (path == NULL)
- return;
-
- /* XXX Because we stuff three renderers in a single column,
- * we have to manually hunt for the text renderer. */
- renderer = NULL;
- list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
- while (list != NULL) {
- renderer = list->data;
- if (GTK_IS_CELL_RENDERER_TEXT (renderer))
- break;
- list = g_list_delete_link (list, list);
- }
- g_list_free (list);
-
- /* Make the text cell renderer editable, but only temporarily.
- * We don't want editing to be activated by simply clicking on
- * the source name. Too easy for accidental edits to occur. */
- g_object_set (renderer, "editable", TRUE, NULL);
- gtk_tree_view_expand_to_path (tree_view, path);
- gtk_tree_view_set_cursor_on_cell (
- tree_view, path, column, renderer, TRUE);
- g_object_set (renderer, "editable", FALSE, NULL);
-
- gtk_tree_path_free (path);
-}
-
-/**
- * e_source_selector_ref_primary_selection:
- * @selector: An #ESourceSelector widget
- *
- * Get the primary selected source. The primary selection is the one that is
- * highlighted through the normal #GtkTreeView selection mechanism (as opposed
- * to the "normal" selection, which is the set of source whose checkboxes are
- * checked).
- *
- * The returned #ESource is referenced for thread-safety and must be
- * unreferenced with g_object_unref() when finished with it.
- *
- * Returns: The selected source.
- *
- * Since: 3.6
- **/
-ESource *
-e_source_selector_ref_primary_selection (ESourceSelector *selector)
-{
- ESource *source;
- GtkTreeRowReference *reference;
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreeIter iter;
- const gchar *extension_name;
- gboolean have_iter = FALSE;
-
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), NULL);
-
- tree_view = GTK_TREE_VIEW (selector);
- model = gtk_tree_view_get_model (tree_view);
- selection = gtk_tree_view_get_selection (tree_view);
-
- reference = selector->priv->saved_primary_selection;
-
- if (gtk_tree_row_reference_valid (reference)) {
- GtkTreePath *path;
-
- path = gtk_tree_row_reference_get_path (reference);
- have_iter = gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
- }
-
- if (!have_iter)
- have_iter = gtk_tree_selection_get_selected (
- selection, NULL, &iter);
-
- if (!have_iter)
- return NULL;
-
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- extension_name = e_source_selector_get_extension_name (selector);
-
- if (!e_source_has_extension (source, extension_name)) {
- g_object_unref (source);
- return NULL;
- }
-
- return source;
-}
-
-/**
- * e_source_selector_set_primary_selection:
- * @selector: an #ESourceSelector widget
- * @source: an #ESource to select
- *
- * Highlights @source in @selector. The highlighted #ESource is called
- * the primary selection.
- *
- * Do not confuse this function with e_source_selector_select_source(),
- * which activates the check box next to an #ESource's display name in
- * @selector. This function does not alter the check box.
- **/
-void
-e_source_selector_set_primary_selection (ESourceSelector *selector,
- ESource *source)
-{
- GHashTable *source_index;
- GtkTreeRowReference *reference;
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GtkTreePath *child_path;
- GtkTreePath *parent_path;
- const gchar *extension_name;
-
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
- g_return_if_fail (E_IS_SOURCE (source));
-
- tree_view = GTK_TREE_VIEW (selector);
- selection = gtk_tree_view_get_selection (tree_view);
-
- source_index = selector->priv->source_index;
- reference = g_hash_table_lookup (source_index, source);
-
- /* XXX Maybe we should return a success/fail boolean? */
- if (!gtk_tree_row_reference_valid (reference))
- return;
-
- extension_name = e_source_selector_get_extension_name (selector);
-
- /* Return silently if attempting to select a parent node
- * lacking the expected extension (e.g. On This Computer). */
- if (!e_source_has_extension (source, extension_name))
- return;
-
- /* We block the signal because this all needs to be atomic */
- g_signal_handlers_block_matched (
- selection, G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, selection_changed_callback, NULL);
- gtk_tree_selection_unselect_all (selection);
- g_signal_handlers_unblock_matched (
- selection, G_SIGNAL_MATCH_FUNC,
- 0, 0, NULL, selection_changed_callback, NULL);
-
- clear_saved_primary_selection (selector);
-
- child_path = gtk_tree_row_reference_get_path (reference);
-
- parent_path = gtk_tree_path_copy (child_path);
- gtk_tree_path_up (parent_path);
-
- if (gtk_tree_view_row_expanded (tree_view, parent_path)) {
- gtk_tree_selection_select_path (selection, child_path);
- } else {
- selector->priv->saved_primary_selection =
- gtk_tree_row_reference_copy (reference);
- g_signal_emit (selector, signals[PRIMARY_SELECTION_CHANGED], 0);
- g_object_notify (G_OBJECT (selector), "primary-selection");
- }
-
- gtk_tree_path_free (child_path);
- gtk_tree_path_free (parent_path);
-}
-
-/**
- * e_source_selector_ref_source_by_path:
- * @selector: an #ESourceSelector
- * @path: a #GtkTreePath
- *
- * Returns the #ESource object at @path, or %NULL if @path is invalid.
- *
- * The returned #ESource is referenced for thread-safety and must be
- * unreferenced with g_object_unref() when finished with it.
- *
- * Returns: the #ESource object at @path, or %NULL
- *
- * Since: 3.6
- **/
-ESource *
-e_source_selector_ref_source_by_path (ESourceSelector *selector,
- GtkTreePath *path)
-{
- ESource *source = NULL;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), NULL);
- g_return_val_if_fail (path != NULL, NULL);
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector));
-
- if (gtk_tree_model_get_iter (model, &iter, path))
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- return source;
-}
-
-/**
- * e_source_selector_queue_write:
- * @selector: an #ESourceSelecetor
- * @source: an #ESource with changes to be written
- *
- * Queues a main loop idle callback to write changes to @source back to
- * the D-Bus registry service.
- *
- * Since: 3.6
- **/
-void
-e_source_selector_queue_write (ESourceSelector *selector,
- ESource *source)
-{
- GSource *idle_source;
- GHashTable *pending_writes;
- GMainContext *main_context;
- AsyncContext *async_context;
-
- g_return_if_fail (E_IS_SOURCE_SELECTOR (selector));
- g_return_if_fail (E_IS_SOURCE (source));
-
- main_context = selector->priv->main_context;
- pending_writes = selector->priv->pending_writes;
-
- idle_source = g_hash_table_lookup (pending_writes, source);
- if (idle_source != NULL && !g_source_is_destroyed (idle_source))
- return;
-
- async_context = g_slice_new0 (AsyncContext);
- async_context->selector = g_object_ref (selector);
- async_context->source = g_object_ref (source);
-
- /* Set a higher priority so this idle source runs before our
- * source_selector_cancel_write() signal handler, which will
- * cancel this idle source. Cancellation is the right thing
- * to do when receiving changes from OTHER registry clients,
- * but we don't want to cancel our own changes.
- *
- * XXX This might be an argument for using etags.
- */
- idle_source = g_idle_source_new ();
- g_hash_table_insert (
- pending_writes,
- g_object_ref (source),
- g_source_ref (idle_source));
- g_source_set_callback (
- idle_source,
- source_selector_write_idle_cb,
- async_context,
- (GDestroyNotify) async_context_free);
- g_source_set_priority (idle_source, G_PRIORITY_HIGH_IDLE);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
-}
-
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-source-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 the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Author: Ettore Perazzoli <ettore@ximian.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_SOURCE_SELECTOR_H
-#define E_SOURCE_SELECTOR_H
-
-#include <gtk/gtk.h>
-#include <libedataserver/libedataserver.h>
-
-/* Standard GObject macros */
-#define E_TYPE_SOURCE_SELECTOR \
- (e_source_selector_get_type ())
-#define E_SOURCE_SELECTOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_SOURCE_SELECTOR, ESourceSelector))
-#define E_SOURCE_SELECTOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_SOURCE_SELECTOR, ESourceSelectorClass))
-#define E_IS_SOURCE_SELECTOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_SOURCE_SELECTOR))
-#define E_IS_SOURCE_SELECTOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_SOURCE_SELECTOR))
-#define E_SOURCE_SELECTOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_SOURCE_SELECTOR, ESourceSelectorClass))
-
-G_BEGIN_DECLS
-
-typedef struct _ESourceSelector ESourceSelector;
-typedef struct _ESourceSelectorClass ESourceSelectorClass;
-typedef struct _ESourceSelectorPrivate ESourceSelectorPrivate;
-
-struct _ESourceSelector {
- GtkTreeView parent;
- ESourceSelectorPrivate *priv;
-};
-
-struct _ESourceSelectorClass {
- GtkTreeViewClass parent_class;
-
- /* Methods */
- gboolean (*get_source_selected) (ESourceSelector *selector,
- ESource *source);
- void (*set_source_selected) (ESourceSelector *selector,
- ESource *source,
- gboolean selected);
-
- /* Signals */
- void (*selection_changed) (ESourceSelector *selector);
- void (*primary_selection_changed)
- (ESourceSelector *selector);
- gboolean (*popup_event) (ESourceSelector *selector,
- ESource *primary,
- GdkEventButton *event);
- gboolean (*data_dropped) (ESourceSelector *selector,
- GtkSelectionData *data,
- ESource *destination,
- GdkDragAction action,
- guint target_info);
-
- gpointer padding1;
- gpointer padding2;
- gpointer padding3;
-};
-
-GType e_source_selector_get_type (void);
-GtkWidget * e_source_selector_new (ESourceRegistry *registry,
- const gchar *extension_name);
-ESourceRegistry *
- e_source_selector_get_registry (ESourceSelector *selector);
-const gchar * e_source_selector_get_extension_name
- (ESourceSelector *selector);
-gboolean e_source_selector_get_show_colors
- (ESourceSelector *selector);
-void e_source_selector_set_show_colors
- (ESourceSelector *selector,
- gboolean show_colors);
-gboolean e_source_selector_get_show_toggles
- (ESourceSelector *selector);
-void e_source_selector_set_show_toggles
- (ESourceSelector *selector,
- gboolean show_toggles);
-void e_source_selector_select_source (ESourceSelector *selector,
- ESource *source);
-void e_source_selector_unselect_source
- (ESourceSelector *selector,
- ESource *source);
-void e_source_selector_select_exclusive
- (ESourceSelector *selector,
- ESource *source);
-gboolean e_source_selector_source_is_selected
- (ESourceSelector *selector,
- ESource *source);
-GSList * e_source_selector_get_selection (ESourceSelector *selector);
-void e_source_selector_free_selection
- (GSList *list);
-void e_source_selector_set_select_new
- (ESourceSelector *selector,
- gboolean state);
-void e_source_selector_edit_primary_selection
- (ESourceSelector *selector);
-ESource * e_source_selector_ref_primary_selection
- (ESourceSelector *selector);
-void e_source_selector_set_primary_selection
- (ESourceSelector *selector,
- ESource *source);
-ESource * e_source_selector_ref_source_by_path
- (ESourceSelector *selector,
- GtkTreePath *path);
-void e_source_selector_queue_write (ESourceSelector *selector,
- ESource *source);
-
-G_END_DECLS
-
-#endif /* E_SOURCE_SELECTOR_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-tree-model-generator.c - Model wrapper that permutes underlying rows.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-#include <glib/gi18n-lib.h>
-#include "e-tree-model-generator.h"
-
-#define ETMG_DEBUG(x)
-
-#define ITER_IS_VALID(tree_model_generator, iter) \
- ((iter)->stamp == (tree_model_generator)->priv->stamp)
-#define ITER_GET(iter, group, index) \
- G_STMT_START { \
- *(group) = (iter)->user_data; \
- *(index) = GPOINTER_TO_INT ((iter)->user_data2); \
- } G_STMT_END
-
-#define ITER_SET(tree_model_generator, iter, group, index) \
- G_STMT_START { \
- (iter)->stamp = (tree_model_generator)->priv->stamp; \
- (iter)->user_data = group; \
- (iter)->user_data2 = GINT_TO_POINTER (index); \
- } G_STMT_END
-
-#define E_TREE_MODEL_GENERATOR_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_TREE_MODEL_GENERATOR, ETreeModelGeneratorPrivate))
-
-struct _ETreeModelGeneratorPrivate {
- GtkTreeModel *child_model;
- GArray *root_nodes;
- gint stamp;
-
- ETreeModelGeneratorGenerateFunc generate_func;
- gpointer generate_func_data;
-
- ETreeModelGeneratorModifyFunc modify_func;
- gpointer modify_func_data;
-};
-
-static void e_tree_model_generator_tree_model_init (GtkTreeModelIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (
- ETreeModelGenerator, e_tree_model_generator, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, e_tree_model_generator_tree_model_init))
-
-static GtkTreeModelFlags e_tree_model_generator_get_flags (GtkTreeModel *tree_model);
-static gint e_tree_model_generator_get_n_columns (GtkTreeModel *tree_model);
-static GType e_tree_model_generator_get_column_type (GtkTreeModel *tree_model,
- gint index);
-static gboolean e_tree_model_generator_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path);
-static GtkTreePath *e_tree_model_generator_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static void e_tree_model_generator_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value);
-static gboolean e_tree_model_generator_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean e_tree_model_generator_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent);
-static gboolean e_tree_model_generator_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gint e_tree_model_generator_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter);
-static gboolean e_tree_model_generator_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n);
-static gboolean e_tree_model_generator_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child);
-
-static GArray *build_node_map (ETreeModelGenerator *tree_model_generator, GtkTreeIter *parent_iter,
- GArray *parent_group, gint parent_index);
-static void release_node_map (GArray *group);
-
-static void child_row_changed (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter);
-static void child_row_inserted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path, GtkTreeIter *iter);
-static void child_row_deleted (ETreeModelGenerator *tree_model_generator, GtkTreePath *path);
-
-typedef struct {
- GArray *parent_group;
- gint parent_index;
-
- gint n_generated;
- GArray *child_nodes;
-}
-Node;
-
-enum {
- PROP_0,
- PROP_CHILD_MODEL
-};
-
-/* ------------------ *
- * Class/object setup *
- * ------------------ */
-
-static void
-tree_model_generator_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
-
- switch (prop_id)
- {
- case PROP_CHILD_MODEL:
- tree_model_generator->priv->child_model = g_value_get_object (value);
- g_object_ref (tree_model_generator->priv->child_model);
-
- if (tree_model_generator->priv->root_nodes)
- release_node_map (tree_model_generator->priv->root_nodes);
- tree_model_generator->priv->root_nodes =
- build_node_map (tree_model_generator, NULL, NULL, -1);
-
- g_signal_connect_swapped (
- tree_model_generator->priv->child_model, "row-changed",
- G_CALLBACK (child_row_changed), tree_model_generator);
- g_signal_connect_swapped (
- tree_model_generator->priv->child_model, "row-deleted",
- G_CALLBACK (child_row_deleted), tree_model_generator);
- g_signal_connect_swapped (
- tree_model_generator->priv->child_model, "row-inserted",
- G_CALLBACK (child_row_inserted), tree_model_generator);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-tree_model_generator_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
-
- switch (prop_id)
- {
- case PROP_CHILD_MODEL:
- g_value_set_object (value, tree_model_generator->priv->child_model);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-tree_model_generator_finalize (GObject *object)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (object);
-
- if (tree_model_generator->priv->child_model) {
- g_signal_handlers_disconnect_matched (
- tree_model_generator->priv->child_model,
- G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
- tree_model_generator);
- g_object_unref (tree_model_generator->priv->child_model);
- }
-
- if (tree_model_generator->priv->root_nodes)
- release_node_map (tree_model_generator->priv->root_nodes);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_tree_model_generator_parent_class)->finalize (object);
-}
-
-static void
-e_tree_model_generator_class_init (ETreeModelGeneratorClass *class)
-{
- GObjectClass *object_class;
-
- g_type_class_add_private (class, sizeof (ETreeModelGeneratorPrivate));
-
- object_class = G_OBJECT_CLASS (class);
- object_class->get_property = tree_model_generator_get_property;
- object_class->set_property = tree_model_generator_set_property;
- object_class->finalize = tree_model_generator_finalize;
-
- g_object_class_install_property (
- object_class,
- PROP_CHILD_MODEL,
- g_param_spec_object (
- "child-model",
- "Child Model",
- "The child model to extend",
- G_TYPE_OBJECT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-e_tree_model_generator_tree_model_init (GtkTreeModelIface *iface)
-{
- iface->get_flags = e_tree_model_generator_get_flags;
- iface->get_n_columns = e_tree_model_generator_get_n_columns;
- iface->get_column_type = e_tree_model_generator_get_column_type;
- iface->get_iter = e_tree_model_generator_get_iter;
- iface->get_path = e_tree_model_generator_get_path;
- iface->get_value = e_tree_model_generator_get_value;
- iface->iter_next = e_tree_model_generator_iter_next;
- iface->iter_children = e_tree_model_generator_iter_children;
- iface->iter_has_child = e_tree_model_generator_iter_has_child;
- iface->iter_n_children = e_tree_model_generator_iter_n_children;
- iface->iter_nth_child = e_tree_model_generator_iter_nth_child;
- iface->iter_parent = e_tree_model_generator_iter_parent;
-}
-
-static void
-e_tree_model_generator_init (ETreeModelGenerator *tree_model_generator)
-{
- tree_model_generator->priv =
- E_TREE_MODEL_GENERATOR_GET_PRIVATE (tree_model_generator);
-
- tree_model_generator->priv->stamp = g_random_int ();
- tree_model_generator->priv->root_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
-}
-
-/* ------------------ *
- * Row update helpers *
- * ------------------ */
-
-static void
-row_deleted (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path)
-{
- g_assert (path);
-
- ETMG_DEBUG (g_print ("row_deleted emitting\n"));
- gtk_tree_model_row_deleted (GTK_TREE_MODEL (tree_model_generator), path);
-}
-
-static void
-row_inserted (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path)
-{
- GtkTreeIter iter;
-
- g_assert (path);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_generator), &iter, path)) {
- ETMG_DEBUG (g_print ("row_inserted emitting\n"));
- gtk_tree_model_row_inserted (GTK_TREE_MODEL (tree_model_generator), path, &iter);
- } else {
- ETMG_DEBUG (g_print ("row_inserted could not get iter!\n"));
- }
-}
-
-static void
-row_changed (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path)
-{
- GtkTreeIter iter;
-
- g_assert (path);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_model_generator), &iter, path)) {
- ETMG_DEBUG (g_print ("row_changed emitting\n"));
- gtk_tree_model_row_changed (GTK_TREE_MODEL (tree_model_generator), path, &iter);
- } else {
- ETMG_DEBUG (g_print ("row_changed could not get iter!\n"));
- }
-}
-
-/* -------------------- *
- * Node map translation *
- * -------------------- */
-
-static gint
-generated_offset_to_child_offset (GArray *group,
- gint offset,
- gint *internal_offset)
-{
- gboolean success = FALSE;
- gint accum_offset = 0;
- gint i;
-
- for (i = 0; i < group->len; i++) {
- Node *node = &g_array_index (group, Node, i);
-
- accum_offset += node->n_generated;
- if (accum_offset > offset) {
- accum_offset -= node->n_generated;
- success = TRUE;
- break;
- }
- }
-
- if (!success)
- return -1;
-
- if (internal_offset)
- *internal_offset = offset - accum_offset;
-
- return i;
-}
-
-static gint
-child_offset_to_generated_offset (GArray *group,
- gint offset)
-{
- gint accum_offset = 0;
- gint i;
-
- g_return_val_if_fail (group != NULL, -1);
-
- for (i = 0; i < group->len && i < offset; i++) {
- Node *node = &g_array_index (group, Node, i);
-
- accum_offset += node->n_generated;
- }
-
- return accum_offset;
-}
-
-static gint
-count_generated_nodes (GArray *group)
-{
- gint accum_offset = 0;
- gint i;
-
- for (i = 0; i < group->len; i++) {
- Node *node = &g_array_index (group, Node, i);
-
- accum_offset += node->n_generated;
- }
-
- return accum_offset;
-}
-
-/* ------------------- *
- * Node map management *
- * ------------------- */
-
-static void
-release_node_map (GArray *group)
-{
- gint i;
-
- for (i = 0; i < group->len; i++) {
- Node *node = &g_array_index (group, Node, i);
-
- if (node->child_nodes)
- release_node_map (node->child_nodes);
- }
-
- g_array_free (group, TRUE);
-}
-
-static gint
-append_node (GArray *group)
-{
- g_array_set_size (group, group->len + 1);
- return group->len - 1;
-}
-
-static GArray *
-build_node_map (ETreeModelGenerator *tree_model_generator,
- GtkTreeIter *parent_iter,
- GArray *parent_group,
- gint parent_index)
-{
- GArray *group;
- GtkTreeIter iter;
- gboolean result;
-
- if (parent_iter)
- result = gtk_tree_model_iter_children (tree_model_generator->priv->child_model, &iter, parent_iter);
- else
- result = gtk_tree_model_get_iter_first (tree_model_generator->priv->child_model, &iter);
-
- if (!result)
- return NULL;
-
- group = g_array_new (FALSE, FALSE, sizeof (Node));
-
- do {
- Node *node;
- gint i;
-
- i = append_node (group);
- node = &g_array_index (group, Node, i);
-
- node->parent_group = parent_group;
- node->parent_index = parent_index;
-
- if (tree_model_generator->priv->generate_func)
- node->n_generated =
- tree_model_generator->priv->generate_func (tree_model_generator->priv->child_model,
- &iter, tree_model_generator->priv->generate_func_data);
- else
- node->n_generated = 1;
-
- node->child_nodes = build_node_map (tree_model_generator, &iter, group, i);
- } while (gtk_tree_model_iter_next (tree_model_generator->priv->child_model, &iter));
-
- return group;
-}
-
-static gint
-get_first_visible_index_from (GArray *group,
- gint index)
-{
- gint i;
-
- for (i = index; i < group->len; i++) {
- Node *node = &g_array_index (group, Node, i);
-
- if (node->n_generated)
- break;
- }
-
- if (i >= group->len)
- i = -1;
-
- return i;
-}
-
-static Node *
-get_node_by_child_path (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path,
- GArray **node_group)
-{
- Node *node = NULL;
- GArray *group;
- gint depth;
-
- group = tree_model_generator->priv->root_nodes;
-
- for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
- gint index;
-
- if (!group) {
- g_warning ("ETreeModelGenerator got unknown child element!");
- break;
- }
-
- index = gtk_tree_path_get_indices (path)[depth];
- node = &g_array_index (group, Node, index);
-
- if (depth + 1 < gtk_tree_path_get_depth (path))
- group = node->child_nodes;
- }
-
- if (!node)
- group = NULL;
-
- if (node_group)
- *node_group = group;
-
- return node;
-}
-
-static Node *
-create_node_at_child_path (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path)
-{
- GtkTreePath *parent_path;
- gint parent_index;
- GArray *parent_group;
- GArray *group;
- gint index;
- Node *node;
-
- parent_path = gtk_tree_path_copy (path);
- gtk_tree_path_up (parent_path);
- node = get_node_by_child_path (tree_model_generator, parent_path, &parent_group);
-
- if (node) {
- if (!node->child_nodes)
- node->child_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
-
- group = node->child_nodes;
- parent_index = gtk_tree_path_get_indices (parent_path)[gtk_tree_path_get_depth (parent_path) - 1];
- } else {
- if (!tree_model_generator->priv->root_nodes)
- tree_model_generator->priv->root_nodes = g_array_new (FALSE, FALSE, sizeof (Node));
-
- group = tree_model_generator->priv->root_nodes;
- parent_index = -1;
- }
-
- gtk_tree_path_free (parent_path);
-
- index = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path) - 1];
- ETMG_DEBUG (g_print ("Inserting index %d into group of length %d\n", index, group->len));
- index = MIN (index, group->len);
-
- append_node (group);
-
- if (group->len - 1 - index > 0) {
- gint i;
-
- memmove (
- (Node *) group->data + index + 1,
- (Node *) group->data + index,
- (group->len - 1 - index) * sizeof (Node));
-
- /* Update parent pointers */
- for (i = index + 1; i < group->len; i++) {
- Node *pnode = &g_array_index (group, Node, i);
- GArray *child_group;
- gint j;
-
- child_group = pnode->child_nodes;
- if (!child_group)
- continue;
-
- for (j = 0; j < child_group->len; j++) {
- Node *child_node = &g_array_index (child_group, Node, j);
- child_node->parent_index = i;
- }
- }
- }
-
- node = &g_array_index (group, Node, index);
- node->parent_group = parent_group;
- node->parent_index = parent_index;
- node->n_generated = 0;
- node->child_nodes = NULL;
-
- ETMG_DEBUG (
- g_print ("Created node at offset %d, parent_group = %p, parent_index = %d\n",
- index, node->parent_group, node->parent_index));
-
- return node;
-}
-
-ETMG_DEBUG (
-
-static void
-dump_group (GArray *group)
-{
- gint i;
-
- g_print ("\nGroup %p:\n", group);
-
- for (i = 0; i < group->len; i++) {
- Node *node = &g_array_index (group, Node, i);
- g_print (
- " %04d: pgroup=%p, pindex=%d, n_generated=%d, child_nodes=%p\n",
- i, node->parent_group, node->parent_index, node->n_generated, node->child_nodes);
- }
-}
-
-)
-
-static void
-delete_node_at_child_path (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path)
-{
- GtkTreePath *parent_path;
- GArray *parent_group;
- GArray *group;
- gint index;
- Node *node;
- gint i;
-
- parent_path = gtk_tree_path_copy (path);
- gtk_tree_path_up (parent_path);
- node = get_node_by_child_path (tree_model_generator, parent_path, &parent_group);
-
- if (node) {
- group = node->child_nodes;
- } else {
- group = tree_model_generator->priv->root_nodes;
- }
-
- gtk_tree_path_free (parent_path);
-
- if (!group)
- return;
-
- index = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path) - 1];
- if (index >= group->len)
- return;
-
- node = &g_array_index (group, Node, index);
- if (node->child_nodes)
- release_node_map (node->child_nodes);
- g_array_remove_index (group, index);
-
- /* Update parent pointers */
- for (i = index; i < group->len; i++) {
- Node *pnode = &g_array_index (group, Node, i);
- GArray *child_group;
- gint j;
-
- child_group = pnode->child_nodes;
- if (!child_group)
- continue;
-
- for (j = 0; j < child_group->len; j++) {
- Node *child_node = &g_array_index (child_group, Node, j);
- child_node->parent_index = i;
- }
- }
-}
-
-static void
-child_row_changed (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path,
- GtkTreeIter *iter)
-{
- GtkTreePath *generated_path;
- Node *node;
- gint n_generated;
- gint i;
-
- if (tree_model_generator->priv->generate_func)
- n_generated =
- tree_model_generator->priv->generate_func (tree_model_generator->priv->child_model,
- iter, tree_model_generator->priv->generate_func_data);
- else
- n_generated = 1;
-
- node = get_node_by_child_path (tree_model_generator, path, NULL);
- if (!node)
- return;
-
- generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
-
- /* FIXME: Converting the path to an iter every time is inefficient */
-
- for (i = 0; i < n_generated && i < node->n_generated; i++) {
- row_changed (tree_model_generator, generated_path);
- gtk_tree_path_next (generated_path);
- }
-
- for (; i < node->n_generated; ) {
- node->n_generated--;
- row_deleted (tree_model_generator, generated_path);
- }
-
- for (; i < n_generated; i++) {
- node->n_generated++;
- row_inserted (tree_model_generator, generated_path);
- gtk_tree_path_next (generated_path);
- }
-
- gtk_tree_path_free (generated_path);
-}
-
-static void
-child_row_inserted (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path,
- GtkTreeIter *iter)
-{
- GtkTreePath *generated_path;
- Node *node;
- gint n_generated;
-
- if (tree_model_generator->priv->generate_func)
- n_generated =
- tree_model_generator->priv->generate_func (tree_model_generator->priv->child_model,
- iter, tree_model_generator->priv->generate_func_data);
- else
- n_generated = 1;
-
- node = create_node_at_child_path (tree_model_generator, path);
- if (!node)
- return;
-
- generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
-
- /* FIXME: Converting the path to an iter every time is inefficient */
-
- for (node->n_generated = 0; node->n_generated < n_generated; ) {
- node->n_generated++;
- row_inserted (tree_model_generator, generated_path);
- gtk_tree_path_next (generated_path);
- }
-
- gtk_tree_path_free (generated_path);
-}
-
-static void
-child_row_deleted (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *path)
-{
- GtkTreePath *generated_path;
- Node *node;
-
- node = get_node_by_child_path (tree_model_generator, path, NULL);
- if (!node)
- return;
-
- generated_path = e_tree_model_generator_convert_child_path_to_path (tree_model_generator, path);
-
- /* FIXME: Converting the path to an iter every time is inefficient */
-
- for (; node->n_generated; ) {
- node->n_generated--;
- row_deleted (tree_model_generator, generated_path);
- }
-
- delete_node_at_child_path (tree_model_generator, path);
- gtk_tree_path_free (generated_path);
-}
-
-/* ----------------------- *
- * ETreeModelGenerator API *
- * ----------------------- */
-
-/**
- * e_tree_model_generator_new:
- * @child_model: a #GtkTreeModel
- *
- * Creates a new #ETreeModelGenerator wrapping @child_model.
- *
- * Returns: A new #ETreeModelGenerator.
- **/
-ETreeModelGenerator *
-e_tree_model_generator_new (GtkTreeModel *child_model)
-{
- g_return_val_if_fail (GTK_IS_TREE_MODEL (child_model), NULL);
-
- return E_TREE_MODEL_GENERATOR (
- g_object_new (E_TYPE_TREE_MODEL_GENERATOR,
- "child-model", child_model, NULL));
-}
-
-/**
- * e_tree_model_generator_get_model:
- * @tree_model_generator: an #ETreeModelGenerator
- *
- * Gets the child model being wrapped by @tree_model_generator.
- *
- * Returns: A #GtkTreeModel being wrapped.
- **/
-GtkTreeModel *
-e_tree_model_generator_get_model (ETreeModelGenerator *tree_model_generator)
-{
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
-
- return tree_model_generator->priv->child_model;
-}
-
-/**
- * e_tree_model_generator_set_generate_func:
- * @tree_model_generator: an #ETreeModelGenerator
- * @func: an #ETreeModelGeneratorGenerateFunc, or %NULL
- * @data: user data to pass to @func
- * @destroy:
- *
- * Sets the callback function used to filter or generate additional rows
- * based on the child model's data. This function is called for each child
- * row, and returns a value indicating the number of rows that will be
- * used to represent the child row - 0 or more.
- *
- * If @func is %NULL, a filtering/generating function will not be applied.
- **/
-void
-e_tree_model_generator_set_generate_func (ETreeModelGenerator *tree_model_generator,
- ETreeModelGeneratorGenerateFunc func,
- gpointer data,
- GDestroyNotify destroy)
-{
- g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
-
- tree_model_generator->priv->generate_func = func;
- tree_model_generator->priv->generate_func_data = data;
-}
-
-/**
- * e_tree_model_generator_set_modify_func:
- * @tree_model_generator: an #ETreeModelGenerator
- * @func: an @ETreeModelGeneratorModifyFunc, or %NULL
- * @data: user data to pass to @func
- * @destroy:
- *
- * Sets the callback function used to override values for the child row's
- * columns and specify values for generated rows' columns.
- *
- * If @func is %NULL, the child model's values will always be used.
- **/
-void
-e_tree_model_generator_set_modify_func (ETreeModelGenerator *tree_model_generator,
- ETreeModelGeneratorModifyFunc func,
- gpointer data,
- GDestroyNotify destroy)
-{
- g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
-
- tree_model_generator->priv->modify_func = func;
- tree_model_generator->priv->modify_func_data = data;
-}
-
-/**
- * e_tree_model_generator_convert_child_path_to_path:
- * @tree_model_generator: an #ETreeModelGenerator
- * @child_path: a #GtkTreePath
- *
- * Convert a path to a child row to a path to a @tree_model_generator row.
- *
- * Returns: A new GtkTreePath, owned by the caller.
- **/
-GtkTreePath *
-e_tree_model_generator_convert_child_path_to_path (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *child_path)
-{
- GtkTreePath *path;
- GArray *group;
- gint depth;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
- g_return_val_if_fail (child_path != NULL, NULL);
-
- path = gtk_tree_path_new ();
-
- group = tree_model_generator->priv->root_nodes;
-
- for (depth = 0; depth < gtk_tree_path_get_depth (child_path); depth++) {
- Node *node;
- gint index;
- gint generated_index;
-
- if (!group) {
- g_warning ("ETreeModelGenerator was asked for path to unknown child element!");
- break;
- }
-
- index = gtk_tree_path_get_indices (child_path)[depth];
- generated_index = child_offset_to_generated_offset (group, index);
- node = &g_array_index (group, Node, index);
- group = node->child_nodes;
-
- gtk_tree_path_append_index (path, generated_index);
- }
-
- return path;
-}
-
-/**
- * e_tree_model_generator_convert_child_iter_to_iter:
- * @tree_model_generator: an #ETreeModelGenerator
- * @generator_iter: a #GtkTreeIter to set
- * @child_iter: a #GtkTreeIter to convert
- *
- * Convert @child_iter to a corresponding #GtkTreeIter for @tree_model_generator,
- * storing the result in @generator_iter.
- **/
-void
-e_tree_model_generator_convert_child_iter_to_iter (ETreeModelGenerator *tree_model_generator,
- GtkTreeIter *generator_iter,
- GtkTreeIter *child_iter)
-{
- GtkTreePath *path;
- GArray *group;
- gint depth;
- gint index = 0;
-
- g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
-
- path = gtk_tree_model_get_path (tree_model_generator->priv->child_model, child_iter);
- if (!path)
- return;
-
- group = tree_model_generator->priv->root_nodes;
-
- for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
- Node *node;
-
- index = gtk_tree_path_get_indices (path)[depth];
- node = &g_array_index (group, Node, index);
-
- if (depth + 1 < gtk_tree_path_get_depth (path))
- group = node->child_nodes;
-
- if (!group) {
- g_warning ("ETreeModelGenerator was asked for iter to unknown child element!");
- break;
- }
- }
-
- g_return_if_fail (group != NULL);
-
- index = child_offset_to_generated_offset (group, index);
- ITER_SET (tree_model_generator, generator_iter, group, index);
- gtk_tree_path_free (path);
-}
-
-/**
- * e_tree_model_generator_convert_path_to_child_path:
- * @tree_model_generator: an #ETreeModelGenerator
- * @generator_path: a #GtkTreePath to a @tree_model_generator row
- *
- * Converts @generator_path to a corresponding #GtkTreePath in the child model.
- *
- * Returns: A new #GtkTreePath, owned by the caller.
- **/
-GtkTreePath *
-e_tree_model_generator_convert_path_to_child_path (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *generator_path)
-{
- GtkTreePath *path;
- GArray *group;
- gint depth;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator), NULL);
- g_return_val_if_fail (generator_path != NULL, NULL);
-
- path = gtk_tree_path_new ();
-
- group = tree_model_generator->priv->root_nodes;
-
- for (depth = 0; depth < gtk_tree_path_get_depth (generator_path); depth++) {
- Node *node;
- gint index;
- gint child_index;
-
- if (!group) {
- g_warning ("ETreeModelGenerator was asked for path to unknown child element!");
- break;
- }
-
- index = gtk_tree_path_get_indices (generator_path)[depth];
- child_index = generated_offset_to_child_offset (group, index, NULL);
- node = &g_array_index (group, Node, child_index);
- group = node->child_nodes;
-
- gtk_tree_path_append_index (path, child_index);
- }
-
- return path;
-}
-
-/**
- * e_tree_model_generator_convert_iter_to_child_iter:
- * @tree_model_generator: an #ETreeModelGenerator
- * @child_iter: a #GtkTreeIter to set
- * @permutation_n: a permutation index to set
- * @generator_iter: a #GtkTreeIter indicating the row to convert
- *
- * Converts a @tree_model_generator row into a child row and permutation index.
- * The permutation index is the index of the generated row based on this
- * child row, with the first generated row based on this child row being 0.
- **/
-void
-e_tree_model_generator_convert_iter_to_child_iter (ETreeModelGenerator *tree_model_generator,
- GtkTreeIter *child_iter,
- gint *permutation_n,
- GtkTreeIter *generator_iter)
-{
- GtkTreePath *path;
- GArray *group;
- gint index;
- gint internal_offset = 0;
-
- g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model_generator));
- g_return_if_fail (ITER_IS_VALID (tree_model_generator, generator_iter));
-
- path = gtk_tree_path_new ();
- ITER_GET (generator_iter, &group, &index);
-
- index = generated_offset_to_child_offset (group, index, &internal_offset);
- gtk_tree_path_prepend_index (path, index);
-
- while (group) {
- Node *node = &g_array_index (group, Node, index);
-
- group = node->parent_group;
- index = node->parent_index;
-
- if (group)
- gtk_tree_path_prepend_index (path, index);
- }
-
- if (child_iter)
- gtk_tree_model_get_iter (tree_model_generator->priv->child_model, child_iter, path);
- if (permutation_n)
- *permutation_n = internal_offset;
-
- gtk_tree_path_free (path);
-}
-
-/* ---------------- *
- * GtkTreeModel API *
- * ---------------- */
-
-static GtkTreeModelFlags
-e_tree_model_generator_get_flags (GtkTreeModel *tree_model)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
-
- return gtk_tree_model_get_flags (tree_model_generator->priv->child_model);
-}
-
-static gint
-e_tree_model_generator_get_n_columns (GtkTreeModel *tree_model)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
-
- return gtk_tree_model_get_n_columns (tree_model_generator->priv->child_model);
-}
-
-static GType
-e_tree_model_generator_get_column_type (GtkTreeModel *tree_model,
- gint index)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), G_TYPE_INVALID);
-
- return gtk_tree_model_get_column_type (tree_model_generator->priv->child_model, index);
-}
-
-static gboolean
-e_tree_model_generator_get_iter (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreePath *path)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- GArray *group;
- gint depth;
- gint index = 0;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
- g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
-
- group = tree_model_generator->priv->root_nodes;
- if (!group)
- return FALSE;
-
- for (depth = 0; depth < gtk_tree_path_get_depth (path); depth++) {
- Node *node;
- gint child_index;
-
- index = gtk_tree_path_get_indices (path)[depth];
- child_index = generated_offset_to_child_offset (group, index, NULL);
- if (child_index < 0)
- return FALSE;
-
- node = &g_array_index (group, Node, child_index);
-
- if (depth + 1 < gtk_tree_path_get_depth (path)) {
- group = node->child_nodes;
- if (!group)
- return FALSE;
- }
- }
-
- ITER_SET (tree_model_generator, iter, group, index);
- return TRUE;
-}
-
-static GtkTreePath *
-e_tree_model_generator_get_path (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- GtkTreePath *path;
- GArray *group;
- gint index;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), NULL);
- g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), NULL);
-
- ITER_GET (iter, &group, &index);
- path = gtk_tree_path_new ();
-
- /* FIXME: Converting a path to an iter is a destructive operation, because
- * we don't store a node for each generated entry... Doesn't matter for
- * lists, not sure about trees. */
-
- gtk_tree_path_prepend_index (path, index);
- index = generated_offset_to_child_offset (group, index, NULL);
-
- while (group) {
- Node *node = &g_array_index (group, Node, index);
- gint generated_index;
-
- group = node->parent_group;
- index = node->parent_index;
- if (group) {
- generated_index = child_offset_to_generated_offset (group, index);
- gtk_tree_path_prepend_index (path, generated_index);
- }
- }
-
- return path;
-}
-
-static gboolean
-e_tree_model_generator_iter_next (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- Node *node;
- GArray *group;
- gint index;
- gint child_index;
- gint internal_offset = 0;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
- g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), FALSE);
-
- ITER_GET (iter, &group, &index);
- child_index = generated_offset_to_child_offset (group, index, &internal_offset);
- node = &g_array_index (group, Node, child_index);
-
- if (internal_offset + 1 < node->n_generated ||
- get_first_visible_index_from (group, child_index + 1) >= 0) {
- ITER_SET (tree_model_generator, iter, group, index + 1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-e_tree_model_generator_iter_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- Node *node;
- GArray *group;
- gint index;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
-
- if (!parent) {
- if (!tree_model_generator->priv->root_nodes ||
- !count_generated_nodes (tree_model_generator->priv->root_nodes))
- return FALSE;
-
- ITER_SET (tree_model_generator, iter, tree_model_generator->priv->root_nodes, 0);
- return TRUE;
- }
-
- ITER_GET (parent, &group, &index);
- index = generated_offset_to_child_offset (group, index, NULL);
- if (index < 0)
- return FALSE;
-
- node = &g_array_index (group, Node, index);
-
- if (!node->child_nodes)
- return FALSE;
-
- if (!count_generated_nodes (node->child_nodes))
- return FALSE;
-
- ITER_SET (tree_model_generator, iter, node->child_nodes, 0);
- return TRUE;
-}
-
-static gboolean
-e_tree_model_generator_iter_has_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- Node *node;
- GArray *group;
- gint index;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
-
- if (iter == NULL) {
- if (!tree_model_generator->priv->root_nodes ||
- !count_generated_nodes (tree_model_generator->priv->root_nodes))
- return FALSE;
-
- return TRUE;
- }
-
- ITER_GET (iter, &group, &index);
- index = generated_offset_to_child_offset (group, index, NULL);
- if (index < 0)
- return FALSE;
-
- node = &g_array_index (group, Node, index);
-
- if (!node->child_nodes)
- return FALSE;
-
- if (!count_generated_nodes (node->child_nodes))
- return FALSE;
-
- return TRUE;
-}
-
-static gint
-e_tree_model_generator_iter_n_children (GtkTreeModel *tree_model,
- GtkTreeIter *iter)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- Node *node;
- GArray *group;
- gint index;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), 0);
-
- if (iter == NULL)
- return tree_model_generator->priv->root_nodes ?
- count_generated_nodes (tree_model_generator->priv->root_nodes) : 0;
-
- ITER_GET (iter, &group, &index);
- index = generated_offset_to_child_offset (group, index, NULL);
- if (index < 0)
- return 0;
-
- node = &g_array_index (group, Node, index);
-
- if (!node->child_nodes)
- return 0;
-
- return count_generated_nodes (node->child_nodes);
-}
-
-static gboolean
-e_tree_model_generator_iter_nth_child (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *parent,
- gint n)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- Node *node;
- GArray *group;
- gint index;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
-
- if (!parent) {
- if (!tree_model_generator->priv->root_nodes)
- return FALSE;
-
- if (n >= count_generated_nodes (tree_model_generator->priv->root_nodes))
- return FALSE;
-
- ITER_SET (tree_model_generator, iter, tree_model_generator->priv->root_nodes, n);
- return TRUE;
- }
-
- ITER_GET (parent, &group, &index);
- index = generated_offset_to_child_offset (group, index, NULL);
- if (index < 0)
- return FALSE;
-
- node = &g_array_index (group, Node, index);
-
- if (!node->child_nodes)
- return FALSE;
-
- if (n >= count_generated_nodes (node->child_nodes))
- return FALSE;
-
- ITER_SET (tree_model_generator, iter, node->child_nodes, n);
- return TRUE;
-}
-
-static gboolean
-e_tree_model_generator_iter_parent (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- GtkTreeIter *child)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- Node *node;
- GArray *group;
- gint index;
-
- g_return_val_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model), FALSE);
- g_return_val_if_fail (ITER_IS_VALID (tree_model_generator, iter), FALSE);
-
- ITER_GET (child, &group, &index);
- index = generated_offset_to_child_offset (group, index, NULL);
- if (index < 0)
- return FALSE;
-
- node = &g_array_index (group, Node, index);
-
- group = node->parent_group;
- if (!group)
- return FALSE;
-
- ITER_SET (tree_model_generator, iter, group, node->parent_index);
- return TRUE;
-}
-
-static void
-e_tree_model_generator_get_value (GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gint column,
- GValue *value)
-{
- ETreeModelGenerator *tree_model_generator = E_TREE_MODEL_GENERATOR (tree_model);
- GtkTreeIter child_iter;
- gint permutation_n;
-
- g_return_if_fail (E_IS_TREE_MODEL_GENERATOR (tree_model));
- g_return_if_fail (ITER_IS_VALID (tree_model_generator, iter));
-
- e_tree_model_generator_convert_iter_to_child_iter (
- tree_model_generator, &child_iter,
- &permutation_n, iter);
-
- if (tree_model_generator->priv->modify_func) {
- tree_model_generator->priv->modify_func (tree_model_generator->priv->child_model,
- &child_iter, permutation_n,
- column, value,
- tree_model_generator->priv->modify_func_data);
- return;
- }
-
- gtk_tree_model_get_value (tree_model_generator->priv->child_model, &child_iter, column, value);
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* e-tree-model-generator.h - Model wrapper that permutes underlying rows.
- *
- * 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 Lesser 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser 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.
- *
- * Authors: Hans Petter Jansson <hpj@novell.com>
- */
-
-#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION)
-#error "Only <libedataserverui/libedataserverui.h> should be included directly."
-#endif
-
-#ifndef E_TREE_MODEL_GENERATOR_H
-#define E_TREE_MODEL_GENERATOR_H
-
-#include <gtk/gtk.h>
-
-/* Standard GObject macros */
-#define E_TYPE_TREE_MODEL_GENERATOR \
- (e_tree_model_generator_get_type ())
-#define E_TREE_MODEL_GENERATOR(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_TREE_MODEL_GENERATOR, ETreeModelGenerator))
-#define E_TREE_MODEL_GENERATOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_TREE_MODEL_GENERATOR, ETreeModelGeneratorClass))
-#define E_IS_TREE_MODEL_GENERATOR(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_TREE_MODEL_GENERATOR))
-#define E_IS_TREE_MODEL_GENERATOR_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_TREE_MODEL_GENERATOR))
-#define E_TREE_MODEL_GENERATOR_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_TREE_MODEL_GENERATOR, ETreeModelGeneratorClass))
-
-G_BEGIN_DECLS
-
-typedef gint (*ETreeModelGeneratorGenerateFunc) (GtkTreeModel *model, GtkTreeIter *child_iter,
- gpointer data);
-typedef void (*ETreeModelGeneratorModifyFunc) (GtkTreeModel *model, GtkTreeIter *child_iter,
- gint permutation_n, gint column, GValue *value,
- gpointer data);
-
-typedef struct _ETreeModelGenerator ETreeModelGenerator;
-typedef struct _ETreeModelGeneratorClass ETreeModelGeneratorClass;
-typedef struct _ETreeModelGeneratorPrivate ETreeModelGeneratorPrivate;
-
-struct _ETreeModelGenerator {
- GObject parent;
- ETreeModelGeneratorPrivate *priv;
-};
-
-struct _ETreeModelGeneratorClass {
- GObjectClass parent_class;
-};
-
-GType e_tree_model_generator_get_type (void);
-ETreeModelGenerator *
- e_tree_model_generator_new (GtkTreeModel *child_model);
-GtkTreeModel * e_tree_model_generator_get_model (ETreeModelGenerator *tree_model_generator);
-void e_tree_model_generator_set_generate_func
- (ETreeModelGenerator *tree_model_generator,
- ETreeModelGeneratorGenerateFunc func,
- gpointer data,
- GDestroyNotify destroy);
-void e_tree_model_generator_set_modify_func
- (ETreeModelGenerator *tree_model_generator,
- ETreeModelGeneratorModifyFunc func,
- gpointer data,
- GDestroyNotify destroy);
-GtkTreePath * e_tree_model_generator_convert_child_path_to_path
- (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *child_path);
-void e_tree_model_generator_convert_child_iter_to_iter
- (ETreeModelGenerator *tree_model_generator,
- GtkTreeIter *generator_iter,
- GtkTreeIter *child_iter);
-GtkTreePath * e_tree_model_generator_convert_path_to_child_path
- (ETreeModelGenerator *tree_model_generator,
- GtkTreePath *generator_path);
-void e_tree_model_generator_convert_iter_to_child_iter
- (ETreeModelGenerator *tree_model_generator,
- GtkTreeIter *child_iter,
- gint *permutation_n,
- GtkTreeIter *generator_iter);
-
-G_END_DECLS
-
-#endif /* E_TREE_MODEL_GENERATOR_H */
+++ /dev/null
-/*
- * libedataserverui.h
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- */
-
-#ifndef LIBEDATASERVERUI_H
-#define LIBEDATASERVERUI_H
-
-#define __LIBEDATASERVERUI_H_INSIDE__
-
-#include <libedataserver/libedataserver.h>
-
-#include <libedataserverui/e-book-auth-util.h>
-#include <libedataserverui/e-categories-dialog.h>
-#include <libedataserverui/e-categories-editor.h>
-#include <libedataserverui/e-categories-selector.h>
-#include <libedataserverui/e-category-completion.h>
-#include <libedataserverui/e-category-editor.h>
-#include <libedataserverui/e-cell-renderer-color.h>
-#include <libedataserverui/e-client-utils.h>
-#include <libedataserverui/e-contact-store.h>
-#include <libedataserverui/e-destination-store.h>
-#include <libedataserverui/e-name-selector-dialog.h>
-#include <libedataserverui/e-name-selector-entry.h>
-#include <libedataserverui/e-name-selector-list.h>
-#include <libedataserverui/e-name-selector-model.h>
-#include <libedataserverui/e-name-selector.h>
-#include <libedataserverui/e-passwords.h>
-#include <libedataserverui/e-source-combo-box.h>
-#include <libedataserverui/e-source-selector-dialog.h>
-#include <libedataserverui/e-source-selector.h>
-#include <libedataserverui/e-tree-model-generator.h>
-
-#undef __LIBEDATASERVERUI_H_INSIDE__
-
-#endif /* LIBEDATASERVERUI_H */
-
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-privincludedir=@privincludedir@
-
-Name: libedataserverui
-Description: GUI utility library for Evolution Data Server
-Version: @VERSION@
-Requires: gtk+-3.0 libedataserver-1.2 libebook-1.2
-Libs: -L${libdir} -ledataserverui-3.0
-Cflags: -I${privincludedir}
-SUBDIRS = libedataserver libedataserverui libebook libecal libedata-cal tools
+SUBDIRS = libedataserver libebook libecal libedata-cal tools
@GNOME_CODE_COVERAGE_RULES@
+++ /dev/null
-noinst_PROGRAMS = \
- evolution-source-viewer \
- test-category-completion \
- test-source-combo-box \
- test-source-selector \
- test-contact-store \
- test-name-selector
-
-TEST_EDATASERVERUI_CPPFLAGS= \
- $(AM_CPPFLAGS) \
- -I$(top_srcdir) \
- -I$(top_srcdir)/addressbook \
- -I$(top_builddir)/addressbook \
- -DLOCALEDIR=\""$(localedir)"\" \
- -DG_LOG_DOMAIN=\"e-data-server-ui\" \
- $(CAMEL_CFLAGS) \
- $(LIBSECRET_CFLAGS) \
- $(E_DATA_SERVER_UI_CFLAGS)
-
-TEST_EDATASERVERUI_LDFLAGS = \
- $(top_builddir)/camel/libcamel-1.2.la \
- $(top_builddir)/calendar/libecal/libecal-1.2.la \
- $(top_builddir)/addressbook/libebook/libebook-1.2.la \
- $(top_builddir)/libebackend/libebackend-1.2.la \
- $(top_builddir)/libedataserver/libedataserver-1.2.la \
- $(top_builddir)/libedataserverui/libedataserverui-3.0.la \
- $(CAMEL_LIBS) \
- $(LIBSECRET_LIBS) \
- $(E_DATA_SERVER_UI_LIBS)
-
-evolution_source_viewer_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
-evolution_source_viewer_SOURCES = evolution-source-viewer.c
-evolution_source_viewer_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
-
-test_category_completion_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
-test_category_completion_SOURCES = test-category-completion.c
-test_category_completion_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
-
-test_source_selector_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
-test_source_selector_SOURCES = test-source-selector.c
-test_source_selector_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
-
-test_source_combo_box_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
-test_source_combo_box_SOURCES = test-source-combo-box.c
-test_source_combo_box_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
-
-test_contact_store_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
-test_contact_store_SOURCES = test-contact-store.c
-test_contact_store_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
-
-test_name_selector_CPPFLAGS = $(TEST_EDATASERVERUI_CPPFLAGS)
-test_name_selector_SOURCES = test-name-selector.c
-test_name_selector_LDADD = $(TEST_EDATASERVERUI_LDFLAGS)
-
--include $(top_srcdir)/git.mk
+++ /dev/null
-/*
- * evolution-source-viewer.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with the program; if not, see <http://www.gnu.org/licenses/>
- *
- */
-
-#include <config.h>
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include <libedataserver/libedataserver.h>
-
-/* XXX Even though this is all one file, I'm still being pedantic about data
- * encapsulation (except for a private struct, even I'm not that anal!).
- * I expect this program will eventually be too complex for one file
- * and we'll want to split off an e-source-viewer.[ch]. */
-
-/* Standard GObject macros */
-#define E_TYPE_SOURCE_VIEWER \
- (e_source_viewer_get_type ())
-#define E_SOURCE_VIEWER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_SOURCE_VIEWER, ESourceViewer))
-#define E_SOURCE_VIEWER_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_SOURCE_VIEWER, ESourceViewerClass))
-#define E_IS_SOURCE_VIEWER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_SOURCE_VIEWER))
-#define E_IS_SOURCE_VIEWER_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_SOURCE_VIEWER))
-#define E_SOURCE_VIEWER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_SOURCE_VIEWER, ESourceViewerClass))
-
-typedef struct _ESourceViewer ESourceViewer;
-typedef struct _ESourceViewerClass ESourceViewerClass;
-
-struct _ESourceViewer {
- GtkWindow parent;
- ESourceRegistry *registry;
-
- GtkTreeStore *tree_store;
- GHashTable *source_index;
-
- GCancellable *delete_operation;
-
- GtkWidget *tree_view; /* not referenced */
- GtkWidget *text_view; /* not referenced */
- GtkWidget *top_panel; /* not referenced */
-
- /* Viewing Page */
- GtkWidget *viewing_label; /* not referenced */
- GtkWidget *delete_button; /* not referenced */
-
- /* Deleting Page */
- GtkWidget *deleting_label; /* not referenced */
- GtkWidget *deleting_cancel; /* not referenced */
-};
-
-struct _ESourceViewerClass {
- GtkWindowClass parent_class;
-};
-
-enum {
- PAGE_VIEWING,
- PAGE_DELETING
-};
-
-enum {
- PROP_0,
- PROP_REGISTRY
-};
-
-enum {
- COLUMN_DISPLAY_NAME,
- COLUMN_SOURCE_UID,
- COLUMN_REMOVABLE,
- COLUMN_WRITABLE,
- COLUMN_REMOTE_CREATABLE,
- COLUMN_REMOTE_DELETABLE,
- COLUMN_SOURCE,
- NUM_COLUMNS
-};
-
-/* Forward Declarations */
-GType e_source_viewer_get_type (void) G_GNUC_CONST;
-GtkWidget * e_source_viewer_new (GCancellable *cancellable,
- GError **error);
-ESourceRegistry *
- e_source_viewer_get_registry (ESourceViewer *viewer);
-GtkTreePath * e_source_viewer_dup_selected_path
- (ESourceViewer *viewer);
-gboolean e_source_viewer_set_selected_path
- (ESourceViewer *viewer,
- GtkTreePath *path);
-ESource * e_source_viewer_ref_selected_source
- (ESourceViewer *viewer);
-gboolean e_source_viewer_set_selected_source
- (ESourceViewer *viewer,
- ESource *source);
-GNode * e_source_viewer_build_display_tree
- (ESourceViewer *viewer);
-
-static void e_source_viewer_initable_init (GInitableIface *interface);
-
-G_DEFINE_TYPE_WITH_CODE (
- ESourceViewer,
- e_source_viewer,
- GTK_TYPE_WINDOW,
- G_IMPLEMENT_INTERFACE (
- G_TYPE_INITABLE,
- e_source_viewer_initable_init));
-
-static GIcon *
-source_view_new_remote_creatable_icon (void)
-{
- GEmblem *emblem;
- GIcon *emblem_icon;
- GIcon *folder_icon;
- GIcon *icon;
-
- emblem_icon = g_themed_icon_new ("emblem-new");
- folder_icon = g_themed_icon_new ("folder-remote");
-
- emblem = g_emblem_new (emblem_icon);
- icon = g_emblemed_icon_new (folder_icon, emblem);
- g_object_unref (emblem);
-
- g_object_unref (folder_icon);
- g_object_unref (emblem_icon);
-
- return icon;
-}
-
-static GIcon *
-source_view_new_remote_deletable_icon (void)
-{
- GEmblem *emblem;
- GIcon *emblem_icon;
- GIcon *folder_icon;
- GIcon *icon;
-
- emblem_icon = g_themed_icon_new ("edit-delete");
- folder_icon = g_themed_icon_new ("folder-remote");
-
- emblem = g_emblem_new (emblem_icon);
- icon = g_emblemed_icon_new (folder_icon, emblem);
- g_object_unref (emblem);
-
- g_object_unref (folder_icon);
- g_object_unref (emblem_icon);
-
- return icon;
-}
-
-static gchar *
-source_viewer_get_monospace_font_name (void)
-{
- GSettings *settings;
- gchar *font_name;
-
- settings = g_settings_new ("org.gnome.desktop.interface");
- font_name = g_settings_get_string (settings, "monospace-font-name");
- g_object_unref (settings);
-
- /* Fallback to a reasonable default. */
- if (font_name == NULL)
- font_name = g_strdup ("Monospace 10");
-
- return font_name;
-}
-
-static void
-source_viewer_set_text (ESourceViewer *viewer,
- ESource *source)
-{
- GtkTextView *text_view;
- GtkTextBuffer *buffer;
- GtkTextIter start;
- GtkTextIter end;
-
- text_view = GTK_TEXT_VIEW (viewer->text_view);
- buffer = gtk_text_view_get_buffer (text_view);
-
- gtk_text_buffer_get_start_iter (buffer, &start);
- gtk_text_buffer_get_end_iter (buffer, &end);
- gtk_text_buffer_delete (buffer, &start, &end);
-
- if (source != NULL) {
- gchar *string;
- gsize length;
-
- gtk_text_buffer_get_start_iter (buffer, &start);
-
- string = e_source_to_string (source, &length);
- gtk_text_buffer_insert (buffer, &start, string, length);
- g_free (string);
- }
-}
-
-static void
-source_viewer_update_row (ESourceViewer *viewer,
- ESource *source)
-{
- GHashTable *source_index;
- GtkTreeRowReference *reference;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
- const gchar *display_name;
- const gchar *source_uid;
- gboolean removable;
- gboolean writable;
- gboolean remote_creatable;
- gboolean remote_deletable;
-
- source_index = viewer->source_index;
- reference = g_hash_table_lookup (source_index, source);
-
- /* We show all sources, so the reference should be valid. */
- g_return_if_fail (gtk_tree_row_reference_valid (reference));
-
- model = gtk_tree_row_reference_get_model (reference);
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
-
- source_uid = e_source_get_uid (source);
- display_name = e_source_get_display_name (source);
- removable = e_source_get_removable (source);
- writable = e_source_get_writable (source);
- remote_creatable = e_source_get_remote_creatable (source);
- remote_deletable = e_source_get_remote_deletable (source);
-
- gtk_tree_store_set (
- GTK_TREE_STORE (model), &iter,
- COLUMN_DISPLAY_NAME, display_name,
- COLUMN_SOURCE_UID, source_uid,
- COLUMN_REMOVABLE, removable,
- COLUMN_WRITABLE, writable,
- COLUMN_REMOTE_CREATABLE, remote_creatable,
- COLUMN_REMOTE_DELETABLE, remote_deletable,
- COLUMN_SOURCE, source,
- -1);
-}
-
-static gboolean
-source_viewer_traverse (GNode *node,
- gpointer user_data)
-{
- ESourceViewer *viewer;
- ESource *source;
- GHashTable *source_index;
- GtkTreeRowReference *reference = NULL;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- /* Skip the root node. */
- if (G_NODE_IS_ROOT (node))
- return FALSE;
-
- viewer = E_SOURCE_VIEWER (user_data);
-
- source_index = viewer->source_index;
-
- tree_view = GTK_TREE_VIEW (viewer->tree_view);
- model = gtk_tree_view_get_model (tree_view);
-
- if (node->parent != NULL && node->parent->data != NULL)
- reference = g_hash_table_lookup (
- source_index, node->parent->data);
-
- if (gtk_tree_row_reference_valid (reference)) {
- GtkTreeIter parent;
-
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_model_get_iter (model, &parent, path);
- gtk_tree_path_free (path);
-
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent);
- } else
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
-
- /* Source index takes ownership. */
- source = g_object_ref (node->data);
-
- path = gtk_tree_model_get_path (model, &iter);
- reference = gtk_tree_row_reference_new (model, path);
- g_hash_table_insert (source_index, source, reference);
- gtk_tree_path_free (path);
-
- source_viewer_update_row (viewer, source);
-
- return FALSE;
-}
-
-static void
-source_viewer_save_expanded (GtkTreeView *tree_view,
- GtkTreePath *path,
- GQueue *queue)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- ESource *source;
-
- model = gtk_tree_view_get_model (tree_view);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
- g_queue_push_tail (queue, source);
-}
-
-static void
-source_viewer_build_model (ESourceViewer *viewer)
-{
- GQueue queue = G_QUEUE_INIT;
- GHashTable *source_index;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreePath *sel_path;
- ESource *sel_source;
- GNode *root;
-
- tree_view = GTK_TREE_VIEW (viewer->tree_view);
-
- source_index = viewer->source_index;
- sel_path = e_source_viewer_dup_selected_path (viewer);
- sel_source = e_source_viewer_ref_selected_source (viewer);
-
- /* Save expanded sources to restore later. */
- gtk_tree_view_map_expanded_rows (
- tree_view, (GtkTreeViewMappingFunc)
- source_viewer_save_expanded, &queue);
-
- model = gtk_tree_view_get_model (tree_view);
- gtk_tree_store_clear (GTK_TREE_STORE (model));
-
- g_hash_table_remove_all (source_index);
-
- root = e_source_viewer_build_display_tree (viewer);
-
- g_node_traverse (
- root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) source_viewer_traverse, viewer);
-
- e_source_registry_free_display_tree (root);
-
- /* Restore previously expanded sources. */
- while (!g_queue_is_empty (&queue)) {
- GtkTreeRowReference *reference;
- ESource *source;
-
- source = g_queue_pop_head (&queue);
- reference = g_hash_table_lookup (source_index, source);
-
- if (gtk_tree_row_reference_valid (reference)) {
- GtkTreePath *path;
-
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_view_expand_to_path (tree_view, path);
- gtk_tree_path_free (path);
- }
-
- g_object_unref (source);
- }
-
- /* Restore the selection. */
- if (sel_source != NULL && sel_path != NULL) {
- if (!e_source_viewer_set_selected_source (viewer, sel_source))
- e_source_viewer_set_selected_path (viewer, sel_path);
- }
-
- if (sel_path != NULL)
- gtk_tree_path_free (sel_path);
-
- if (sel_source != NULL)
- g_object_unref (sel_source);
-}
-
-static void
-source_viewer_expand_to_source (ESourceViewer *viewer,
- ESource *source)
-{
- GHashTable *source_index;
- GtkTreeRowReference *reference;
- GtkTreeView *tree_view;
- GtkTreePath *path;
-
- source_index = viewer->source_index;
- reference = g_hash_table_lookup (source_index, source);
-
- /* We show all sources, so the reference should be valid. */
- g_return_if_fail (gtk_tree_row_reference_valid (reference));
-
- /* Expand the tree view to the path containing the ESource. */
- tree_view = GTK_TREE_VIEW (viewer->tree_view);
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_view_expand_to_path (tree_view, path);
- gtk_tree_path_free (path);
-}
-
-static void
-source_viewer_source_added_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceViewer *viewer)
-{
- source_viewer_build_model (viewer);
-
- source_viewer_expand_to_source (viewer, source);
-}
-
-static void
-source_viewer_source_changed_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceViewer *viewer)
-{
- ESource *selected;
-
- source_viewer_update_row (viewer, source);
-
- selected = e_source_viewer_ref_selected_source (viewer);
- if (selected != NULL) {
- if (e_source_equal (source, selected))
- source_viewer_set_text (viewer, source);
- g_object_unref (selected);
- }
-}
-
-static void
-source_viewer_source_removed_cb (ESourceRegistry *registry,
- ESource *source,
- ESourceViewer *viewer)
-{
- source_viewer_build_model (viewer);
-}
-
-static void
-source_viewer_selection_changed_cb (GtkTreeSelection *selection,
- ESourceViewer *viewer)
-{
- ESource *source;
- const gchar *uid = NULL;
- gboolean removable = FALSE;
-
- source = e_source_viewer_ref_selected_source (viewer);
-
- source_viewer_set_text (viewer, source);
-
- if (source != NULL) {
- uid = e_source_get_uid (source);
- removable = e_source_get_removable (source);
- }
-
- gtk_label_set_text (GTK_LABEL (viewer->viewing_label), uid);
- gtk_widget_set_visible (viewer->delete_button, removable);
-
- if (source != NULL)
- g_object_unref (source);
-}
-
-static void
-source_viewer_delete_done_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- ESource *source;
- ESourceViewer *viewer;
- GError *error = NULL;
-
- source = E_SOURCE (source_object);
- viewer = E_SOURCE_VIEWER (user_data);
-
- e_source_remove_finish (source, result, &error);
-
- /* Ignore cancellations. */
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- g_clear_error (&error);
-
- /* FIXME Show an info bar with the error message. */
- } else if (error != NULL) {
- g_warning ("%s: %s", G_STRFUNC, error->message);
- g_clear_error (&error);
- }
-
- gtk_notebook_set_current_page (
- GTK_NOTEBOOK (viewer->top_panel), PAGE_VIEWING);
- gtk_widget_set_sensitive (viewer->tree_view, TRUE);
-
- g_object_unref (viewer->delete_operation);
- viewer->delete_operation = NULL;
-
- g_object_unref (viewer);
-}
-
-static void
-source_viewer_delete_button_clicked_cb (GtkButton *delete_button,
- ESourceViewer *viewer)
-{
- ESource *source;
- const gchar *uid;
-
- g_return_if_fail (viewer->delete_operation == NULL);
-
- source = e_source_viewer_ref_selected_source (viewer);
- g_return_if_fail (source != NULL);
-
- uid = e_source_get_uid (source);
- gtk_label_set_text (GTK_LABEL (viewer->deleting_label), uid);
-
- gtk_notebook_set_current_page (
- GTK_NOTEBOOK (viewer->top_panel), PAGE_DELETING);
- gtk_widget_set_sensitive (viewer->tree_view, FALSE);
-
- viewer->delete_operation = g_cancellable_new ();
-
- e_source_remove (
- source,
- viewer->delete_operation,
- source_viewer_delete_done_cb,
- g_object_ref (viewer));
-
- g_object_unref (source);
-}
-
-static void
-source_viewer_deleting_cancel_clicked_cb (GtkButton *deleting_cancel,
- ESourceViewer *viewer)
-{
- g_return_if_fail (viewer->delete_operation != NULL);
-
- g_cancellable_cancel (viewer->delete_operation);
-}
-
-static void
-source_viewer_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_REGISTRY:
- g_value_set_object (
- value,
- e_source_viewer_get_registry (
- E_SOURCE_VIEWER (object)));
- return;
- }
-
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
-
-static void
-source_viewer_dispose (GObject *object)
-{
- ESourceViewer *viewer = E_SOURCE_VIEWER (object);
-
- if (viewer->registry != NULL) {
- g_signal_handlers_disconnect_matched (
- viewer->registry,
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, object);
- g_object_unref (viewer->registry);
- viewer->registry = NULL;
- }
-
- if (viewer->tree_store != NULL) {
- g_object_unref (viewer->tree_store);
- viewer->tree_store = NULL;
- }
-
- g_hash_table_remove_all (viewer->source_index);
-
- if (viewer->delete_operation != NULL) {
- g_object_unref (viewer->delete_operation);
- viewer->delete_operation = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_source_viewer_parent_class)->dispose (object);
-}
-
-static void
-source_viewer_finalize (GObject *object)
-{
- ESourceViewer *viewer = E_SOURCE_VIEWER (object);
-
- g_hash_table_destroy (viewer->source_index);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_source_viewer_parent_class)->finalize (object);
-}
-
-static void
-source_viewer_constructed (GObject *object)
-{
- ESourceViewer *viewer;
- GtkTreeViewColumn *column;
- GtkTreeSelection *selection;
- GtkCellRenderer *renderer;
- GtkWidget *container;
- GtkWidget *paned;
- GtkWidget *widget;
- PangoAttribute *attr;
- PangoAttrList *bold;
- PangoFontDescription *desc;
- GIcon *icon;
- const gchar *title;
- gchar *font_name;
- gint page_num;
-
- viewer = E_SOURCE_VIEWER (object);
-
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_source_viewer_parent_class)->constructed (object);
-
- bold = pango_attr_list_new ();
- attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
- pango_attr_list_insert (bold, attr);
-
- title = _("Evolution Source Viewer");
- gtk_window_set_title (GTK_WINDOW (viewer), title);
- gtk_window_set_default_size (GTK_WINDOW (viewer), 800, 600);
-
- paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
- gtk_paned_set_position (GTK_PANED (paned), 400);
- gtk_container_add (GTK_CONTAINER (viewer), paned);
- gtk_widget_show (paned);
-
- /* Left panel */
-
- widget = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
- gtk_paned_add1 (GTK_PANED (paned), widget);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = gtk_tree_view_new_with_model (
- GTK_TREE_MODEL (viewer->tree_store));
- gtk_container_add (GTK_CONTAINER (container), widget);
- viewer->tree_view = widget; /* do not reference */
- gtk_widget_show (widget);
-
- column = gtk_tree_view_column_new ();
- /* Translators: The name that is displayed in the user interface */
- gtk_tree_view_column_set_title (column, _("Display Name"));
- gtk_tree_view_append_column (GTK_TREE_VIEW (widget), column);
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_column_pack_start (column, renderer, TRUE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "text", COLUMN_DISPLAY_NAME);
-
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_title (column, _("Flags"));
- gtk_tree_view_append_column (GTK_TREE_VIEW (widget), column);
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (
- renderer,
- "stock-id", GTK_STOCK_EDIT,
- "stock-size", GTK_ICON_SIZE_MENU,
- NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "visible", COLUMN_WRITABLE);
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (
- renderer,
- "stock-id", GTK_STOCK_DELETE,
- "stock-size", GTK_ICON_SIZE_MENU,
- NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "visible", COLUMN_REMOVABLE);
-
- icon = source_view_new_remote_creatable_icon ();
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (
- renderer,
- "gicon", icon,
- "stock-size", GTK_ICON_SIZE_MENU,
- NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "visible", COLUMN_REMOTE_CREATABLE);
- g_object_unref (icon);
-
- icon = source_view_new_remote_deletable_icon ();
- renderer = gtk_cell_renderer_pixbuf_new ();
- g_object_set (
- renderer,
- "gicon", icon,
- "stock-size", GTK_ICON_SIZE_MENU,
- NULL);
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "visible", COLUMN_REMOTE_DELETABLE);
- g_object_unref (icon);
-
- /* Append an empty pixbuf renderer to fill leftover space. */
- renderer = gtk_cell_renderer_pixbuf_new ();
- gtk_tree_view_column_pack_start (column, renderer, TRUE);
-
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_title (column, _("Identity"));
- gtk_tree_view_append_column (GTK_TREE_VIEW (widget), column);
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (
- column, renderer, "text", COLUMN_SOURCE_UID);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
-
- /* Right panel */
-
- widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_paned_add2 (GTK_PANED (paned), widget);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = gtk_notebook_new ();
- gtk_widget_set_margin_top (widget, 3);
- gtk_widget_set_margin_right (widget, 3);
- gtk_widget_set_margin_bottom (widget, 3);
- /* leave left margin at zero */
- gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
- viewer->top_panel = widget; /* do not reference */
- gtk_widget_show (widget);
-
- widget = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (widget),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
- gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = gtk_text_view_new ();
- gtk_text_view_set_editable (GTK_TEXT_VIEW (widget), FALSE);
- gtk_container_add (GTK_CONTAINER (container), widget);
- viewer->text_view = widget; /* do not reference */
- gtk_widget_show (widget);
-
- font_name = source_viewer_get_monospace_font_name ();
- desc = pango_font_description_from_string (font_name);
- gtk_widget_override_font (widget, desc);
- pango_font_description_free (desc);
- g_free (font_name);
-
- /* Top panel: Viewing */
-
- container = viewer->top_panel;
-
- widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
- page_num = gtk_notebook_append_page (
- GTK_NOTEBOOK (container), widget, NULL);
- g_warn_if_fail (page_num == PAGE_VIEWING);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = gtk_label_new ("Identity:");
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
- gtk_widget_show (widget);
-
- widget = gtk_label_new (NULL);
- gtk_label_set_attributes (GTK_LABEL (widget), bold);
- gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
- viewer->viewing_label = widget; /* do not reference */
- gtk_widget_show (widget);
-
- widget = gtk_button_new_from_stock (GTK_STOCK_DELETE);
- gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
- viewer->delete_button = widget; /* do not reference */
- gtk_widget_hide (widget);
-
- /* Top panel: Deleting */
-
- container = viewer->top_panel;
-
- widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
- page_num = gtk_notebook_append_page (
- GTK_NOTEBOOK (container), widget, NULL);
- g_warn_if_fail (page_num == PAGE_DELETING);
- gtk_widget_show (widget);
-
- container = widget;
-
- widget = gtk_label_new ("Deleting");
- gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
- gtk_widget_show (widget);
-
- widget = gtk_label_new (NULL);
- gtk_label_set_attributes (GTK_LABEL (widget), bold);
- gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
- gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
- viewer->deleting_label = widget; /* do not reference */
- gtk_widget_show (widget);
-
- widget = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
- gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
- viewer->deleting_cancel = widget; /* do not reference */
- gtk_widget_show (widget);
-
- pango_attr_list_unref (bold);
-
- g_signal_connect (
- selection, "changed",
- G_CALLBACK (source_viewer_selection_changed_cb), viewer);
-
- g_signal_connect (
- viewer->delete_button, "clicked",
- G_CALLBACK (source_viewer_delete_button_clicked_cb), viewer);
-
- g_signal_connect (
- viewer->deleting_cancel, "clicked",
- G_CALLBACK (source_viewer_deleting_cancel_clicked_cb), viewer);
-}
-
-static gboolean
-source_viewer_initable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
-{
- ESourceViewer *viewer;
- ESourceRegistry *registry;
-
- viewer = E_SOURCE_VIEWER (initable);
-
- registry = e_source_registry_new_sync (cancellable, error);
-
- if (registry == NULL)
- return FALSE;
-
- viewer->registry = registry; /* takes ownership */
-
- g_signal_connect (
- registry, "source-added",
- G_CALLBACK (source_viewer_source_added_cb), viewer);
-
- g_signal_connect (
- registry, "source-changed",
- G_CALLBACK (source_viewer_source_changed_cb), viewer);
-
- g_signal_connect (
- registry, "source-removed",
- G_CALLBACK (source_viewer_source_removed_cb), viewer);
-
- source_viewer_build_model (viewer);
-
- gtk_tree_view_expand_all (GTK_TREE_VIEW (viewer->tree_view));
-
- return TRUE;
-}
-
-static void
-e_source_viewer_class_init (ESourceViewerClass *class)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (class);
- object_class->get_property = source_viewer_get_property;
- object_class->dispose = source_viewer_dispose;
- object_class->finalize = source_viewer_finalize;
- object_class->constructed = source_viewer_constructed;
-
- g_object_class_install_property (
- object_class,
- PROP_REGISTRY,
- g_param_spec_object (
- "registry",
- "Registry",
- "Data source registry",
- E_TYPE_SOURCE_REGISTRY,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-}
-
-static void
-e_source_viewer_initable_init (GInitableIface *interface)
-{
- interface->init = source_viewer_initable_init;
-}
-
-static void
-e_source_viewer_init (ESourceViewer *viewer)
-{
- viewer->tree_store = gtk_tree_store_new (
- NUM_COLUMNS,
- G_TYPE_STRING, /* COLUMN_DISPLAY_NAME */
- G_TYPE_STRING, /* COLUMN_SOURCE_UID */
- G_TYPE_BOOLEAN, /* COLUMN_REMOVABLE */
- G_TYPE_BOOLEAN, /* COLUMN_WRITABLE */
- G_TYPE_BOOLEAN, /* COLUMN_REMOTE_CREATABLE */
- G_TYPE_BOOLEAN, /* COLUMN_REMOTE_DELETABLE */
- E_TYPE_SOURCE); /* COLUMN_SOURCE */
-
- viewer->source_index = g_hash_table_new_full (
- (GHashFunc) e_source_hash,
- (GEqualFunc) e_source_equal,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) gtk_tree_row_reference_free);
-}
-
-GtkWidget *
-e_source_viewer_new (GCancellable *cancellable,
- GError **error)
-{
- return g_initable_new (
- E_TYPE_SOURCE_VIEWER,
- cancellable, error, NULL);
-}
-
-ESourceRegistry *
-e_source_viewer_get_registry (ESourceViewer *viewer)
-{
- g_return_val_if_fail (E_IS_SOURCE_VIEWER (viewer), NULL);
-
- return viewer->registry;
-}
-
-GtkTreePath *
-e_source_viewer_dup_selected_path (ESourceViewer *viewer)
-{
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- g_return_val_if_fail (E_IS_SOURCE_VIEWER (viewer), NULL);
-
- tree_view = GTK_TREE_VIEW (viewer->tree_view);
- selection = gtk_tree_view_get_selection (tree_view);
-
- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
- return NULL;
-
- return gtk_tree_model_get_path (model, &iter);
-}
-
-gboolean
-e_source_viewer_set_selected_path (ESourceViewer *viewer,
- GtkTreePath *path)
-{
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- g_return_val_if_fail (E_IS_SOURCE_VIEWER (viewer), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
-
- tree_view = GTK_TREE_VIEW (viewer->tree_view);
- selection = gtk_tree_view_get_selection (tree_view);
-
- /* Check that the path is valid. */
- model = gtk_tree_view_get_model (tree_view);
- if (!gtk_tree_model_get_iter (model, &iter, path))
- return FALSE;
-
- gtk_tree_selection_unselect_all (selection);
-
- gtk_tree_view_expand_to_path (tree_view, path);
- gtk_tree_selection_select_path (selection, path);
-
- return TRUE;
-}
-
-ESource *
-e_source_viewer_ref_selected_source (ESourceViewer *viewer)
-{
- ESource *source;
- GtkTreeSelection *selection;
- GtkTreeView *tree_view;
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- g_return_val_if_fail (E_IS_SOURCE_VIEWER (viewer), NULL);
-
- tree_view = GTK_TREE_VIEW (viewer->tree_view);
- selection = gtk_tree_view_get_selection (tree_view);
-
- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
- return NULL;
-
- gtk_tree_model_get (model, &iter, COLUMN_SOURCE, &source, -1);
-
- return source;
-}
-
-gboolean
-e_source_viewer_set_selected_source (ESourceViewer *viewer,
- ESource *source)
-{
- GHashTable *source_index;
- GtkTreeRowReference *reference;
- GtkTreePath *path;
- gboolean success;
-
- g_return_val_if_fail (E_IS_SOURCE_VIEWER (viewer), FALSE);
- g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
-
- source_index = viewer->source_index;
- reference = g_hash_table_lookup (source_index, source);
-
- if (!gtk_tree_row_reference_valid (reference))
- return FALSE;
-
- path = gtk_tree_row_reference_get_path (reference);
- success = e_source_viewer_set_selected_path (viewer, path);
- gtk_tree_path_free (path);
-
- return success;
-}
-
-/* Helper for e_source_viewer_build_display_tree() */
-static gint
-source_viewer_compare_nodes (GNode *node_a,
- GNode *node_b)
-{
- ESource *source_a = E_SOURCE (node_a->data);
- ESource *source_b = E_SOURCE (node_b->data);
-
- return e_source_compare_by_display_name (source_a, source_b);
-}
-
-/* Helper for e_source_viewer_build_display_tree() */
-static gboolean
-source_viewer_sort_nodes (GNode *node,
- gpointer unused)
-{
- GQueue queue = G_QUEUE_INIT;
- GNode *child_node;
-
- /* Unlink all the child nodes and place them in a queue. */
- while ((child_node = g_node_first_child (node)) != NULL) {
- g_node_unlink (child_node);
- g_queue_push_tail (&queue, child_node);
- }
-
- /* Sort the queue by source name. */
- g_queue_sort (
- &queue, (GCompareDataFunc)
- source_viewer_compare_nodes, NULL);
-
- /* Pop nodes off the head of the queue and put them back
- * under the parent node (preserving the sorted order). */
- while ((child_node = g_queue_pop_head (&queue)) != NULL)
- g_node_append (node, child_node);
-
- return FALSE;
-}
-
-GNode *
-e_source_viewer_build_display_tree (ESourceViewer *viewer)
-{
- GNode *root;
- GHashTable *index;
- GList *list, *link;
- GHashTableIter iter;
- gpointer value;
-
- /* This is just like e_source_registry_build_display_tree()
- * except it includes all data sources, even disabled ones.
- * Free the tree with e_source_registry_free_display_tree(). */
-
- g_return_val_if_fail (E_IS_SOURCE_VIEWER (viewer), NULL);
-
- root = g_node_new (NULL);
- index = g_hash_table_new (g_str_hash, g_str_equal);
-
- /* Add a GNode for each ESource to the index.
- * The GNodes take ownership of the ESource references. */
- list = e_source_registry_list_sources (viewer->registry, NULL);
- for (link = list; link != NULL; link = g_list_next (link)) {
- ESource *source = E_SOURCE (link->data);
- gpointer key = (gpointer) e_source_get_uid (source);
- g_hash_table_insert (index, key, g_node_new (source));
- }
- g_list_free (list);
-
- /* Traverse the index and link the nodes together. */
- g_hash_table_iter_init (&iter, index);
- while (g_hash_table_iter_next (&iter, NULL, &value)) {
- ESource *source;
- GNode *source_node;
- GNode *parent_node;
- const gchar *parent_uid;
-
- source_node = (GNode *) value;
- source = E_SOURCE (source_node->data);
- parent_uid = e_source_get_parent (source);
-
- if (parent_uid == NULL || *parent_uid == '\0') {
- parent_node = root;
- } else {
- parent_node = g_hash_table_lookup (index, parent_uid);
- }
-
- /* This could be NULL if the registry service was
- * shutdown or reloaded. All sources will vanish. */
- if (parent_node != NULL)
- g_node_append (parent_node, source_node);
- }
-
- /* Sort nodes by display name in post order. */
- g_node_traverse (
- root, G_POST_ORDER, G_TRAVERSE_ALL,
- -1, source_viewer_sort_nodes, NULL);
-
- g_hash_table_destroy (index);
-
- return root;
-}
-
-gint
-main (gint argc,
- gchar **argv)
-{
- GtkWidget *viewer;
- GError *error = NULL;
-
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
-
- gtk_init (&argc, &argv);
-
- viewer = e_source_viewer_new (NULL, &error);
-
- if (error != NULL) {
- g_warn_if_fail (viewer == NULL);
- g_error ("%s", error->message);
- g_assert_not_reached ();
- }
-
- g_signal_connect (
- viewer, "delete-event",
- G_CALLBACK (gtk_main_quit), NULL);
-
- gtk_widget_show (viewer);
-
- gtk_main ();
-
- return 0;
-}
+++ /dev/null
-/*
- * 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 Lesser 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 Lesser 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 <libedataserverui/libedataserverui.h>
-
-static gboolean
-on_idle_create_widget (void)
-{
- GtkWidget *window;
- GtkWidget *vgrid;
- GtkWidget *entry;
- GtkEntryCompletion *completion;
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size (GTK_WINDOW (window), 400, 200);
-
- g_signal_connect (
- window, "delete-event",
- G_CALLBACK (gtk_main_quit), NULL);
-
- vgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", FALSE,
- "row-spacing", 3,
- NULL);
- gtk_container_add (GTK_CONTAINER (window), vgrid);
-
- entry = gtk_entry_new ();
- completion = e_category_completion_new ();
- gtk_entry_set_completion (GTK_ENTRY (entry), completion);
- gtk_widget_set_vexpand (entry, TRUE);
- gtk_widget_set_hexpand (entry, TRUE);
- gtk_widget_set_halign (entry, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (vgrid), entry);
-
- gtk_widget_show_all (window);
-
- return FALSE;
-}
-
-gint
-main (gint argc,
- gchar **argv)
-{
- gtk_init (&argc, &argv);
-
- g_idle_add ((GSourceFunc) on_idle_create_widget, NULL);
-
- gtk_main ();
-
- return 0;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* test-contact-store.c - Test program for EContactStore.
- *
- * 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 Lesser 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 Lesser 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.
- *
- * Author: Hans Petter Jansson <hpj@novell.com>
- */
-
-#include <libedataserverui/libedataserverui.h>
-
-static void
-entry_changed (GtkWidget *entry,
- EContactStore *contact_store)
-{
- const gchar *text;
- EBookQuery *query;
-
- text = gtk_entry_get_text (GTK_ENTRY (entry));
-
- query = e_book_query_any_field_contains (text);
- e_contact_store_set_query (contact_store, query);
- e_book_query_unref (query);
-}
-
-static GtkTreeViewColumn *
-create_text_column_for_field (EContactField field_id)
-{
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell_renderer;
-
- column = gtk_tree_view_column_new ();
- cell_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
- gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
- gtk_tree_view_column_set_resizable (column, TRUE);
- gtk_tree_view_column_set_title (column, e_contact_pretty_name (field_id));
- gtk_tree_view_column_add_attribute (column, cell_renderer, "text", field_id);
- gtk_tree_view_column_set_sort_column_id (column, field_id);
-
- return column;
-}
-
-static gint
-start_test (const gchar *param)
-{
- EContactStore *contact_store;
- GtkTreeModel *model_sort;
- GtkWidget *scrolled_window;
- GtkWidget *window;
- GtkWidget *tree_view;
- GtkWidget *vgrid;
- GtkWidget *entry;
- GtkTreeViewColumn *column;
- EBookClient *book_client;
- EBookQuery *book_query;
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- vgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", FALSE,
- "row-spacing", 2,
- NULL);
- gtk_container_add (GTK_CONTAINER (window), vgrid);
-
- entry = gtk_entry_new ();
- gtk_widget_set_halign (entry, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (vgrid), entry);
-
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_widget_set_hexpand (scrolled_window, TRUE);
- gtk_widget_set_halign (scrolled_window, GTK_ALIGN_FILL);
- gtk_widget_set_vexpand (scrolled_window, TRUE);
- gtk_widget_set_valign (scrolled_window, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (vgrid), scrolled_window);
-
- contact_store = e_contact_store_new ();
- model_sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (contact_store));
- tree_view = GTK_WIDGET (gtk_tree_view_new ());
- gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model_sort);
-
- column = create_text_column_for_field (E_CONTACT_FILE_AS);
- gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
-
- column = create_text_column_for_field (E_CONTACT_FULL_NAME);
- gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
-
- column = create_text_column_for_field (E_CONTACT_EMAIL_1);
- gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
-
- gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
-
-#if 0 /* ACCOUNT_MGMT */
- book_client = e_book_client_new_default (NULL);
- g_warn_if_fail (e_client_open_sync (E_CLIENT (book_client), TRUE, NULL, NULL));
- e_contact_store_add_client (contact_store, book_client);
- g_object_unref (book_client);
-#endif /* ACCOUNT_MGMT */
-
- book_query = e_book_query_any_field_contains ("");
- e_contact_store_set_query (contact_store, book_query);
- e_book_query_unref (book_query);
-
- g_signal_connect (entry, "changed", G_CALLBACK (entry_changed), contact_store);
-
- gtk_widget_show_all (window);
-
- return FALSE;
-}
-
-gint
-main (gint argc,
- gchar **argv)
-{
- const gchar *param;
-
- gtk_init (&argc, &argv);
-
- if (argc < 2)
- param = "???";
- else
- param = argv[1];
-
- g_idle_add ((GSourceFunc) start_test, (gpointer) param);
-
- gtk_main ();
-
- return 0;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* test-name-selector.c - Test for name selector components.
- *
- * 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 Lesser 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 Lesser 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.
- *
- * Author: Hans Petter Jansson <hpj@novell.com>
- */
-
-#include <camel/camel.h>
-#include <libedataserverui/libedataserverui.h>
-
-static ENameSelectorDialog *name_selector_dialog;
-static GtkWidget *name_selector_entry_window;
-
-static void
-close_dialog (GtkWidget *widget,
- gint response,
- gpointer data)
-{
- gtk_widget_destroy (GTK_WIDGET (name_selector_dialog));
- gtk_widget_destroy (name_selector_entry_window);
-
- g_timeout_add (4000, (GSourceFunc) gtk_main_quit, NULL);
-}
-
-static gboolean
-start_test (ESourceRegistry *registry)
-{
- ENameSelectorModel *name_selector_model;
- ENameSelectorEntry *name_selector_entry;
- EDestinationStore *destination_store;
- GtkWidget *container;
-
- destination_store = e_destination_store_new ();
- name_selector_model = e_name_selector_model_new ();
-
- e_name_selector_model_add_section (name_selector_model, "to", "To", destination_store);
- e_name_selector_model_add_section (name_selector_model, "cc", "Cc", NULL);
- e_name_selector_model_add_section (name_selector_model, "bcc", "Bcc", NULL);
-
- name_selector_dialog = e_name_selector_dialog_new (registry);
- e_name_selector_dialog_set_model (name_selector_dialog, name_selector_model);
- gtk_window_set_modal (GTK_WINDOW (name_selector_dialog), FALSE);
-
- name_selector_entry = e_name_selector_entry_new (registry);
- e_name_selector_entry_set_destination_store (name_selector_entry, destination_store);
-
- g_signal_connect (name_selector_dialog, "response", G_CALLBACK (close_dialog), name_selector_dialog);
- gtk_widget_show (GTK_WIDGET (name_selector_dialog));
-
- container = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_container_add (GTK_CONTAINER (container), GTK_WIDGET (name_selector_entry));
- gtk_widget_show_all (container);
-
- name_selector_entry_window = container;
-
- g_object_unref (name_selector_model);
- g_object_unref (destination_store);
- return FALSE;
-}
-
-gint
-main (gint argc,
- gchar **argv)
-{
- ESourceRegistry *registry;
- GError *error = NULL;
-
- gtk_init (&argc, &argv);
-
- camel_init (NULL, 0);
-
- registry = e_source_registry_new_sync (NULL, &error);
-
- if (error != NULL) {
- g_error (
- "Failed to load ESource registry: %s",
- error->message);
- g_assert_not_reached ();
- }
-
- g_idle_add ((GSourceFunc) start_test, registry);
-
- gtk_main ();
-
- return 0;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* test-source-combo-box.c - Test for ESourceComboBox.
- *
- * 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 Lesser 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 Lesser 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.
- *
- * Author: Ettore Perazzoli <ettore@ximian.com>
- */
-
-#include <config.h>
-#include <gtk/gtk.h>
-
-#include <libedataserverui/libedataserverui.h>
-
-static const gchar *extension_name;
-
-static void
-source_changed_cb (ESourceComboBox *combo_box)
-{
- ESource *source;
-
- source = e_source_combo_box_ref_active (combo_box);
- if (source != NULL) {
- const gchar *display_name;
- display_name = e_source_get_display_name (source);
- g_print ("source selected: \"%s\"\n", display_name);
- g_object_unref (source);
- } else {
- g_print ("source selected: (none)\n");
- }
-}
-
-static gint
-on_idle_create_widget (ESourceRegistry *registry)
-{
- GtkWidget *window;
- GtkWidget *box;
- GtkWidget *combo_box;
- GtkWidget *button;
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
- gtk_container_add (GTK_CONTAINER (window), box);
-
- combo_box = e_source_combo_box_new (registry, extension_name);
- g_signal_connect (
- combo_box, "changed",
- G_CALLBACK (source_changed_cb), NULL);
- gtk_box_pack_start (GTK_BOX (box), combo_box, FALSE, FALSE, 0);
-
- button = gtk_toggle_button_new_with_label ("Show Colors");
- gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
-
- g_object_bind_property (
- combo_box, "show-colors",
- button, "active",
- G_BINDING_SYNC_CREATE |
- G_BINDING_BIDIRECTIONAL);
-
- gtk_widget_show_all (window);
-
- return FALSE;
-}
-
-gint
-main (gint argc,
- gchar **argv)
-{
- ESourceRegistry *registry;
- GError *error = NULL;
-
- gtk_init (&argc, &argv);
-
- if (argc < 2)
- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
- else
- extension_name = argv[1];
-
- registry = e_source_registry_new_sync (NULL, &error);
-
- if (error != NULL) {
- g_error (
- "Failed to load ESource registry: %s",
- error->message);
- g_assert_not_reached ();
- }
-
- g_idle_add ((GSourceFunc) on_idle_create_widget, registry);
-
- gtk_main ();
-
- return 0;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* test-source-list-selector.c - Test program for the ESourceListSelector
- * widget.
- *
- * 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 Lesser 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 Lesser 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.
- *
- * Author: Ettore Perazzoli <ettore@ximian.com>
- */
-
-#include <libedataserverui/libedataserverui.h>
-
-static const gchar *extension_name;
-
-static void
-dump_selection (ESourceSelector *selector)
-{
- GSList *selection = e_source_selector_get_selection (selector);
-
- g_print ("Current selection:\n");
- if (selection == NULL) {
- g_print ("\t(None)\n");
- } else {
- GSList *p;
-
- for (p = selection; p != NULL; p = p->next) {
- ESource *source = E_SOURCE (p->data);
- ESourceBackend *extension;
-
- extension = e_source_get_extension (
- source, extension_name);
-
- g_print (
- "\tSource %s (backend %s)\n",
- e_source_get_display_name (source),
- e_source_backend_get_backend_name (extension));
- }
- }
-
- e_source_selector_free_selection (selection);
-}
-
-static void
-selection_changed_callback (ESourceSelector *selector)
-{
- g_print ("Selection changed!\n");
- dump_selection (selector);
-}
-
-static gint
-on_idle_create_widget (ESourceRegistry *registry)
-{
- GtkWidget *window;
- GtkWidget *vgrid;
- GtkWidget *selector;
- GtkWidget *scrolled_window;
- GtkWidget *check;
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
-
- g_signal_connect (
- window, "delete-event",
- G_CALLBACK (gtk_main_quit), NULL);
-
- vgrid = g_object_new (GTK_TYPE_GRID,
- "orientation", GTK_ORIENTATION_VERTICAL,
- "column-homogeneous", FALSE,
- "row-spacing", 6,
- NULL);
- gtk_container_add (GTK_CONTAINER (window), vgrid);
-
- selector = e_source_selector_new (registry, extension_name);
- g_signal_connect (
- selector, "selection_changed",
- G_CALLBACK (selection_changed_callback), NULL);
-
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (
- GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (
- GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
- gtk_container_add (GTK_CONTAINER (scrolled_window), selector);
- gtk_widget_set_hexpand (scrolled_window, TRUE);
- gtk_widget_set_halign (scrolled_window, GTK_ALIGN_FILL);
- gtk_widget_set_vexpand (scrolled_window, TRUE);
- gtk_widget_set_valign (scrolled_window, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (vgrid), scrolled_window);
-
- check = gtk_check_button_new_with_label ("Show colors");
- gtk_widget_set_halign (check, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (vgrid), check);
-
- g_object_bind_property (
- selector, "show-colors",
- check, "active",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-
- check = gtk_check_button_new_with_label ("Show toggles");
- gtk_widget_set_halign (check, GTK_ALIGN_FILL);
- gtk_container_add (GTK_CONTAINER (vgrid), check);
-
- g_object_bind_property (
- selector, "show-toggles",
- check, "active",
- G_BINDING_BIDIRECTIONAL |
- G_BINDING_SYNC_CREATE);
-
- gtk_widget_show_all (window);
-
- return FALSE;
-}
-
-gint
-main (gint argc,
- gchar **argv)
-{
- ESourceRegistry *registry;
- GError *error = NULL;
-
- gtk_init (&argc, &argv);
-
- if (argc < 2)
- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
- else
- extension_name = argv[1];
-
- registry = e_source_registry_new_sync (NULL, &error);
-
- if (error != NULL) {
- g_error (
- "Failed to load ESource registry: %s",
- error->message);
- g_assert_not_reached ();
- }
-
- g_idle_add ((GSourceFunc) on_idle_create_widget, registry);
-
- gtk_main ();
-
- return 0;
-}