2007-10-07 [colin] 3.0.2cvs31
authorColin Leroy <colin@colino.net>
Sun, 7 Oct 2007 18:40:19 +0000 (18:40 +0000)
committerColin Leroy <colin@colino.net>
Sun, 7 Oct 2007 18:40:19 +0000 (18:40 +0000)
* src/addrduplicates.c
* src/addrduplicates.h
* src/addressbook.c
* src/addressbook.h
* src/addrindex.c
* src/addrindex.h
Implement deletion in duplicate finder.
Patch by Holger

ChangeLog
PATCHSETS
configure.ac
src/addrduplicates.c
src/addrduplicates.h
src/addressbook.c
src/addressbook.h
src/addrindex.c
src/addrindex.h

index b292126..747f96e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-10-07 [colin]     3.0.2cvs31
+
+       * src/addrduplicates.c
+       * src/addrduplicates.h
+       * src/addressbook.c
+       * src/addressbook.h
+       * src/addrindex.c
+       * src/addrindex.h
+               Implement deletion in duplicate finder. 
+               Patch by Holger 
+
 2007-10-07 [colin]     3.0.2cvs30
 
        * src/exporthtml.c
@@ -21,6 +32,7 @@
 
        * src/prefs_toolbar.c
                Only use icons that wouldn't look stupid in the toolbar
+               Patch by Pawel
 
 2007-10-07 [colin]     3.0.2cvs26
 
index 97b05cc..68ecc75 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.5.2.24 -r 1.5.2.25 src/exporthtml.c;  ) > 3.0.2cvs28.patchset
 ( cvs diff -u -r 1.100.2.55 -r 1.100.2.56 AUTHORS;  cvs diff -u -r 1.1.2.41 -r 1.1.2.42 src/gtk/authors.h;  ) > 3.0.2cvs29.patchset
 ( cvs diff -u -r 1.5.2.25 -r 1.5.2.26 src/exporthtml.c;  cvs diff -u -r 1.28.2.40 -r 1.28.2.41 src/mbox.c;  cvs diff -u -r 1.36.2.116 -r 1.36.2.117 src/common/utils.c;  ) > 3.0.2cvs30.patchset
+( cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/addrduplicates.c;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/addrduplicates.h;  cvs diff -u -r 1.60.2.99 -r 1.60.2.100 src/addressbook.c;  cvs diff -u -r 1.18.2.9 -r 1.18.2.10 src/addressbook.h;  cvs diff -u -r 1.28.2.32 -r 1.28.2.33 src/addrindex.c;  cvs diff -u -r 1.9.2.12 -r 1.9.2.13 src/addrindex.h;  ) > 3.0.2cvs31.patchset
index 2cd7c06..0cd5a82 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=0
 MICRO_VERSION=2
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=30
+EXTRA_VERSION=31
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 3ffd42d..ec22a70 100644 (file)
  * 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"
 #endif
 
-#include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <string.h>
 
 #include "defs.h"
 
+#ifdef USE_LDAP
+#include "ldapserver.h"
+#include "ldapupdate.h"
+#endif
 #include "addrduplicates.h"
 #include "addrindex.h"
+#include "addrbook.h"
+#include "addressbook.h"
+#include "editaddress.h"
 #include "alertpanel.h"
 #include "gtkutils.h"
+#include "inc.h"
+#include "utils.h"
 
 typedef struct
 {
-       ItemPerson *person;
-       gchar *book;
+       ItemPerson        *person;
+       AddressDataSource *ds;
 }
 AddrDupListEntry;
 
 enum {
     COL_BOOK = 0,
     COL_NAME,
+    COL_ITEM,
+    COL_DS,
     NUM_COLS
 };
 
-static gboolean create_dialog(void);
-static void create_addr_hash(void);
-static void present_finder_results(void);
+static gboolean create_dialog();
+static void refresh_addr_hash(void);
+static void refresh_stores(void);
+static void present_finder_results(GtkWindow*);
 static void cb_finder_results_dialog_destroy(GtkWindow*, gpointer);
 static void destroy_addr_hash_val(gpointer);
 static GSList* deep_copy_hash_val(GSList*);
 static void fill_hash_table();
