[Commits] [SCM] claws branch, master, updated. 3.16.0-107-gf25722a
wwp at claws-mail.org
wwp at claws-mail.org
Tue Apr 10 00:25:32 CEST 2018
The branch, master has been updated
via f25722af77b9378ce0fcfb4c3d09b9bd3c01902a (commit)
from a5b4afcf66c7f86f4d3b6ce9a5a792ea124541fd (commit)
Summary of changes:
src/Makefile.am | 2 +
src/addressbook.c | 58 ++++++-
src/addressbook.h | 5 +
src/addrmerge.c | 496 +++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 555 insertions(+), 6 deletions(-)
create mode 100644 src/addrmerge.c
- Log -----------------------------------------------------------------
commit f25722af77b9378ce0fcfb4c3d09b9bd3c01902a
Author: wwp <wwp at free.fr>
Date: Tue Apr 10 00:23:14 2018 +0200
Add a basic contact merging feature to the address book, thanks to
Charles Lehner <cel at celehner.com>.
Closes bug 3346: Contact merging
diff --git a/src/Makefile.am b/src/Makefile.am
index d4eafbc..460c182 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,7 @@ orig_abook_source = \
addrquery.c \
addrselect.c \
addrduplicates.c \
+ addrmerge.c \
browseldap.c \
editaddress.c \
editaddress_other_attributes_ldap.c \
@@ -93,6 +94,7 @@ abook_headers = \
addrquery.h \
addrselect.h \
addrduplicates.h \
+ addrmerge.h \
browseldap.h \
editaddress.h \
editaddress_other_attributes_ldap.h \
diff --git a/src/addressbook.c b/src/addressbook.c
index 77c3b65..30adcce 100644
--- a/src/addressbook.c
+++ b/src/addressbook.c
@@ -57,6 +57,7 @@
#include "addrcache.h"
#include "addrbook.h"
#include "addrindex.h"
+#include "addrmerge.h"
#include "addressadd.h"
#include "addrduplicates.h"
#include "addressbook_foldersel.h"
@@ -306,10 +307,6 @@ static void addressbook_folder_load_one_person (GtkCMCTree *clist,
ItemPerson *person,
AddressTypeControlItem *atci,
AddressTypeControlItem *atciMail);
-static void addressbook_folder_refresh_one_person(GtkCMCTree *clist,
- ItemPerson *person);
-static void addressbook_folder_remove_one_person(GtkCMCTree *clist,
- ItemPerson *person);
static void addressbook_folder_remove_node (GtkCMCTree *clist,
GtkCMCTreeNode *node);
@@ -352,6 +349,7 @@ static void addressbook_treenode_copy_cb ( GtkAction *action, gpointer data );
static void addressbook_treenode_paste_cb ( GtkAction *action, gpointer data );
static void addressbook_mail_to_cb ( GtkAction *action, gpointer data );
+static void addressbook_merge_cb ( GtkAction *action, gpointer data );
#ifdef USE_LDAP
static void addressbook_browse_entry_cb ( GtkAction *action, gpointer data );
@@ -442,6 +440,7 @@ static GtkActionEntry addressbook_entries[] =
{"Address/NewGroup", NULL, N_("New _Group"), "<control>G", NULL, G_CALLBACK(addressbook_new_group_cb) },
/* {"Address/---", NULL, "---", NULL, NULL, NULL }, */
{"Address/Mailto", NULL, N_("_Mail To"), "<control>M", NULL, G_CALLBACK(addressbook_mail_to_cb) },
+ {"Address/Merge", NULL, N_("_Merge"), "<control>E", NULL, G_CALLBACK(addressbook_merge_cb) },
/* Tools menu */
@@ -494,6 +493,7 @@ static GtkActionEntry addressbook_list_popup_entries[] =
#ifdef USE_LDAP
{"ABListPopup/BrowseEntry", NULL, N_("_Browse Entry"), NULL, NULL, G_CALLBACK(addressbook_browse_entry_cb) },
#endif
+ {"ABListPopup/Merge", NULL, N_("_Merge"), NULL, NULL, G_CALLBACK(addressbook_merge_cb) },
};
/**
@@ -978,6 +978,7 @@ static void addressbook_create(void)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "NewGroup", "Address/NewGroup", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Separator4", "Address/---", GTK_UI_MANAGER_SEPARATOR)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Mailto", "Address/Mailto", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Address", "Merge", "Address/Merge", GTK_UI_MANAGER_MENUITEM)
/* Tools menu */
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Tools", "ImportLDIF", "Tools/ImportLDIF", GTK_UI_MANAGER_MENUITEM)
@@ -1281,6 +1282,7 @@ static void addressbook_create(void)
#ifdef USE_LDAP
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "BrowseEntry", "ABListPopup/BrowseEntry", GTK_UI_MANAGER_MENUITEM)
#endif
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Merge", "ABListPopup/Merge", GTK_UI_MANAGER_MENUITEM)
list_popup = gtk_menu_item_get_submenu(GTK_MENU_ITEM(
gtk_ui_manager_get_widget(ui_manager, "/Popups/ABListPopup")));
@@ -1797,6 +1799,7 @@ static void addressbook_menubar_set_sensitive( gboolean sensitive ) {
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/NewAddress", sensitive );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/NewGroup", sensitive );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Mailto", sensitive );
+ cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Merge", sensitive );
gtk_widget_set_sensitive( addrbook.edit_btn, sensitive );
gtk_widget_set_sensitive( addrbook.del_btn, sensitive );
}
@@ -1985,12 +1988,16 @@ static void addressbook_list_menu_setup( void ) {
AdapterDSource *ads = NULL;
AddressInterface *iface = NULL;
AddressDataSource *ds = NULL;
+ GList *list;
+ AddrItemObject *aio;
+ AddrSelectItem *item;
gboolean canEdit = FALSE;
gboolean canDelete = FALSE;
gboolean canCut = FALSE;
gboolean canCopy = FALSE;
gboolean canPaste = FALSE;
gboolean canBrowse = FALSE;
+ gboolean canMerge = FALSE;
pobj = gtk_cmctree_node_get_row_data( GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected );
if( pobj == NULL ) return;
@@ -2068,11 +2075,23 @@ static void addressbook_list_menu_setup( void ) {
canBrowse = FALSE;
}
+ /* Allow merging persons or emails are selected */
+ list = _addressSelect_->listSelect;
+ if (list && list->next ) {
+ item = list->data;
+ aio = ( AddrItemObject * ) item->addressItem;
+ if( aio->type == ITEMTYPE_EMAIL ||
+ aio->type == ITEMTYPE_PERSON ) {
+ canMerge = TRUE;
+ }
+ }
+
/* Forbid write changes when read-only */
if( iface && iface->readOnly ) {
canCut = FALSE;
canDelete = FALSE;
canPaste = FALSE;
+ canMerge = FALSE;
}
/* Now go finalize menu items */
@@ -2084,6 +2103,7 @@ static void addressbook_list_menu_setup( void ) {
cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Paste", canPaste );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Mailto", canCopy );
+ cm_menu_set_sensitive_full( addrbook.ui_manager, "Popups/ABListPopup/Merge", canMerge );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Cut", canCut );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Copy", canCopy );
@@ -2092,6 +2112,7 @@ static void addressbook_list_menu_setup( void ) {
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Edit", canEdit );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Delete", canDelete );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Mailto", canCopy );
+ cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Address/Merge", canMerge );
gtk_widget_set_sensitive( addrbook.edit_btn, canEdit );
gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
@@ -2371,6 +2392,31 @@ static void addressbook_mail_to_cb( GtkAction *action, gpointer data ) {
}
}
+static void addressbook_merge_list( AddrSelectList *list ) {
+ GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
+ GtkCMCTree *clist = GTK_CMCTREE(addrbook.clist);
+ AddressObject *pobj;
+ AddressDataSource *ds = NULL;
+
+ pobj = gtk_cmctree_node_get_row_data(ctree, addrbook.opened );
+ cm_return_if_fail(pobj != NULL);
+
+ ds = addressbook_find_datasource( addrbook.treeSelected );
+ if( ds == NULL ) return;
+
+ addrmerge_merge(clist, pobj, ds, list);
+}
+
+/**
+ * Merge selected entries in the address list
+ */
+static void addressbook_merge_cb( GtkAction *action, gpointer data ) {
+ if( addrselect_test_empty( _addressSelect_ ) )
+ return;
+
+ addressbook_merge_list( _addressSelect_ );
+}
+
static void addressbook_list_row_selected( GtkCMCTree *clist,
GtkCMCTreeNode *node,
gint column,
@@ -3739,7 +3785,7 @@ static void addressbook_folder_remove_node( GtkCMCTree *clist, GtkCMCTreeNode *n
addrbook.treeSelected );
}
-static void addressbook_folder_refresh_one_person( GtkCMCTree *clist, ItemPerson *person ) {
+void addressbook_folder_refresh_one_person( GtkCMCTree *clist, ItemPerson *person ) {
AddressTypeControlItem *atci = addrbookctl_lookup( ADDR_ITEM_PERSON );
AddressTypeControlItem *atciMail = addrbookctl_lookup( ADDR_ITEM_EMAIL );
GtkCMCTreeNode *node;
@@ -3761,7 +3807,7 @@ static void addressbook_folder_refresh_one_person( GtkCMCTree *clist, ItemPerson
}
}
-static void addressbook_folder_remove_one_person( GtkCMCTree *clist, ItemPerson *person ) {
+void addressbook_folder_remove_one_person( GtkCMCTree *clist, ItemPerson *person ) {
GtkCMCTreeNode *node;
if( person == NULL ) return;
diff --git a/src/addressbook.h b/src/addressbook.h
index ce5c707..beb92cd 100644
--- a/src/addressbook.h
+++ b/src/addressbook.h
@@ -60,5 +60,10 @@ void addressbook_refresh( void );
gchar *addressbook_set_col_name_guard(gchar *value);
void addressbook_reflect_prefs_pixmap_theme(void);
+void addressbook_folder_refresh_one_person(GtkCMCTree *clist,
+ ItemPerson *person);
+void addressbook_folder_remove_one_person(GtkCMCTree *clist,
+ ItemPerson *person);
+
#endif /* __ADDRESSBOOK_H__ */
diff --git a/src/addrmerge.c b/src/addrmerge.c
new file mode 100644
index 0000000..363bab7
--- /dev/null
+++ b/src/addrmerge.c
@@ -0,0 +1,496 @@
+/* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2014 Charles Lehner and the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "defs.h"
+
+#ifdef USE_LDAP
+#include "ldapserver.h"
+#include "ldapupdate.h"
+#endif
+#include "addrbook.h"
+#include "addressbook.h"
+#include "addressitem.h"
+#include "addrmerge.h"
+#include "alertpanel.h"
+#include "gtkutils.h"
+#include "utils.h"
+#include "prefs_common.h"
+
+enum
+{
+ COL_DISPLAYNAME,
+ COL_FIRSTNAME,
+ COL_LASTNAME,
+ COL_NICKNAME,
+ N_NAME_COLS
+};
+
+enum
+{
+ SET_ICON,
+ SET_PERSON,
+ N_SET_COLUMNS
+};
+
+static void addrmerge_done(struct AddrMergePage *page)
+{
+ g_list_free(page->emails);
+ g_list_free(page->persons);
+ gtk_widget_destroy(GTK_WIDGET(page->dialog));
+ g_free(page);
+}
+
+static void addrmerge_do_merge(struct AddrMergePage *page)
+{
+ GList *node;
+ ItemEMail *email;
+ ItemPerson *person;
+ ItemPerson *target = page->target;
+ ItemPerson *nameTarget = page->nameTarget;
+
+ gtk_cmclist_freeze(GTK_CMCLIST(page->clist));
+
+ /* Update target name */
+ if (nameTarget && nameTarget != target) {
+ target->status = UPDATE_ENTRY;
+ addritem_person_set_first_name( target, nameTarget->firstName );
+ addritem_person_set_last_name( target, nameTarget->lastName );
+ addritem_person_set_nick_name( target, nameTarget->nickName );
+ addritem_person_set_common_name( target, ADDRITEM_NAME(nameTarget ));
+ }
+
+ /* Merge emails into target */
+ for (node = page->emails; node; node = node->next) {
+ email = node->data;
+ person = ( ItemPerson * ) ADDRITEM_PARENT(email);
+ /* Remove the email from the person */
+ email = addrbook_person_remove_email( page->abf, person, email );
+ if( email ) {
+ addrcache_remove_email( page->abf->addressCache, email );
+ /* Add the email to the target */
+ addrcache_person_add_email( page->abf->addressCache, target, email );
+ }
+ person->status = UPDATE_ENTRY;
+ addressbook_folder_refresh_one_person( page->clist, person );
+ }
+
+ /* Merge persons into target */
+ for (node = page->persons; node; node = node->next) {
+ GList *nodeE, *nodeA;
+ person = node->data;
+
+ if (person == target) continue;
+ person->status = DELETE_ENTRY;
+
+ /* Move all emails to the target */
+ for (nodeE = person->listEMail; nodeE; nodeE = nodeE->next) {
+ email = nodeE->data;
+ addritem_person_add_email( target, email );
+ }
+ g_list_free( person->listEMail );
+ person->listEMail = NULL;
+
+ /* Move all attributes to the target */
+ for (nodeA = person->listAttrib; nodeA; nodeA = nodeA->next) {
+ UserAttribute *attrib = nodeA->data;
+ addritem_person_add_attribute( target, attrib );
+ }
+ g_list_free( person->listAttrib );
+ person->listAttrib = NULL;
+
+ /* Remove the person */
+ addrselect_list_remove( page->addressSelect, (AddrItemObject *)person );
+ addressbook_folder_remove_one_person( page->clist, person );
+ if (page->pobj->type == ADDR_ITEM_FOLDER)
+ addritem_folder_remove_person(ADAPTER_FOLDER(page->pobj)->itemFolder, person);
+ person = addrbook_remove_person( page->abf, person );
+
+ if( person ) {
+ gchar *filename = addritem_person_get_picture(person);
+ if ((strcmp2(person->picture, target->picture) &&
+ filename && is_file_exist(filename)))
+ claws_unlink(filename);
+ if (filename)
+ g_free(filename);
+ addritem_free_item_person( person );
+ }
+ }
+
+ addressbook_folder_refresh_one_person( page->clist, target );
+
+ addrbook_set_dirty( page->abf, TRUE );
+ addressbook_export_to_file();
+
+#ifdef USE_LDAP
+ if (page->ds && page->ds->type == ADDR_IF_LDAP) {
+ LdapServer *server = page->ds->rawDataSource;
+ ldapsvr_set_modified(server, TRUE);
+ ldapsvr_update_book(server, NULL);
+ }
+#endif
+ gtk_cmclist_thaw(GTK_CMCLIST(page->clist));
+
+ addrmerge_done(page);
+}
+
+static void addrmerge_dialog_cb(GtkWidget* widget, gint action, gpointer data) {
+ struct AddrMergePage* page = data;
+
+ if (action != GTK_RESPONSE_ACCEPT)
+ return addrmerge_done(page);
+
+ addrmerge_do_merge(page);
+}
+
+static void addrmerge_update_dialog_sensitive( struct AddrMergePage *page )
+{
+ gboolean canMerge = (page->target && page->nameTarget);
+ gtk_dialog_set_response_sensitive( GTK_DIALOG(page->dialog),
+ GTK_RESPONSE_ACCEPT, canMerge );
+}
+
+static void addrmerge_name_selected( GtkCMCList *clist, gint row, gint column, GdkEvent *event, struct AddrMergePage *page )
+{
+ ItemPerson *person = gtk_cmclist_get_row_data( clist, row );
+ page->nameTarget = person;
+ addrmerge_update_dialog_sensitive(page);
+}
+
+static void addrmerge_picture_selected(GtkTreeView *treeview,
+ struct AddrMergePage *page)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GList *list;
+ ItemPerson *pictureTarget;
+
+ /* Get selected picture target */
+ model = gtk_icon_view_get_model(GTK_ICON_VIEW(page->iconView));
+ list = gtk_icon_view_get_selected_items(GTK_ICON_VIEW(page->iconView));
+ page->target = NULL;
+ if (list != NULL) {
+ if (gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data)) {
+ gtk_tree_model_get(model, &iter,
+ SET_PERSON, &pictureTarget,
+ -1);
+ page->target = pictureTarget;
+ }
+
+ gtk_tree_path_free(list->data);
+ g_list_free(list);
+ }
+ addrmerge_update_dialog_sensitive(page);
+}
+
+static void addrmerge_prompt( struct AddrMergePage *page )
+{
+ GtkWidget *dialog;
+ GtkWidget *frame;
+ GtkWidget *mvbox, *vbox, *hbox;
+ GtkWidget *label;
+ GtkWidget *iconView = NULL;
+ GtkWidget *namesList = NULL;
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+ GtkListStore *store = NULL;
+ GtkTreeIter iter;
+ GList *node;
+ ItemPerson *person;
+ GError *error = NULL;
+ gchar *msg, *label_msg;
+
+ dialog = page->dialog = gtk_dialog_new_with_buttons (
+ _("Merge addresses"),
+ GTK_WINDOW(mainwin->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ "_Merge",
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ g_signal_connect ( dialog, "response",
+ G_CALLBACK(addrmerge_dialog_cb), page);
+
+ mvbox = gtk_vbox_new(FALSE, 4);
+ gtk_container_add(GTK_CONTAINER(
+ gtk_dialog_get_content_area(GTK_DIALOG(dialog))), mvbox);
+ gtk_container_set_border_width(GTK_CONTAINER(mvbox), 8);
+ hbox = gtk_hbox_new(FALSE, 4);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 8);
+ gtk_box_pack_start(GTK_BOX(mvbox),
+ hbox, FALSE, FALSE, 0);
+
+ msg = page->pickPicture || page->pickName ?
+ _("Merging %u contacts." ) :
+ _("Really merge these %u contacts?" );
+ label_msg = g_strdup_printf(msg,
+ g_list_length(page->addressSelect->listSelect));
+ label = gtk_label_new( label_msg );
+ gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ g_free(label_msg);
+
+ if (page->pickPicture) {
+ GtkWidget *scrollwinPictures;
+
+ store = gtk_list_store_new(N_SET_COLUMNS,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_POINTER,
+ -1);
+ gtk_list_store_clear(store);
+
+ vbox = gtkut_get_options_frame(mvbox, &frame,
+ _("Keep which picture?"));
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
+
+ scrollwinPictures = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(scrollwinPictures), 1);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwinPictures),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwinPictures),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (vbox), scrollwinPictures, FALSE, FALSE, 0);
+ gtk_widget_set_size_request(scrollwinPictures, 464, 192);
+
+ iconView = gtk_icon_view_new_with_model(GTK_TREE_MODEL(store));
+ gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(iconView), GTK_SELECTION_SINGLE);
+ gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(iconView), SET_ICON);
+ gtk_container_add(GTK_CONTAINER(scrollwinPictures), GTK_WIDGET(iconView));
+ g_signal_connect(G_OBJECT(iconView), "selection-changed",
+ G_CALLBACK(addrmerge_picture_selected), page);
+
+ /* Add pictures from persons */
+ for (node = page->persons; node; node = node->next) {
+ gchar *filename;
+ person = node->data;
+ filename = addritem_person_get_picture(person);
+ if (filename && is_file_exist(filename)) {
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
+
+ pixbuf = gdk_pixbuf_new_from_file(filename, &error);
+ if (error) {
+ debug_print("Failed to read image: \n%s",
+ error->message);
+ g_error_free(error);
+ continue;
+ }
+
+ image = gtk_image_new();
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf);
+
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ SET_ICON, pixbuf,
+ SET_PERSON, person,
+ -1);
+ }
+ if (filename)
+ g_free(filename);
+ }
+ }
+
+ if (page->pickName) {
+ GtkWidget *scrollwinNames;
+ gchar *name_titles[N_NAME_COLS];
+
+ name_titles[COL_DISPLAYNAME] = _("Display Name");
+ name_titles[COL_FIRSTNAME] = _("First Name");
+ name_titles[COL_LASTNAME] = _("Last Name");
+ name_titles[COL_NICKNAME] = _("Nickname");
+
+ store = gtk_list_store_new(N_SET_COLUMNS,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_POINTER,
+ -1);
+ gtk_list_store_clear(store);
+
+ vbox = gtkut_get_options_frame(mvbox, &frame,
+ _("Keep which name?"));
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
+
+ scrollwinNames = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(scrollwinNames), 1);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwinNames),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwinNames),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(scrollwinNames), FALSE, FALSE, 0);
+
+ namesList = gtk_cmclist_new_with_titles(N_NAME_COLS, name_titles);
+ gtk_widget_set_can_focus(GTK_CMCLIST(namesList)->column[0].button, FALSE);
+ gtk_cmclist_set_selection_mode(GTK_CMCLIST(namesList), GTK_SELECTION_BROWSE);
+ gtk_cmclist_set_column_width(GTK_CMCLIST(namesList), COL_DISPLAYNAME, 164);
+
+ gtk_container_add(GTK_CONTAINER(scrollwinNames), namesList);
+
+ /* Add names from persons */
+ for (node = page->persons; node; node = node->next) {
+ int row;
+ person = node->data;
+ gchar *text[N_NAME_COLS];
+ text[COL_DISPLAYNAME] = ADDRITEM_NAME(person);
+ text[COL_FIRSTNAME] = person->firstName;
+ text[COL_LASTNAME] = person->lastName;
+ text[COL_NICKNAME] = person->nickName;
+ row = gtk_cmclist_insert( GTK_CMCLIST(namesList), -1, text );
+ gtk_cmclist_set_row_data( GTK_CMCLIST(namesList), row, person );
+ }
+
+ g_signal_connect(G_OBJECT(namesList), "select_row",
+ G_CALLBACK(addrmerge_name_selected), page);
+ }
+
+ page->iconView = iconView;
+ page->namesList = namesList;
+
+ addrmerge_update_dialog_sensitive(page);
+ gtk_widget_show_all(dialog);
+}
+
+void addrmerge_merge(
+ GtkCMCTree *clist,
+ AddressObject *pobj,
+ AddressDataSource *ds,
+ AddrSelectList *list)
+{
+ struct AddrMergePage* page;
+ AdapterDSource *ads = NULL;
+ AddressBookFile *abf;
+ gboolean procFlag;
+ GList *node;
+ AddrSelectItem *item;
+ AddrItemObject *aio;
+ ItemPerson *person, *target = NULL, *nameTarget = NULL;
+ GList *persons = NULL, *emails = NULL;
+ gboolean pickPicture = FALSE, pickName = FALSE;
+
+ /* Test for read only */
+ if( ds->interface->readOnly ) {
+ alertpanel( _("Merge addresses"),
+ _("This address data is readonly and cannot be deleted."),
+ GTK_STOCK_CLOSE, NULL, NULL, ALERTFOCUS_FIRST );
+ return;
+ }
+
+ /* Test whether Ok to proceed */
+ procFlag = FALSE;
+ if( pobj->type == ADDR_DATASOURCE ) {
+ ads = ADAPTER_DSOURCE(pobj);
+ if( ads->subType == ADDR_BOOK ) procFlag = TRUE;
+ }
+ else if( pobj->type == ADDR_ITEM_FOLDER ) {
+ procFlag = TRUE;
+ }
+ else if( pobj->type == ADDR_ITEM_GROUP ) {
+ procFlag = TRUE;
+ }
+ if( ! procFlag ) return;
+ abf = ds->rawDataSource;
+ if( abf == NULL ) return;
+
+ /* Gather selected persons and emails */
+ for (node = list->listSelect; node; node = node->next) {
+ item = node->data;
+ aio = ( AddrItemObject * ) item->addressItem;
+ if( aio->type == ITEMTYPE_EMAIL ) {
+ emails = g_list_prepend(emails, aio);
+ } else if( aio->type == ITEMTYPE_PERSON ) {
+ persons = g_list_prepend(persons, aio);
+ }
+ }
+
+ /* Check if more than one person has a picture */
+ for (node = persons; node; node = node->next) {
+ gchar *filename;
+ person = node->data;
+ filename = addritem_person_get_picture(person);
+ if (filename && is_file_exist(filename)) {
+ if (target == NULL) {
+ target = person;
+ } else {
+ pickPicture = TRUE;
+ target = NULL;
+ break;
+ }
+ }
+ if (filename)
+ g_free(filename);
+ }
+ if (pickPicture || target) {
+ /* At least one person had a picture */
+ } else if (persons && persons->data) {
+ /* No person had a picture. Use the first person as target */
+ target = persons->data;
+ } else {
+ /* No persons in list. Abort */
+ goto abort;
+ }
+
+ /* Pick which name to keep */
+ for (node = persons; node; node = node->next) {
+ person = node->data;
+ if (nameTarget == NULL) {
+ nameTarget = person;
+ } else if (nameTarget == person) {
+ continue;
+ } else if (strcmp2(person->firstName, nameTarget->firstName) ||
+ strcmp2(person->lastName, nameTarget->lastName) ||
+ strcmp2(person->nickName, nameTarget->nickName) ||
+ strcmp2(ADDRITEM_NAME(person), ADDRITEM_NAME(nameTarget))) {
+ pickName = TRUE;
+ break;
+ }
+ }
+ if (!nameTarget) {
+ /* No persons in list */
+ goto abort;
+ }
+
+ /* Create object */
+ page = g_new0(struct AddrMergePage, 1);
+ page->pickPicture = pickPicture;
+ page->pickName = pickName;
+ page->target = target;
+ page->nameTarget = nameTarget;
+ page->addressSelect = list;
+ page->persons = persons;
+ page->emails = emails;
+ page->clist = clist;
+ page->pobj = pobj;
+ page->abf = abf;
+ page->ds = ds;
+
+ addrmerge_prompt(page);
+ return;
+
+abort:
+ g_list_free( emails );
+ g_list_free( persons );
+}
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list