From a61e43b262663f88c8ff66e1b522dcab56f4710a Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 10 Dec 2012 08:19:32 -0500 Subject: [PATCH] Remove libedataserverui. Evolution is the only consumer of libedataserverui. The library has been merged into Evolution's own libeutil which is not restrained by backward-compatibility promises. --- Makefile.am | 2 +- configure.ac | 28 +- docs/reference/Makefile.am | 1 - docs/reference/libedataserverui/Makefile.am | 44 - .../libedataserverui/libedataserverui-docs.sgml | 94 - .../libedataserverui-overrides.txt | 0 .../libedataserverui/libedataserverui-sections.txt | 446 --- .../libedataserverui/libedataserverui.types | 17 - libedataserverui/Makefile.am | 112 - libedataserverui/e-book-auth-util.c | 187 -- libedataserverui/e-book-auth-util.h | 49 - libedataserverui/e-categories-dialog.c | 156 - libedataserverui/e-categories-dialog.h | 73 - libedataserverui/e-categories-editor.c | 436 --- libedataserverui/e-categories-editor.h | 88 - libedataserverui/e-categories-selector.c | 589 ---- libedataserverui/e-categories-selector.h | 97 - libedataserverui/e-category-completion.c | 505 --- libedataserverui/e-category-completion.h | 72 - libedataserverui/e-category-editor.c | 343 -- libedataserverui/e-category-editor.h | 81 - libedataserverui/e-cell-renderer-color.c | 243 -- libedataserverui/e-cell-renderer-color.h | 79 - libedataserverui/e-client-utils.c | 448 --- libedataserverui/e-client-utils.h | 64 - libedataserverui/e-contact-store.c | 1370 -------- libedataserverui/e-contact-store.h | 94 - libedataserverui/e-data-server-ui-marshal.list | 3 - libedataserverui/e-destination-store.c | 751 ----- libedataserverui/e-destination-store.h | 106 - libedataserverui/e-name-selector-dialog.c | 1863 ---------- libedataserverui/e-name-selector-dialog.h | 100 - libedataserverui/e-name-selector-entry.c | 3542 -------------------- libedataserverui/e-name-selector-entry.h | 124 - libedataserverui/e-name-selector-list.c | 793 ----- libedataserverui/e-name-selector-list.h | 82 - libedataserverui/e-name-selector-model.c | 663 ---- libedataserverui/e-name-selector-model.h | 108 - libedataserverui/e-name-selector.c | 658 ---- libedataserverui/e-name-selector.h | 94 - libedataserverui/e-passwords-win32.c | 1064 ------ libedataserverui/e-passwords.c | 890 ----- libedataserverui/e-passwords.h | 81 - libedataserverui/e-source-combo-box.c | 701 ---- libedataserverui/e-source-combo-box.h | 90 - libedataserverui/e-source-selector-dialog.c | 453 --- libedataserverui/e-source-selector-dialog.h | 85 - libedataserverui/e-source-selector.c | 2085 ------------ libedataserverui/e-source-selector.h | 141 - libedataserverui/e-tree-model-generator.c | 1345 -------- libedataserverui/e-tree-model-generator.h | 104 - libedataserverui/libedataserverui.h | 50 - libedataserverui/libedataserverui.pc.in | 13 - tests/Makefile.am | 2 +- tests/libedataserverui/Makefile.am | 55 - tests/libedataserverui/evolution-source-viewer.c | 1176 ------- tests/libedataserverui/test-category-completion.c | 67 - tests/libedataserverui/test-contact-store.c | 143 - tests/libedataserverui/test-name-selector.c | 102 - tests/libedataserverui/test-source-combo-box.c | 107 - tests/libedataserverui/test-source-selector.c | 157 - 61 files changed, 9 insertions(+), 23507 deletions(-) delete mode 100644 docs/reference/libedataserverui/Makefile.am delete mode 100644 docs/reference/libedataserverui/libedataserverui-docs.sgml delete mode 100644 docs/reference/libedataserverui/libedataserverui-overrides.txt delete mode 100644 docs/reference/libedataserverui/libedataserverui-sections.txt delete mode 100644 docs/reference/libedataserverui/libedataserverui.types delete mode 100644 libedataserverui/Makefile.am delete mode 100644 libedataserverui/e-book-auth-util.c delete mode 100644 libedataserverui/e-book-auth-util.h delete mode 100644 libedataserverui/e-categories-dialog.c delete mode 100644 libedataserverui/e-categories-dialog.h delete mode 100644 libedataserverui/e-categories-editor.c delete mode 100644 libedataserverui/e-categories-editor.h delete mode 100644 libedataserverui/e-categories-selector.c delete mode 100644 libedataserverui/e-categories-selector.h delete mode 100644 libedataserverui/e-category-completion.c delete mode 100644 libedataserverui/e-category-completion.h delete mode 100644 libedataserverui/e-category-editor.c delete mode 100644 libedataserverui/e-category-editor.h delete mode 100644 libedataserverui/e-cell-renderer-color.c delete mode 100644 libedataserverui/e-cell-renderer-color.h delete mode 100644 libedataserverui/e-client-utils.c delete mode 100644 libedataserverui/e-client-utils.h delete mode 100644 libedataserverui/e-contact-store.c delete mode 100644 libedataserverui/e-contact-store.h delete mode 100644 libedataserverui/e-data-server-ui-marshal.list delete mode 100644 libedataserverui/e-destination-store.c delete mode 100644 libedataserverui/e-destination-store.h delete mode 100644 libedataserverui/e-name-selector-dialog.c delete mode 100644 libedataserverui/e-name-selector-dialog.h delete mode 100644 libedataserverui/e-name-selector-entry.c delete mode 100644 libedataserverui/e-name-selector-entry.h delete mode 100644 libedataserverui/e-name-selector-list.c delete mode 100644 libedataserverui/e-name-selector-list.h delete mode 100644 libedataserverui/e-name-selector-model.c delete mode 100644 libedataserverui/e-name-selector-model.h delete mode 100644 libedataserverui/e-name-selector.c delete mode 100644 libedataserverui/e-name-selector.h delete mode 100644 libedataserverui/e-passwords-win32.c delete mode 100644 libedataserverui/e-passwords.c delete mode 100644 libedataserverui/e-passwords.h delete mode 100644 libedataserverui/e-source-combo-box.c delete mode 100644 libedataserverui/e-source-combo-box.h delete mode 100644 libedataserverui/e-source-selector-dialog.c delete mode 100644 libedataserverui/e-source-selector-dialog.h delete mode 100644 libedataserverui/e-source-selector.c delete mode 100644 libedataserverui/e-source-selector.h delete mode 100644 libedataserverui/e-tree-model-generator.c delete mode 100644 libedataserverui/e-tree-model-generator.h delete mode 100644 libedataserverui/libedataserverui.h delete mode 100644 libedataserverui/libedataserverui.pc.in delete mode 100644 tests/libedataserverui/Makefile.am delete mode 100644 tests/libedataserverui/evolution-source-viewer.c delete mode 100644 tests/libedataserverui/test-category-completion.c delete mode 100644 tests/libedataserverui/test-contact-store.c delete mode 100644 tests/libedataserverui/test-name-selector.c delete mode 100644 tests/libedataserverui/test-source-combo-box.c delete mode 100644 tests/libedataserverui/test-source-selector.c diff --git a/Makefile.am b/Makefile.am index 8f6b082..aad317e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS=-I m4 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 diff --git a/configure.ac b/configure.ac index a9e4d2d..31995d4 100644 --- a/configure.ac +++ b/configure.ac @@ -1284,6 +1284,12 @@ dnl sqlite3 flags 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 ****************************** @@ -1294,26 +1300,10 @@ AC_SUBST(E_DATA_SERVER_CFLAGS) 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) @@ -1617,8 +1607,6 @@ libebackend/libebackend.pc 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 @@ -1639,7 +1627,6 @@ tests/libecal/Makefile tests/libecal/client/Makefile tests/libedata-cal/Makefile tests/libedataserver/Makefile -tests/libedataserverui/Makefile tests/tools/Makefile docs/Makefile docs/reference/Makefile @@ -1651,7 +1638,6 @@ docs/reference/calendar/libecal/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 diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 2d64b2c..f1f2986 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -9,7 +9,6 @@ SUBDIRS = \ calendar \ camel \ libedataserver \ - libedataserverui \ libebackend \ $(PRIVATE_DIR) \ $(NULL) diff --git a/docs/reference/libedataserverui/Makefile.am b/docs/reference/libedataserverui/Makefile.am deleted file mode 100644 index 657d0ee..0000000 --- a/docs/reference/libedataserverui/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -# 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 diff --git a/docs/reference/libedataserverui/libedataserverui-docs.sgml b/docs/reference/libedataserverui/libedataserverui-docs.sgml deleted file mode 100644 index d3684e4..0000000 --- a/docs/reference/libedataserverui/libedataserverui-docs.sgml +++ /dev/null @@ -1,94 +0,0 @@ - - -]> - - - Evolution-Data-Server Manual: Graphical Utilities (libedataserverui) - - - - Evolution-Data-Server Manual: Graphical Utilities (libedataserverui) - - - - - - - - - - - - - - - - - - - - - - - - Index - - - - Index of deprecated symbols - - - - Index of new symbols in 3.8 - - - - Index of new symbols in 3.6 - - - - Index of new symbols in 3.4 - - - - Index of new symbols in 3.2 - - - - Index of new symbols in 3.0 - - - - Index of new symbols in 2.32 - - - - Index of new symbols in 2.30 - - - - Index of new symbols in 2.28 - - - - Index of new symbols in 2.26 - - - - Index of new symbols in 2.24 - - - - Index of new symbols in 2.22 - - - - Index of new symbols in 1.12 - - - - - - diff --git a/docs/reference/libedataserverui/libedataserverui-overrides.txt b/docs/reference/libedataserverui/libedataserverui-overrides.txt deleted file mode 100644 index e69de29..0000000 diff --git a/docs/reference/libedataserverui/libedataserverui-sections.txt b/docs/reference/libedataserverui/libedataserverui-sections.txt deleted file mode 100644 index 7c5e089..0000000 --- a/docs/reference/libedataserverui/libedataserverui-sections.txt +++ /dev/null @@ -1,446 +0,0 @@ -
-e-book-auth-util -e_load_book_source_async -e_load_book_source_finish -
- -
-e-categories-dialog -ECategoriesDialog -ECategoriesDialog -e_categories_dialog_new -e_categories_dialog_get_categories -e_categories_dialog_set_categories - -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 - -ECategoriesDialogPrivate -e_categories_dialog_get_type -
- -
-e-categories-editor -ECategoriesEditor -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 - -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 - -ECategoriesEditorPrivate -e_categories_editor_get_type -
- -
-e-categories-selector -ECategoriesSelector -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 - -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 - -ECategoriesSelectorPrivate -e_categories_selector_get_type -
- -
-e-category-completion -ECategoryCompletion -ECategoryCompletion -e_category_completion_new - -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 - -ECategoryCompletionPrivate -e_category_completion_get_type -
- -
-e-category-editor -ECategoryEditor -ECategoryEditor -e_category_editor_new -e_category_editor_create_category -e_category_editor_edit_category - -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 - -ECategoryEditorPrivate -e_category_editor_get_type -
- -
-e-cell-renderer-color -ECellRendererColor -ECellRendererColor -e_cell_renderer_color_new - -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 - -ECellRendererColorPrivate -e_cell_renderer_color_get_type -
- -
-e-client-utils -EClient Utilities -EClientSourceType -e_client_utils_new -e_client_utils_open_new -e_client_utils_open_new_finish -
- -
-e-contact-store -EContactStore -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 - -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 - -EContactStorePrivate -e_contact_store_get_type -
- -
-e-destination-store -EDestinationStore -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 - -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 - -EDestinationStorePrivate -e_destination_store_get_type -
- -
-e-name-selector -ENameSelector -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 - -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 - -ENameSelectorPrivate -e_name_selector_get_type -
- -
-e-name-selector-dialog -ENameSelectorDialog -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 - -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 - -ENameSelectorDialogPrivate -e_name_selector_dialog_get_type -
- -
-e-name-selector-entry -ENameSelectorEntry -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 - -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 - -ENameSelectorEntryPrivate -e_name_selector_entry_get_type -
- -
-e-name-selector-list -ENameSelectorList -ENameSelectorList -e_name_selector_list_new -e_name_selector_list_expand_clicked - -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 - -ENameSelectorListPrivate -e_name_selector_list_get_type -
- -
-e-name-selector-model -ENameSelectorModel -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 - -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 - -ENameSelectorModelPrivate -e_name_selector_model_get_type -
- -
-e-passwords -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 -
- -
-e-source-combo-box -ESourceComboBox -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 - -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 - -ESourceComboBoxPrivate -e_source_combo_box_get_type -
- -
-e-tree-model-generator -ETreeModelGenerator -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 - -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 - -ETreeModelGeneratorPrivate -e_tree_model_generator_get_type -
- -
-e-source-selector -ESourceSelector -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 - -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 - -ESourceSelectorPrivate -e_source_selector_get_type -
- -
-e-source-selector-dialog -ESourceSelectorDialog -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 - -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 - -ESourceSelectorDialogPrivate -e_source_selector_dialog_get_type -
- diff --git a/docs/reference/libedataserverui/libedataserverui.types b/docs/reference/libedataserverui/libedataserverui.types deleted file mode 100644 index e9b198e..0000000 --- a/docs/reference/libedataserverui/libedataserverui.types +++ /dev/null @@ -1,17 +0,0 @@ -#include - -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 diff --git a/libedataserverui/Makefile.am b/libedataserverui/Makefile.am deleted file mode 100644 index aee7061..0000000 --- a/libedataserverui/Makefile.am +++ /dev/null @@ -1,112 +0,0 @@ -# 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 diff --git a/libedataserverui/e-book-auth-util.c b/libedataserverui/e-book-auth-util.c deleted file mode 100644 index 99b5973..0000000 --- a/libedataserverui/e-book-auth-util.c +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- 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 - * - * Mostly taken from Evolution's addressbook/gui/component/addressbook.c - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#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); -} diff --git a/libedataserverui/e-book-auth-util.h b/libedataserverui/e-book-auth-util.h deleted file mode 100644 index 0aea243..0000000 --- a/libedataserverui/e-book-auth-util.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef EDS_DISABLE_DEPRECATED - -#ifndef E_BOOK_AUTH_UTIL_H -#define E_BOOK_AUTH_UTIL_H - -#include -#include - -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 */ diff --git a/libedataserverui/e-categories-dialog.c b/libedataserverui/e-categories-dialog.c deleted file mode 100644 index aff1912..0000000 --- a/libedataserverui/e-categories-dialog.c +++ /dev/null @@ -1,156 +0,0 @@ -/* -*- 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 -#endif - -#include -#include -#include -#include - -#include -#include - -#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); -} diff --git a/libedataserverui/e-categories-dialog.h b/libedataserverui/e-categories-dialog.h deleted file mode 100644 index a2d0511..0000000 --- a/libedataserverui/e-categories-dialog.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef E_CATEGORIES_DIALOG_H -#define E_CATEGORIES_DIALOG_H - -#include - -/* 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 */ diff --git a/libedataserverui/e-categories-editor.c b/libedataserverui/e-categories-editor.c deleted file mode 100644 index 8cb09d4..0000000 --- a/libedataserverui/e-categories-editor.c +++ /dev/null @@ -1,436 +0,0 @@ -/* -*- 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 -#include -#include -#include -#include - -#include -#include - -#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"); -} diff --git a/libedataserverui/e-categories-editor.h b/libedataserverui/e-categories-editor.h deleted file mode 100644 index 7cdf67e..0000000 --- a/libedataserverui/e-categories-editor.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef E_CATEGORIES_EDITOR_H -#define E_CATEGORIES_EDITOR_H - -#include - -/* 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 */ diff --git a/libedataserverui/e-categories-selector.c b/libedataserverui/e-categories-selector.c deleted file mode 100644 index e2eedfa..0000000 --- a/libedataserverui/e-categories-selector.c +++ /dev/null @@ -1,589 +0,0 @@ -/* -*- 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 -#include - -#include - -#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); -} diff --git a/libedataserverui/e-categories-selector.h b/libedataserverui/e-categories-selector.h deleted file mode 100644 index ac06ac8..0000000 --- a/libedataserverui/e-categories-selector.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef E_CATEGORIES_SELECTOR_H -#define E_CATEGORIES_SELECTOR_H - -#include - -/* 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 */ diff --git a/libedataserverui/e-category-completion.c b/libedataserverui/e-category-completion.c deleted file mode 100644 index 095df50..0000000 --- a/libedataserverui/e-category-completion.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#include "e-category-completion.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include - -#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); -} diff --git a/libedataserverui/e-category-completion.h b/libedataserverui/e-category-completion.h deleted file mode 100644 index 397d47a..0000000 --- a/libedataserverui/e-category-completion.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_CATEGORY_COMPLETION_H -#define E_CATEGORY_COMPLETION_H - -#include - -/* 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 */ diff --git a/libedataserverui/e-category-editor.c b/libedataserverui/e-category-editor.c deleted file mode 100644 index 33ad6dd..0000000 --- a/libedataserverui/e-category-editor.c +++ /dev/null @@ -1,343 +0,0 @@ -/* -*- 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 -#endif - -#include -#include -#include - -#include - -#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; -} diff --git a/libedataserverui/e-category-editor.h b/libedataserverui/e-category-editor.h deleted file mode 100644 index 5ca0b1c..0000000 --- a/libedataserverui/e-category-editor.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef E_CATEGORY_EDITOR_H -#define E_CATEGORY_EDITOR_H - -#include - -/* 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 */ diff --git a/libedataserverui/e-cell-renderer-color.c b/libedataserverui/e-cell-renderer-color.c deleted file mode 100644 index 4bbb131..0000000 --- a/libedataserverui/e-cell-renderer-color.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -*- 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 -#endif - -#include "e-cell-renderer-color.h" - -#include -#include - -#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); -} diff --git a/libedataserverui/e-cell-renderer-color.h b/libedataserverui/e-cell-renderer-color.h deleted file mode 100644 index 0c3315f..0000000 --- a/libedataserverui/e-cell-renderer-color.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef _E_CELL_RENDERER_COLOR_H_ -#define _E_CELL_RENDERER_COLOR_H_ - -#include - -/* 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_ */ diff --git a/libedataserverui/e-client-utils.c b/libedataserverui/e-client-utils.c deleted file mode 100644 index 3b8a5da..0000000 --- a/libedataserverui/e-client-utils.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * 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 - * - * - * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com) - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include - -#include - -#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; -} diff --git a/libedataserverui/e-client-utils.h b/libedataserverui/e-client-utils.h deleted file mode 100644 index 3dd1230..0000000 --- a/libedataserverui/e-client-utils.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 - * - * - * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com) - * - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_CLIENT_UTILS_H -#define E_CLIENT_UTILS_H - -#include -#include - -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 */ diff --git a/libedataserverui/e-contact-store.c b/libedataserverui/e-contact-store.c deleted file mode 100644 index 4e49399..0000000 --- a/libedataserverui/e-contact-store.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#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); -} diff --git a/libedataserverui/e-contact-store.h b/libedataserverui/e-contact-store.h deleted file mode 100644 index 86dbe49..0000000 --- a/libedataserverui/e-contact-store.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_CONTACT_STORE_H -#define E_CONTACT_STORE_H - -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-data-server-ui-marshal.list b/libedataserverui/e-data-server-ui-marshal.list deleted file mode 100644 index 5b7fbe9..0000000 --- a/libedataserverui/e-data-server-ui-marshal.list +++ /dev/null @@ -1,3 +0,0 @@ -BOOLEAN:OBJECT,BOXED -BOOLEAN:BOXED,OBJECT,FLAGS,UINT -NONE:STRING,BOOLEAN diff --git a/libedataserverui/e-destination-store.c b/libedataserverui/e-destination-store.c deleted file mode 100644 index 82801f2..0000000 --- a/libedataserverui/e-destination-store.c +++ /dev/null @@ -1,751 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#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; -} diff --git a/libedataserverui/e-destination-store.h b/libedataserverui/e-destination-store.h deleted file mode 100644 index 3d18b87..0000000 --- a/libedataserverui/e-destination-store.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_DESTINATION_STORE_H -#define E_DESTINATION_STORE_H - -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-name-selector-dialog.c b/libedataserverui/e-name-selector-dialog.c deleted file mode 100644 index ece556b..0000000 --- a/libedataserverui/e-name-selector-dialog.c +++ /dev/null @@ -1,1863 +0,0 @@ -/* -*- 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 - */ - -#ifdef GTK_DISABLE_DEPRECATED -#undef GTK_DISABLE_DEPRECATED -#endif - -#include -#include -#include -#include - -#include -#include - -#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 ("", _("Show Contacts"), "", 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 ("", _("Co_ntacts"), "", 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)); -} - diff --git a/libedataserverui/e-name-selector-dialog.h b/libedataserverui/e-name-selector-dialog.h deleted file mode 100644 index 3d1e28c..0000000 --- a/libedataserverui/e-name-selector-dialog.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_NAME_SELECTOR_DIALOG_H -#define E_NAME_SELECTOR_DIALOG_H - -#include -#include - -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-name-selector-entry.c b/libedataserverui/e-name-selector-entry.c deleted file mode 100644 index 87a6b31..0000000 --- a/libedataserverui/e-name-selector-entry.c +++ /dev/null @@ -1,3542 +0,0 @@ -/* -*- 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 - */ - -#include -#include -#include - -#include -#include - -#include - -#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 - * 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; -} diff --git a/libedataserverui/e-name-selector-entry.h b/libedataserverui/e-name-selector-entry.h deleted file mode 100644 index 1ceb5e0..0000000 --- a/libedataserverui/e-name-selector-entry.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_NAME_SELECTOR_ENTRY_H -#define E_NAME_SELECTOR_ENTRY_H - -#include -#include - -#include -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-name-selector-list.c b/libedataserverui/e-name-selector-list.c deleted file mode 100644 index 43c9dc9..0000000 --- a/libedataserverui/e-name-selector-list.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * 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 - * - * - * Authors: - * Srinivasa Ragavan - * Devashish Sharma - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#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); -} diff --git a/libedataserverui/e-name-selector-list.h b/libedataserverui/e-name-selector-list.h deleted file mode 100644 index 0dd4234..0000000 --- a/libedataserverui/e-name-selector-list.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 - * - * - * Authors: - * Srinivasa Ragavan - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_NAME_SELECTOR_LIST_H -#define E_NAME_SELECTOR_LIST_H - -#include -#include - -#include -#include -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-name-selector-model.c b/libedataserverui/e-name-selector-model.c deleted file mode 100644 index 770f514..0000000 --- a/libedataserverui/e-name-selector-model.c +++ /dev/null @@ -1,663 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#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); -} diff --git a/libedataserverui/e-name-selector-model.h b/libedataserverui/e-name-selector-model.h deleted file mode 100644 index ac86ed4..0000000 --- a/libedataserverui/e-name-selector-model.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_NAME_SELECTOR_MODEL_H -#define E_NAME_SELECTOR_MODEL_H - -#include -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-name-selector.c b/libedataserverui/e-name-selector.c deleted file mode 100644 index 90575df..0000000 --- a/libedataserverui/e-name-selector.c +++ /dev/null @@ -1,658 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include - -#include -#include -#include -#include -#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; -} diff --git a/libedataserverui/e-name-selector.h b/libedataserverui/e-name-selector.h deleted file mode 100644 index 40ad1f9..0000000 --- a/libedataserverui/e-name-selector.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_NAME_SELECTOR_H -#define E_NAME_SELECTOR_H - -#include - -#include -#include -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-passwords-win32.c b/libedataserverui/e-passwords-win32.c deleted file mode 100644 index 51c0cb2..0000000 --- a/libedataserverui/e-passwords-win32.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* -*- 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 -#include -#include -#include -#include - -#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 ( - "%s", (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; -} diff --git a/libedataserverui/e-passwords.c b/libedataserverui/e-passwords.c deleted file mode 100644 index bf4cfc1..0000000 --- a/libedataserverui/e-passwords.c +++ /dev/null @@ -1,890 +0,0 @@ -/* -*- 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 -#include -#include -#include -#include - -/* XXX Yeah, yeah... */ -#define SECRET_API_SUBJECT_TO_CHANGE - -#include - -#include - -#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 ( - "%s", (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; -} diff --git a/libedataserverui/e-passwords.h b/libedataserverui/e-passwords.h deleted file mode 100644 index 0c3b857..0000000 --- a/libedataserverui/e-passwords.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 should be included directly." -#endif - -#ifndef EDS_DISABLE_DEPRECATED - -#ifndef _E_PASSWORD_H_ -#define _E_PASSWORD_H_ - -#include - -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 */ diff --git a/libedataserverui/e-source-combo-box.c b/libedataserverui/e-source-combo-box.c deleted file mode 100644 index d8d2273..0000000 --- a/libedataserverui/e-source-combo-box.c +++ /dev/null @@ -1,701 +0,0 @@ -/* -*- 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 -#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); -} - diff --git a/libedataserverui/e-source-combo-box.h b/libedataserverui/e-source-combo-box.h deleted file mode 100644 index 94d92e7..0000000 --- a/libedataserverui/e-source-combo-box.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- 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 should be included directly." -#endif - -#ifndef E_SOURCE_COMBO_BOX_H -#define E_SOURCE_COMBO_BOX_H - -#include -#include - -#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 */ diff --git a/libedataserverui/e-source-selector-dialog.c b/libedataserverui/e-source-selector-dialog.c deleted file mode 100644 index 68e29fd..0000000 --- a/libedataserverui/e-source-selector-dialog.c +++ /dev/null @@ -1,453 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#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 ("%s", _("_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; -} diff --git a/libedataserverui/e-source-selector-dialog.h b/libedataserverui/e-source-selector-dialog.h deleted file mode 100644 index 3ebb3b7..0000000 --- a/libedataserverui/e-source-selector-dialog.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_SOURCE_SELECTOR_DIALOG_H -#define E_SOURCE_SELECTOR_DIALOG_H - -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-source-selector.c b/libedataserverui/e-source-selector.c deleted file mode 100644 index 78ef4ab..0000000 --- a/libedataserverui/e-source-selector.c +++ /dev/null @@ -1,2085 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#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); -} - diff --git a/libedataserverui/e-source-selector.h b/libedataserverui/e-source-selector.h deleted file mode 100644 index c595218..0000000 --- a/libedataserverui/e-source-selector.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_SOURCE_SELECTOR_H -#define E_SOURCE_SELECTOR_H - -#include -#include - -/* 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 */ diff --git a/libedataserverui/e-tree-model-generator.c b/libedataserverui/e-tree-model-generator.c deleted file mode 100644 index aff9129..0000000 --- a/libedataserverui/e-tree-model-generator.c +++ /dev/null @@ -1,1345 +0,0 @@ -/* -*- 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 - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#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); -} diff --git a/libedataserverui/e-tree-model-generator.h b/libedataserverui/e-tree-model-generator.h deleted file mode 100644 index 3e693e8..0000000 --- a/libedataserverui/e-tree-model-generator.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- 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 - */ - -#if !defined (__LIBEDATASERVERUI_H_INSIDE__) && !defined (LIBEDATASERVERUI_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_TREE_MODEL_GENERATOR_H -#define E_TREE_MODEL_GENERATOR_H - -#include - -/* 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 */ diff --git a/libedataserverui/libedataserverui.h b/libedataserverui/libedataserverui.h deleted file mode 100644 index 32865a1..0000000 --- a/libedataserverui/libedataserverui.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 - * - */ - -#ifndef LIBEDATASERVERUI_H -#define LIBEDATASERVERUI_H - -#define __LIBEDATASERVERUI_H_INSIDE__ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef __LIBEDATASERVERUI_H_INSIDE__ - -#endif /* LIBEDATASERVERUI_H */ - diff --git a/libedataserverui/libedataserverui.pc.in b/libedataserverui/libedataserverui.pc.in deleted file mode 100644 index c2ad8b6..0000000 --- a/libedataserverui/libedataserverui.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -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} diff --git a/tests/Makefile.am b/tests/Makefile.am index 46f96be..6c5f457 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = libedataserver libedataserverui libebook libecal libedata-cal tools +SUBDIRS = libedataserver libebook libecal libedata-cal tools @GNOME_CODE_COVERAGE_RULES@ diff --git a/tests/libedataserverui/Makefile.am b/tests/libedataserverui/Makefile.am deleted file mode 100644 index f22b917..0000000 --- a/tests/libedataserverui/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -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 diff --git a/tests/libedataserverui/evolution-source-viewer.c b/tests/libedataserverui/evolution-source-viewer.c deleted file mode 100644 index e90cb6c..0000000 --- a/tests/libedataserverui/evolution-source-viewer.c +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * 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 - * - */ - -#include -#include -#include - -#include - -/* 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; -} diff --git a/tests/libedataserverui/test-category-completion.c b/tests/libedataserverui/test-category-completion.c deleted file mode 100644 index 2a11385..0000000 --- a/tests/libedataserverui/test-category-completion.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 - -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; -} diff --git a/tests/libedataserverui/test-contact-store.c b/tests/libedataserverui/test-contact-store.c deleted file mode 100644 index eeb4ed1..0000000 --- a/tests/libedataserverui/test-contact-store.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- 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 - */ - -#include - -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; -} diff --git a/tests/libedataserverui/test-name-selector.c b/tests/libedataserverui/test-name-selector.c deleted file mode 100644 index c566471..0000000 --- a/tests/libedataserverui/test-name-selector.c +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- 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 - */ - -#include -#include - -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; -} diff --git a/tests/libedataserverui/test-source-combo-box.c b/tests/libedataserverui/test-source-combo-box.c deleted file mode 100644 index 93076b2..0000000 --- a/tests/libedataserverui/test-source-combo-box.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- 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 - */ - -#include -#include - -#include - -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; -} diff --git a/tests/libedataserverui/test-source-selector.c b/tests/libedataserverui/test-source-selector.c deleted file mode 100644 index db4a1e7..0000000 --- a/tests/libedataserverui/test-source-selector.c +++ /dev/null @@ -1,157 +0,0 @@ -/* -*- 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 - */ - -#include - -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; -} -- 2.7.4