From 13bc9d2baa90975f092351347a42ca9968927276 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Mon, 6 Sep 2004 09:53:05 +0000 Subject: [PATCH] 2004-09-06 [colin] 0.9.12cvs94.1 * src/addressbook.c * src/addressitem.h * src/addritem.c * src/addritem.h Sync with HEAD (addressbook DnD) --- ChangeLog-gtk2.claws | 8 ++ PATCHSETS | 1 + configure.ac | 2 +- src/addressbook.c | 332 ++++++++++++++++++++++++++++++++++++++++++- src/addressitem.h | 1 + src/addritem.c | 23 +++ src/addritem.h | 2 + 7 files changed, 364 insertions(+), 5 deletions(-) diff --git a/ChangeLog-gtk2.claws b/ChangeLog-gtk2.claws index c5b32503c..ceaffc049 100644 --- a/ChangeLog-gtk2.claws +++ b/ChangeLog-gtk2.claws @@ -1,3 +1,11 @@ +2004-09-06 [colin] 0.9.12cvs94.1 + + * src/addressbook.c + * src/addressitem.h + * src/addritem.c + * src/addritem.h + Sync with HEAD (addressbook DnD) + 2004-09-03 [colin] 0.9.12cvs93.1 * src/summaryview.c diff --git a/PATCHSETS b/PATCHSETS index 35340070b..a57ad08f4 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -159,3 +159,4 @@ ( cvs diff -u -r 1.1.4.4 -r 1.1.4.5 src/common/xml.c; ) > 0.9.12cvs91.2.patchset ( cvs diff -u -r 1.204.2.19 -r 1.204.2.20 src/prefs_common.c; cvs diff -u -r 1.103.2.8 -r 1.103.2.9 src/prefs_common.h; cvs diff -u -r 1.395.2.29 -r 1.395.2.30 src/summaryview.c; ) > 0.9.12cvs92.1.patchset ( cvs diff -u -r 1.395.2.30 -r 1.395.2.31 src/summaryview.c; ) > 0.9.12cvs93.1.patchset +( cvs diff -u -r 1.60.2.9 -r 1.60.2.10 src/addressbook.c; cvs diff -u -r 1.5 -r 1.6 src/addressitem.h; cvs diff -u -r 1.13.2.1 -r 1.13.2.2 src/addritem.c; cvs diff -u -r 1.12.2.1 -r 1.12.2.2 src/addritem.h; ) > 0.9.12cvs94.1.patchset diff --git a/configure.ac b/configure.ac index 6c6f5a0f4..876e3b035 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=9 MICRO_VERSION=12 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=93 +EXTRA_VERSION=94 EXTRA_RELEASE= EXTRA_GTK2_VERSION=.1 diff --git a/src/addressbook.c b/src/addressbook.c index bf7245704..588fcd735 100644 --- a/src/addressbook.c +++ b/src/addressbook.c @@ -284,6 +284,8 @@ static void addressbook_treenode_remove_item ( void ); static AddressDataSource *addressbook_find_datasource (GtkCTreeNode *node ); +static AddressDataSource *addressbook_find_datasource_for_object + ( AddrItemObject *ao ); static AddressBookFile *addressbook_get_book_file(void); @@ -364,6 +366,42 @@ static void addressbook_mail_to_cb ( void ); static void addressbook_browse_entry_cb ( void ); #endif +static void addressbook_start_drag(GtkWidget *widget, gint button, + GdkEvent *event, + void *data); +static void addressbook_drag_data_get(GtkWidget *widget, + GdkDragContext *drag_context, + GtkSelectionData *selection_data, + guint info, + guint time, + void *data); +static gboolean addressbook_drag_motion_cb(GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time, + void *data); +static void addressbook_drag_leave_cb(GtkWidget *widget, + GdkDragContext *context, + guint time, + void *data); +static void addressbook_drag_received_cb(GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + void *pdata); + +static GtkTargetEntry addressbook_drag_types[] = +{ + {"text/plain", GTK_TARGET_SAME_APP, TARGET_DUMMY} +}; + +static GtkTargetList *addressbook_target_list = NULL; + + static GtkItemFactoryEntry addressbook_entries[] = { {N_("/_File"), NULL, NULL, 0, ""}, @@ -635,6 +673,7 @@ static void addressbook_create(void) GList *nodeIf; gchar *titles[N_COLS]; + gchar *dummy_titles[1]; gchar *text; gint i; @@ -643,6 +682,7 @@ static void addressbook_create(void) titles[COL_NAME] = _("Name"); titles[COL_ADDRESS] = _("E-Mail address"); titles[COL_REMARKS] = _("Remarks"); + dummy_titles[0] = ""; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), _("Address book")); @@ -677,7 +717,7 @@ static void addressbook_create(void) gtk_widget_set_size_request(ctree_swin, COL_FOLDER_WIDTH + 40, -1); /* Address index */ - ctree = gtk_ctree_new(1, 0); + ctree = gtk_sctree_new_with_titles(1, 0, dummy_titles); gtk_container_add(GTK_CONTAINER(ctree_swin), ctree); gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_BROWSE); gtk_clist_set_column_width(GTK_CLIST(ctree), 0, COL_FOLDER_WIDTH); @@ -700,6 +740,19 @@ static void addressbook_create(void) g_signal_connect(G_OBJECT(ctree), "select_row", G_CALLBACK(addressbook_select_row_tree), NULL); + gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & ~GTK_DEST_DEFAULT_HIGHLIGHT, + addressbook_drag_types, 1, + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_DEFAULT); + g_signal_connect(G_OBJECT(ctree), "drag_motion", + G_CALLBACK(addressbook_drag_motion_cb), + ctree); + g_signal_connect(G_OBJECT(ctree), "drag_leave", + G_CALLBACK(addressbook_drag_leave_cb), + ctree); + g_signal_connect(G_OBJECT(ctree), "drag_data_received", + G_CALLBACK(addressbook_drag_received_cb), + ctree); + clist_vbox = gtk_vbox_new(FALSE, 4); clist_swin = gtk_scrolled_window_new(NULL, NULL); @@ -709,7 +762,7 @@ static void addressbook_create(void) gtk_box_pack_start(GTK_BOX(clist_vbox), clist_swin, TRUE, TRUE, 0); /* Address list */ - clist = gtk_ctree_new_with_titles(N_COLS, 0, titles); + clist = gtk_sctree_new_with_titles(N_COLS, 0, titles); gtk_container_add(GTK_CONTAINER(clist_swin), clist); gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_EXTENDED); gtk_ctree_set_line_style(GTK_CTREE(clist), GTK_CTREE_LINES_NONE); @@ -742,7 +795,10 @@ static void addressbook_create(void) G_CALLBACK(addressbook_person_expand_node), NULL ); g_signal_connect(G_OBJECT(clist), "tree_collapse", G_CALLBACK(addressbook_person_collapse_node), NULL ); - + g_signal_connect(G_OBJECT(clist), "start_drag", + G_CALLBACK(addressbook_start_drag), NULL); + g_signal_connect(G_OBJECT(clist), "drag_data_get", + G_CALLBACK(addressbook_drag_data_get), NULL); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(clist_vbox), hbox, FALSE, FALSE, 0); @@ -869,6 +925,8 @@ static void addressbook_create(void) addrbook.window = window; addrbook.menubar = menubar; addrbook.ctree = ctree; + addrbook.ctree_swin + = ctree_swin; addrbook.clist = clist; addrbook.entry = entry; addrbook.statusbar = statusbar; @@ -1182,7 +1240,7 @@ static void addressbook_to_clicked(GtkButton *button, gpointer data) if( ! compose ) return; /* Nothing selected, but maybe there is something in text entry */ - addr = gtk_entry_get_text( GTK_ENTRY( addrbook.entry) ); + addr = (char *)gtk_entry_get_text( GTK_ENTRY( addrbook.entry) ); if ( addr ) { compose_entry_append( compose, addr, (ComposeEntryType)data ); @@ -2506,6 +2564,16 @@ static AddressBookFile *addressbook_get_book_file() { return abf; } +static AddressBookFile *addressbook_get_book_file_for_node(GtkCTreeNode *node) { + AddressBookFile *abf = NULL; + AddressDataSource *ds = NULL; + + ds = addressbook_find_datasource( node ); + if( ds == NULL ) return NULL; + if( ds->type == ADDR_IF_BOOK ) abf = ds->rawDataSource; + return abf; +} + static void addressbook_tree_remove_children( GtkCTree *ctree, GtkCTreeNode *parent ) { GtkCTreeNode *node; GtkCTreeRow *row; @@ -4433,6 +4501,262 @@ static void addressbook_export_ldif_cb( void ) { addressbook_exp_ldif( cache ); } +static void addressbook_start_drag(GtkWidget *widget, gint button, + GdkEvent *event, + void *data) +{ + GdkDragContext *context; + if (addressbook_target_list == NULL) + addressbook_target_list = gtk_target_list_new( + addressbook_drag_types, 1); + context = gtk_drag_begin(widget, addressbook_target_list, + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_DEFAULT, button, event); + gtk_drag_set_icon_default(context); +} + +static ItemPerson *dragged_person = NULL; +static ItemFolder *dragged_folder = NULL; +static AddressBookFile *dragged_ab = NULL; + +static void addressbook_drag_data_get(GtkWidget *widget, + GdkDragContext *drag_context, + GtkSelectionData *selection_data, + guint info, + guint time, + void *data) +{ + AddrItemObject *aio = NULL; + AddressObject *pobj = NULL; + AdapterDSource *ads = NULL; + AddressDataSource *ds = NULL; + + pobj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), addrbook.treeSelected ); + if( pobj == NULL ) return; + + if( pobj->type == ADDR_DATASOURCE ) { + ads = ADAPTER_DSOURCE(pobj); + ds = ads->dataSource; + } else if (pobj->type == ADDR_ITEM_GROUP) { + return; + } + + else if( pobj->type != ADDR_INTERFACE ) { + ds = addressbook_find_datasource( addrbook.treeSelected ); + if (!ds) + return; + } + if (addrbook.listSelected) + aio = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.clist), + addrbook.listSelected ); + + while (aio && aio->type != ADDR_ITEM_PERSON) { + aio = aio->parent; + } + + if (aio && aio->type == ADDR_ITEM_PERSON) { + dragged_person = (ItemPerson *)aio; + dragged_folder = (ItemFolder *)ADAPTER_FOLDER(pobj)->itemFolder; + dragged_ab = addressbook_get_book_file(); + + gtk_selection_data_set(selection_data, + selection_data->target, 8, + "Dummy_addr", 11); + drag_context->actions = GDK_ACTION_MOVE; + + if (pobj->type == ADDR_DATASOURCE) { + if( ds != NULL) { + dragged_folder = addrindex_ds_get_root_folder( ds ); + if (ds->type != ADDR_IF_JPILOT || + ds->type != ADDR_IF_LDAP) + drag_context->action = GDK_ACTION_COPY; + } else { + dragged_folder = NULL; + dragged_person = NULL; + dragged_ab = NULL; + } + } + } else { + dragged_folder = NULL; + dragged_person = NULL; + dragged_ab = NULL; + } +} + +static gboolean addressbook_drag_motion_cb(GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time, + void *data) +{ + gint row, column; + GtkCTreeNode *node = NULL; + gboolean acceptable = FALSE; + gint height = addrbook.ctree->allocation.height; + gint total_height = addrbook.ctree->requisition.height; + GtkAdjustment *pos = gtk_scrolled_window_get_vadjustment( + GTK_SCROLLED_WINDOW(addrbook.ctree_swin)); + gfloat vpos = pos->value; + + if (gtk_clist_get_selection_info + (GTK_CLIST(widget), x - 24, y - 24, &row, &column)) { + + if (y > height - 24 && height + vpos < total_height) + gtk_adjustment_set_value(pos, (vpos+5 > height ? height : vpos+5)); + + if (y < 24 && y > 0) + gtk_adjustment_set_value(pos, (vpos-5 < 0 ? 0 : vpos-5)); + + node = gtk_ctree_node_nth(GTK_CTREE(widget), row); + + if (node != NULL) { + AddressObject *obj = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node ); + if( obj->type == ADDR_ITEM_FOLDER + || obj->type == ADDR_ITEM_GROUP) + acceptable = TRUE; + else { + AdapterDSource *ads = NULL; + AddressDataSource *ds = NULL; + ads = ADAPTER_DSOURCE(obj); + if (ads == NULL ) return FALSE; + ds = ads->dataSource; + if (ds == NULL ) return FALSE; + if (obj->type == ADDR_DATASOURCE + && !ds->interface->externalQuery) + acceptable = TRUE; + + } + } + } + + + if (acceptable) { + g_signal_handlers_block_by_func + (G_OBJECT(widget), + G_CALLBACK(addressbook_tree_selected), NULL); + gtk_ctree_select(GTK_CTREE(widget), node); + g_signal_handlers_unblock_by_func + (G_OBJECT(widget), + G_CALLBACK(addressbook_tree_selected), NULL); + gdk_drag_status(context, + (context->actions == GDK_ACTION_COPY ? + GDK_ACTION_COPY : GDK_ACTION_MOVE) , time); + } else { + gdk_drag_status(context, 0, time); + } + + return acceptable; +} + +static void addressbook_drag_leave_cb(GtkWidget *widget, + GdkDragContext *context, + guint time, + void *data) +{ + if (addrbook.treeSelected) { + g_signal_handlers_block_by_func + (G_OBJECT(widget), + G_CALLBACK(addressbook_tree_selected), NULL); + gtk_ctree_select(GTK_CTREE(widget), addrbook.treeSelected); + g_signal_handlers_unblock_by_func + (G_OBJECT(widget), + G_CALLBACK(addressbook_tree_selected), NULL); + } +} + +static AddressBookFile *get_rawDataSource(ItemFolder *item) +{ + AdapterDSource *ads = NULL; + AddressDataSource *ds = NULL; + ads = ADAPTER_DSOURCE(item); + if (ads == NULL ) return NULL; + ds = ads->dataSource; + if (ds == NULL ) return NULL; + + return ds->rawDataSource; +} + +static void addressbook_drag_received_cb(GtkWidget *widget, + GdkDragContext *drag_context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + void *pdata) +{ + gint row, column; + GtkCTreeNode *node; + ItemFolder *afolder = NULL; + ItemFolder *ofolder = NULL; + ItemPerson *person = NULL; + + + if (!strcmp(data->data, "Dummy_addr")) { + AddressObject *obj = NULL; + AdapterDSource *ads = NULL; + AddressDataSource *ds = NULL; + AddrBookBase *adbase = NULL; + AddressCache *cache = NULL; + + + if (gtk_clist_get_selection_info + (GTK_CLIST(widget), x - 24, y - 24, &row, &column) == 0) { + return; + } + + node = gtk_ctree_node_nth(GTK_CTREE(widget), row); + if( node ) + obj = gtk_ctree_node_get_row_data(GTK_CTREE(addrbook.ctree), node ); + if( obj == NULL ) + return; + + + + person = ( ItemPerson * )dragged_person; + + if (obj->type == ADDR_ITEM_FOLDER) { + afolder = ADAPTER_FOLDER(obj)->itemFolder; + + } else if (obj->type == ADDR_DATASOURCE) { + ads = ADAPTER_DSOURCE(obj); + if( ads == NULL ) + return; + ds = ads->dataSource; + if( ds == NULL || + ds->type == ADDR_IF_JPILOT || + ds->type == ADDR_IF_LDAP) + return; + afolder = addrindex_ds_get_root_folder( ds ); + + } else { + return; + } + + ofolder = dragged_folder; + + if (afolder && ofolder) { + AddressBookFile *obook = dragged_ab; + AddressBookFile *abook = addressbook_get_book_file_for_node(node); + addritem_folder_remove_person(ofolder, person); + addritem_folder_add_person(afolder, person); + addressbook_list_select_clear(); + gtk_ctree_select( GTK_CTREE(addrbook.ctree), addrbook.opened); + + if (abook) { + addrbook_set_dirty(abook, TRUE); + } + if (obook) { + addrbook_set_dirty(obook, TRUE); + } + + addressbook_export_to_file(); + } + + gtk_drag_finish(drag_context, TRUE, TRUE, time); + } +} + /* * End of Source. */ diff --git a/src/addressitem.h b/src/addressitem.h index 8b39df650..8af19a6e6 100644 --- a/src/addressitem.h +++ b/src/addressitem.h @@ -62,6 +62,7 @@ struct _AddressBook_win GtkWidget *window; GtkWidget *menubar; GtkWidget *ctree; + GtkWidget *ctree_swin; GtkWidget *clist; GtkWidget *entry; GtkWidget *statusbar; diff --git a/src/addritem.c b/src/addritem.c index fbda06bf0..c0d9d70a2 100644 --- a/src/addritem.c +++ b/src/addritem.c @@ -846,6 +846,29 @@ ItemEMail *addritem_group_remove_email( ItemGroup *group, ItemEMail *email ) { return NULL; } +/** + * Remove person object for specified group. + * \param group Group from which to remove address. + * \param email EMail to remove + * \return EMail object, or NULL if email not found in group. Note that + * this object is referenced (linked) to a group and should *NOT* + * be freed. An E-Mail object object should only be freed after + * removing from a person. + */ +ItemPerson *addritem_folder_remove_person( ItemFolder *group, ItemPerson *person ) { + if( group && person ) { + GList *node = group->listPerson; + while( node ) { + if( node->data == person ) { + group->listPerson = g_list_remove( group->listPerson, person ); + return person; + } + node = g_list_next( node ); + } + } + return NULL; +} + /** * Remove email address of specified ID for specified group. * \param group Group from which to remove address. diff --git a/src/addritem.h b/src/addritem.h index 6c2fbab2d..322c8dc99 100644 --- a/src/addritem.h +++ b/src/addritem.h @@ -178,6 +178,8 @@ ItemEMail *addritem_group_remove_email ( ItemGroup *group, ItemEMail *email ); ItemEMail *addritem_group_remove_email_id( ItemGroup *group, const gchar *eid ); gboolean addritem_folder_add_person ( ItemFolder *folder, ItemPerson *item ); +ItemPerson *addritem_folder_remove_person( ItemFolder *group, ItemPerson *person ); + gboolean addritem_folder_add_folder ( ItemFolder *folder, ItemFolder *item ); gboolean addritem_folder_add_group ( ItemFolder *folder, ItemGroup *item ); void addritem_folder_free_person ( ItemFolder *folder ); -- 2.25.1