-static gint collect_emails(ItemPerson*, const gchar*);
+static gint collect_emails(ItemPerson*, AddressDataSource*);
 static gboolean is_not_duplicate(gpointer, gpointer, gpointer);
 static gint books_compare(gconstpointer, gconstpointer);
 static GtkWidget* create_email_view(GtkListStore*);
 static GtkWidget* create_detail_view(GtkListStore*);
 static void append_to_email_store(gpointer,gpointer,gpointer);
 static void email_selection_changed(GtkTreeSelection*,gpointer);
+static void detail_selection_changed(GtkTreeSelection*,gpointer);
+static void detail_row_activated(GtkTreeView*,GtkTreePath*,
+                                 GtkTreeViewColumn*,
+                                 gpointer);
+static void cb_del_btn_clicked(GtkButton *, gpointer);
+static gboolean delete_item(ItemPerson*, AddressDataSource*);
 
 static GHashTable *addr_hash;
 static gboolean include_same_book = TRUE;
 static gboolean include_other_books = TRUE;
+
+static GtkListStore *email_store;
 static GtkListStore *detail_store;
 
-void addrduplicates_find(void)
+static GtkWidget *del_btn;
+
+void addrduplicates_find(GtkWindow *parent)
 {
        if(create_dialog()) {
-               create_addr_hash();
-               present_finder_results();
+               refresh_addr_hash();
+               present_finder_results(parent);
        }
 }
 
-static gboolean create_dialog(void)
+static gboolean create_dialog()
 {
        gboolean want_search;
        GtkWidget *vbox;
@@ -121,7 +142,7 @@ static gboolean create_dialog(void)
        return want_search;
 }
 
-static void create_addr_hash(void)
+static void refresh_addr_hash(void)
 {
        if(addr_hash)
                g_hash_table_destroy(addr_hash);
@@ -137,8 +158,6 @@ static void destroy_addr_hash_val(gpointer value)
 
        for(walk = list; walk; walk = walk->next) {
                AddrDupListEntry *entry = (AddrDupListEntry*) walk->data;
-               if(entry->book)
-                       g_free(entry->book);
                if(entry)
                        g_free(entry);
        }
@@ -158,7 +177,7 @@ static GSList* deep_copy_hash_val(GSList *in)
 
                out_entry = g_new0(AddrDupListEntry,1);
                out_entry->person = in_entry->person;
-               out_entry->book   = g_strdup(in_entry->book);
+               out_entry->ds     = in_entry->ds;
                walk->data = out_entry;
        }
 
@@ -167,7 +186,7 @@ static GSList* deep_copy_hash_val(GSList *in)
 
 static void fill_hash_table()
 {
-       addrindex_load_person_attribute(NULL, collect_emails);
+       addrindex_load_person_ds(collect_emails);
        g_hash_table_foreach_remove(addr_hash,is_not_duplicate, NULL);
 }
 
@@ -224,7 +243,7 @@ static gboolean is_not_duplicate(gpointer key, gpointer value,
        return retval;
 }
 
-static gint collect_emails(ItemPerson *itemperson, const gchar *book)
+static gint collect_emails(ItemPerson *itemperson, AddressDataSource *ds)
 {
        gchar *addr;
        GList *nodeM;
@@ -247,7 +266,7 @@ static gint collect_emails(ItemPerson *itemperson, const gchar *book)
 
                entry = g_new0(AddrDupListEntry,1);
                entry->person = itemperson;
-               entry->book = g_strdup(book);
+               entry->ds     = ds;
 
                new_val = g_slist_prepend(new_val, entry);
                g_hash_table_insert(addr_hash, addr, new_val);
@@ -263,12 +282,12 @@ static gint books_compare(gconstpointer a, gconstpointer b)
        const AddrDupListEntry *entry2;
        entry1 = a;
        entry2 = b;
-       return strcmp(entry1->book,entry2->book);
+       return strcmp(addrindex_ds_get_name(entry1->ds),
+                     addrindex_ds_get_name(entry2->ds));
 }
 
-static void present_finder_results(void)
+static void present_finder_results(GtkWindow *parent)
 {
-       GtkListStore *email_store;
        GtkWidget *email_view;
        GtkWidget *detail_view;
        GtkWidget *dialog = NULL;
@@ -286,7 +305,7 @@ static void present_finder_results(void)
        }
 
        email_store = gtk_list_store_new(1, G_TYPE_STRING);
