[Commits] [SCM] claws branch, gtk3, updated. 3.16.0-142-g0690607

ticho at claws-mail.org ticho at claws-mail.org
Tue Apr 10 18:37:44 CEST 2018


The branch, gtk3 has been updated
       via  06906075b0304ace66e876c722c53cc376455dbe (commit)
       via  dfa7cbbc44be6aac6c1cca2b87e3248d0111b98c (commit)
       via  b08715115282bdb9e0d002d4604eac8610215582 (commit)
       via  0b1dabe592bac1deb6ef79651b912eb5aecbcb27 (commit)
       via  21da090e2b45d933e1676ed319f6a5aa930d7db4 (commit)
       via  6027b8ba5bc49541c2e149434521d73ad06a4150 (commit)
       via  7e998163619bcedfb90835775dae93bf2042110b (commit)
      from  269c75cbdd5a9095578fb796f7ba5a13d20010ec (commit)

Summary of changes:
 configure.ac                          |   12 +-
 src/Makefile.am                       |    2 +
 src/addressbook.c                     |   58 +++-
 src/addressbook.h                     |    5 +
 src/addritem.c                        |    8 +-
 src/addrmerge.c                       |  496 +++++++++++++++++++++++++++++++++
 src/{addrduplicates.h => addrmerge.h} |   37 ++-
 src/compose.c                         |    2 +-
 src/gtk/claws-marshal.list            |   26 +-
 src/inc.c                             |    1 +
 10 files changed, 615 insertions(+), 32 deletions(-)
 create mode 100644 src/addrmerge.c
 copy src/{addrduplicates.h => addrmerge.h} (50%)


- Log -----------------------------------------------------------------
commit 06906075b0304ace66e876c722c53cc376455dbe
Author: wwp <wwp at free.fr>
Date:   Tue Apr 10 09:44:20 2018 +0200

    Add missing src/addrmerge.h file from 3.16.0-107-gf25722a.

diff --git a/src/addrmerge.h b/src/addrmerge.h
new file mode 100644
index 0000000..344d361
--- /dev/null
+++ b/src/addrmerge.h
@@ -0,0 +1,51 @@
+/* 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/>. 
+ */
+
+#ifndef __ADDRMERGE_H__
+#define __ADDRMERGE_H__
+
+#include <gtk/gtk.h>
+
+#include "addritem.h"
+#include "addressbook.h"
+#include "addressitem.h"
+#include "addrselect.h"
+
+struct AddrMergePage {
+   GtkCMCTree*     clist;
+   AddressObject*	   pobj;
+   AddressBookFile*    abf;
+   AddressDataSource*  ds;
+   AddrSelectList*     addressSelect;
+   ItemPerson*     target;
+   ItemPerson*     nameTarget;
+   gchar*		   picture;
+   GList*		   emails;
+   GList*		   persons;
+   gboolean 	   pickPicture;
+   gboolean 	   pickName;
+   GtkWidget*	   dialog;
+   GtkWidget*	   iconView;
+   GtkWidget*	   namesList;
+};
+
+void addrmerge_merge   ( GtkCMCTree *clist,
+			 AddressObject *pobj,
+			 AddressDataSource *ds,
+			 AddrSelectList *list );
+
+#endif /*__ADDRMERGE_H__*/

commit dfa7cbbc44be6aac6c1cca2b87e3248d0111b98c
Author: wwp <wwp at free.fr>
Date:   Tue Apr 10 09:26:21 2018 +0200

    Check for enchant-2 (necessary since enchant 2.1.3).

diff --git a/configure.ac b/configure.ac
index aba2b85..6990978 100644
--- a/configure.ac
+++ b/configure.ac
@@ -584,8 +584,16 @@ if test $enable_enchant = yes; then
 		enable_enchant=yes
 	],
 	[
-		echo "Building without enchant-notification"
-		enable_enchant=no
+		PKG_CHECK_MODULES(ENCHANT, enchant-2 >= 2.0.0,
+		[
+			AC_DEFINE(USE_ENCHANT, 1, enchant-2)
+			echo "Building with enchant-2"
+			enable_enchant=yes
+		],
+		[
+			echo "Building without enchant-notification"
+			enable_enchant=no
+		])
 	])
 	AC_SUBST(ENCHANT_CFLAGS)
 	AC_SUBST(ENCHANT_LIBS)

commit b08715115282bdb9e0d002d4604eac8610215582
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 e9470b4..943b9ba 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 );
+}

