[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