-       g_hash_table_foreach(addr_hash,append_to_email_store,email_store);
+       refresh_stores();
        email_view = create_email_view(email_store);
        email_select = gtk_tree_view_get_selection(GTK_TREE_VIEW(email_view));
        gtk_tree_selection_set_mode(email_select,GTK_SELECTION_SINGLE);
@@ -294,12 +313,18 @@ static void present_finder_results(void)
        g_signal_connect(email_select, "changed",
                         (GCallback)email_selection_changed, NULL);
 
-       detail_store = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
+       detail_store = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_STRING,
+                                         G_TYPE_POINTER, G_TYPE_POINTER);
        detail_view = create_detail_view(detail_store);
        detail_select = gtk_tree_view_get_selection(GTK_TREE_VIEW(detail_view));
-       gtk_tree_selection_set_mode(email_select,GTK_SELECTION_SINGLE);
+       gtk_tree_selection_set_mode(detail_select,GTK_SELECTION_MULTIPLE);
+
+       g_signal_connect(detail_select, "changed",
+                        (GCallback)detail_selection_changed, NULL);
 
        dialog = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "address_dupes_finder");
+       gtk_window_set_transient_for(GTK_WINDOW(dialog),parent);
+       gtk_window_set_modal(GTK_WINDOW(dialog),TRUE);
        if(!geometry.min_height) {
                geometry.min_width = 600;
                geometry.min_height = 400;
@@ -322,21 +347,33 @@ static void present_finder_results(void)
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
 
        close = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
-       gtk_box_pack_end(GTK_BOX(hbox), close, FALSE, FALSE, 0);
+       gtk_box_pack_end(GTK_BOX(hbox), close, FALSE, FALSE, 5);
+
+       del_btn = gtk_button_new_from_stock(GTK_STOCK_DELETE);
+       gtk_box_pack_end(GTK_BOX(hbox), del_btn, FALSE, FALSE, 5);
+       gtk_widget_set_sensitive(del_btn, FALSE);
 
        g_signal_connect(dialog, "destroy",
                         G_CALLBACK(cb_finder_results_dialog_destroy), NULL);
        g_signal_connect_swapped(close, "clicked",
                                 G_CALLBACK(gtk_widget_destroy), dialog);
-
+       g_signal_connect(del_btn, "clicked",
+                        G_CALLBACK(cb_del_btn_clicked), detail_view);
+       inc_lock();
        gtk_widget_show_all(dialog);
 }
 
 static void cb_finder_results_dialog_destroy(GtkWindow *win, gpointer data)
 {
-       g_hash_table_destroy(addr_hash);
-       addr_hash = NULL;
+       email_store = NULL;
+       detail_store = NULL;
 
+       if(addr_hash) {
+               g_hash_table_destroy(addr_hash);
+               addr_hash = NULL;
+       }
+       addressbook_refresh();
+       inc_unlock();
 }
 
 static GtkWidget* create_email_view(GtkListStore *store)
@@ -379,6 +416,9 @@ static GtkWidget* create_detail_view(GtkListStore *store)
                "text", COL_NAME,
                NULL);
 
+       g_signal_connect(view, "row-activated",
+                        (GCallback)detail_row_activated, NULL);
+
        return view;
 }
 
@@ -391,6 +431,14 @@ static void append_to_email_store(gpointer key,gpointer value,gpointer data)
        gtk_list_store_set(store, &iter, 0, (gchar*) key, -1);
 }
 
+static void detail_selection_changed(GtkTreeSelection *selection, gpointer data)
+{
+       if(gtk_tree_selection_count_selected_rows(selection) > 0)
+               gtk_widget_set_sensitive(del_btn,TRUE);
+       else
+               gtk_widget_set_sensitive(del_btn,FALSE);
+}
+
 static void email_selection_changed(GtkTreeSelection *selection, gpointer data)
 {
        GtkTreeIter iter;
@@ -411,10 +459,143 @@ static void email_selection_changed(GtkTreeSelection *selection, gpointer data)
                                continue;
                        gtk_list_store_append(detail_store, &iter);
                        gtk_list_store_set(detail_store, &iter,
-                                          COL_BOOK, entry->book,
+                                          COL_BOOK, addrindex_ds_get_name(entry->ds),
                                           COL_NAME, ADDRITEM_NAME(entry->person),
+                                          COL_ITEM, entry->person,
+                                          COL_DS, entry->ds,
                                           -1);
                }
                g_free(email);
        }
 }