commit 0b1dabe592bac1deb6ef79651b912eb5aecbcb27
Author: wwp <wwp at free.fr>
Date:   Sun Apr 8 17:03:50 2018 +0200

    addritem+person_get_picture now returns something useful: a copy
    of the addritem's picture full path (still to be free'd by the caller),
    instead of a copy of the addritem's UID string.

diff --git a/src/addritem.c b/src/addritem.c
index f6d9d12..3a81826 100644
--- a/src/addritem.c
+++ b/src/addritem.c
@@ -270,12 +270,16 @@ void addritem_person_set_picture( ItemPerson *person, const gchar *value ) {
 }
 
 /**
- * Get picture for person object.
+ * Get picture filename for person object.
  * \param person Person object.
+ * \return copy of picture file path string (to be freed by caller - and there is
+ *         no guarantee that path does exist, or NULL.
  */
 gchar *addritem_person_get_picture( ItemPerson *person) {
 	if (person->picture)
-		return g_strdup(person->picture);
+		return g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S,
+			ADDRBOOK_DIR, G_DIR_SEPARATOR_S, person->picture,
+			".png", NULL );
 	return NULL;
 }
 

commit 21da090e2b45d933e1676ed319f6a5aa930d7db4
Author: wwp <wwp at free.fr>
Date:   Wed Apr 4 10:27:01 2018 +0200

    Remove the empty progress bar that may remain in status bar after
    pop3 incorporation (if account is configured to leave messages
    on server).
    Closes bug 3985: an empty progress bar remains after POP mail check completes

diff --git a/src/inc.c b/src/inc.c
index 95f8b01..d4a6e0f 100644
--- a/src/inc.c
+++ b/src/inc.c
@@ -172,6 +172,7 @@ static void inc_finished(MainWindow *mainwin, gboolean new_messages, gboolean au
 		folderview_unselect(mainwin->folderview);
 		folderview_select(mainwin->folderview, item);
 	}
+	statusbar_progress_all(0,0,0);
 }
 
 void inc_mail(MainWindow *mainwin, gboolean notify)

commit 6027b8ba5bc49541c2e149434521d73ad06a4150
Author: Paul <paul at claws-mail.org>
Date:   Tue Apr 3 10:27:56 2018 +0100

    replace deprecated 'NONE' token

diff --git a/src/gtk/claws-marshal.list b/src/gtk/claws-marshal.list
index 8db25d4..1d0e221 100644
--- a/src/gtk/claws-marshal.list
+++ b/src/gtk/claws-marshal.list
@@ -1,13 +1,13 @@
-NONE:POINTER
-NONE:INT,POINTER
-NONE:OBJECT,OBJECT
-NONE:INT,INT,BOXED
-NONE:INT,INT
-NONE:INT
-NONE:VOID
-NONE:VOID,VOID
-NONE:ENUM,FLOAT,BOOLEAN
-NONE:ENUM,FLOAT
-NONE:POINTER,INT
-NONE:POINTER,POINTER,POINTER
-NONE:ENUM
+VOID:POINTER
+VOID:INT,POINTER
+VOID:OBJECT,OBJECT
+VOID:INT,INT,BOXED
+VOID:INT,INT
+VOID:INT
+VOID:VOID
+VOID:VOID,VOID
+VOID:ENUM,FLOAT,BOOLEAN
+VOID:ENUM,FLOAT
+VOID:POINTER,INT
+VOID:POINTER,POINTER,POINTER
+VOID:ENUM

commit 7e998163619bcedfb90835775dae93bf2042110b
Author: wwp <wwp at free.fr>
Date:   Tue Apr 3 10:17:58 2018 +0200

    Fix broken templates attachments due to commit 814b087,
    which clears template internals (including attachments list)
    wherever template contains any field to apply (To/Subject/etc.)
    and before attachments could be processed. Simply process
    attachments before attachments list may be cleared by fields
    processing. Ideally we should change quote_fmt_reset_vartable()
    or its uses in compose.c at least.

diff --git a/src/compose.c b/src/compose.c
index 3ff583c..25488d6 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -8869,8 +8869,8 @@ static void compose_template_apply(Compose *compose, Template *tmpl,
 
 	/* process the other fields */
 
-	compose_template_apply_fields(compose, tmpl);
 	compose_attach_from_list(compose, quote_fmt_get_attachments_list(), FALSE);
+	compose_template_apply_fields(compose, tmpl);
 	quote_fmt_reset_vartable();
 	quote_fmtlex_destroy();
 

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list