+
+static void refresh_stores(void)
+{
+       refresh_addr_hash();
+       if(email_store)
+               gtk_list_store_clear(email_store);
+       if(detail_store)
+               gtk_list_store_clear(detail_store);
+       g_hash_table_foreach(addr_hash,append_to_email_store,email_store);
+}
+
+static void detail_row_activated(GtkTreeView       *tree_view,
+                                 GtkTreePath       *path,
+                                 GtkTreeViewColumn *column,
+                                 gpointer           user_data)
+{
+       GtkTreeIter iter;
+       ItemPerson *person;
+       AddressDataSource *ds;
+       GtkTreeModel *model;
+       AddressBookFile *abf;
+
+       model = gtk_tree_view_get_model(tree_view);
+
+       if(!gtk_tree_model_get_iter(model,&iter,path))
+               return;
+
+       gtk_tree_model_get(model, &iter, COL_ITEM, &person, COL_DS, &ds, -1);
+
+
+       if(!((ds->type == ADDR_IF_BOOK) || ds->type == ADDR_IF_LDAP)) {
+               debug_print("Unsupported address datasource type for editing\n");
+               return;
+       }
+
+       abf = ds->rawDataSource;
+       if(addressbook_edit_person(abf,NULL,person,FALSE,NULL,NULL,TRUE))
+               refresh_stores();
+}
+
+void cb_del_btn_clicked(GtkButton *button, gpointer data)
+{
+       GtkTreeView *detail_view;
+       GtkTreeIter iter;
+       GtkTreeModel *model;
+       GtkTreeSelection *selection;
+       ItemPerson *item;
+       AddressDataSource *ds;
+       GList *list;
+       GList *ref_list;
+       GList *walk;
+       GtkTreeRowReference *ref;
+       AlertValue aval;
+
+       detail_view = data;
+
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(detail_view));
+
+       list = gtk_tree_selection_get_selected_rows(selection, &model);
+
+       if(!list)
+               return;
+
+       aval = alertpanel(_("Delete address(es)"),
+                         _("Really delete the address(es)?"),
+                         GTK_STOCK_CANCEL, "+"GTK_STOCK_DELETE, NULL);
+       if(aval != G_ALERTALTERNATE)
+               return;
+
+       ref_list = NULL;
+       for(walk = list; walk; walk = walk->next) {
+               ref = gtk_tree_row_reference_new(model,(GtkTreePath*)(walk->data));
+               ref_list = g_list_prepend(ref_list, ref);
+       }
+       g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
+       g_list_free(list);
+
+       for(walk = ref_list; walk; walk = walk->next) {
+               GtkTreePath *path;
+               ref = walk->data;
+               if(!gtk_tree_row_reference_valid(ref))
+                       continue;
+               path = gtk_tree_row_reference_get_path(ref);
+               if(gtk_tree_model_get_iter(model, &iter, path)) {
+                       gtk_tree_model_get(model, &iter, COL_ITEM, &item, COL_DS, &ds, -1);
+                       delete_item(item,ds);
+               }
+               gtk_tree_path_free(path);
+       }
+
+       g_list_foreach(ref_list, (GFunc)gtk_tree_row_reference_free, NULL);
+       g_list_free(ref_list);
+
+       refresh_stores();
+}
+
+static gboolean delete_item(ItemPerson *item, AddressDataSource *ds)
+{
+       AddressBookFile *abf;
+       AddressInterface *iface;
+
+       /* Test for read only */
+       iface = ds->interface;
+       if( iface->readOnly ) {
+               alertpanel( _("Delete address"),
+                           _("This address data is readonly and cannot be deleted."),
+                           GTK_STOCK_CLOSE, NULL, NULL );
+               return FALSE;
+       }
+
+       if(!(abf = ds->rawDataSource))
+               return FALSE;
+
+       item->status = DELETE_ENTRY;
+       item = addrbook_remove_person(abf, item);
+
+#ifdef USE_LDAP
+
+       if (ds && ds->type == ADDR_IF_LDAP) {
+               LdapServer *server = ds->rawDataSource;
+               ldapsvr_set_modified(server, TRUE);
+               ldapsvr_update_book(server, item);
+       }
+
+#endif
+
+       if(item)
+               addritem_free_item_person(item);
+
+       return TRUE;
+}
index 5dd5fff..cfefa80 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __ADDRDUPLICATES_H__
 #define __ADDRDUPLICATES_H__
 
-void addrduplicates_find(void);
+#include <gtk/gtk.h>
+
+void addrduplicates_find(GtkWindow *parent);
 
 #endif /*__ADDRDUPLICATES_H__*/
index e1917c0..2eaadfd 100644 (file)
@@ -690,7 +690,7 @@ Compose *addressbook_get_target_compose(void)
 /**
  * Refresh addressbook and save to file(s).
  */
-static void addressbook_refresh( void )
+void addressbook_refresh( void )
 {
        if (addrbook.window) {
                if (addrbook.treeSelected) {
@@ -5290,7 +5290,7 @@ static void addressbook_export_ldif_cb( void ) {
 
 static void addressbook_find_duplicates_cb(void)
 {
-       addrduplicates_find();  
+       addrduplicates_find(GTK_WINDOW(addrbook.window));       
 }
 
 static void addressbook_start_drag(GtkWidget *widget, gint button, 
index 636be30..f412185 100644 (file)
@@ -60,6 +60,7 @@ void addressbook_harvest              ( FolderItem *folderItem,
 void addressbook_read_all              ( void );
 void addressbook_address_list_set_focus( void );
 void addressbook_address_list_disable_some_actions( void );
+void addressbook_refresh( void );
 
 #endif /* __ADDRESSBOOK_H__ */
 
index 433a736..4ad70c5 100644 (file)
@@ -3116,6 +3116,61 @@ gboolean addrindex_load_person_attribute(
        return TRUE;
 }
 
+/**
+ * This function can be used to collect information about
+ * addressbook entries
+ *
+ * \param callBackFunc Function to be called for each ItemPerson
+ * \return <i>TRUE</i>
+ */
+gboolean addrindex_load_person_ds( gint (*callBackFunc)
+                       ( ItemPerson *, AddressDataSource * ) )
+{
+       AddressDataSource *ds;
+       GList *nodeIf, *nodeDS;
+       GList *listP, *nodeP;
+
+       nodeIf = addrindex_get_interface_list( _addressIndex_ );
+       while( nodeIf ) {
+               AddressInterface *iface = nodeIf->data;
+
+               nodeIf = g_list_next( nodeIf );
+
+               if( ! iface->useInterface || iface->externalQuery )
+                       continue;
+
+               nodeDS = iface->listSource;
+               while( nodeDS ) {
+                       ds = nodeDS->data;
+
+                       /* Read address book */
+                       if( addrindex_ds_get_modify_flag( ds ) ) {
+                               addrindex_ds_read_data( ds );
+                       }
+
+                       if( ! addrindex_ds_get_read_flag( ds ) ) {
+                               addrindex_ds_read_data( ds );
+                       }
+
+                       /* Get all persons */
+                       listP = addrindex_ds_get_all_persons( ds );
+                       nodeP = listP;
+                       while( nodeP ) {
+                               ItemPerson *person = nodeP->data;
+
+                               callBackFunc(person, ds);
+                               nodeP = g_list_next( nodeP );
+                       }
+                       /* Free up the list */
+                       g_list_free( listP );
+
+                       nodeDS = g_list_next( nodeDS );
+               }
+       }
+       return TRUE;
+}
+
+
 /*
  * End of Source.
  */
index 42428cd..8255855 100644 (file)
@@ -172,6 +172,9 @@ gboolean addrindex_load_person_attribute( const gchar *attr,
                gint (*callBackFunc)
                        ( ItemPerson *, const gchar * ) );
 
+gboolean addrindex_load_person_ds( gint (*callBackFunc)
+                       ( ItemPerson *, AddressDataSource * ) );
+                       
 #endif /* __ADDRINDEX_H__ */
 
 /*