2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2006 Match Grun and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
33 #include <glib/gi18n.h>
34 #include <gdk/gdkkeysyms.h>
35 #include <gtk/gtkwindow.h>
36 #include <gtk/gtksignal.h>
37 #include <gtk/gtkhbox.h>
38 #include <gtk/gtklabel.h>
39 #include <gtk/gtkentry.h>
40 #include <gtk/gtkhbbox.h>
41 #include <gtk/gtkbutton.h>
45 #include "stock_pixmap.h"
46 #include "prefs_common.h"
47 #include "browseldap.h"
49 #include "addrindex.h"
50 #include "manage_window.h"
52 #include "ldapquery.h"
53 #include "ldapserver.h"
54 #include "ldaplocate.h"
61 #define BROWSELDAP_WIDTH 450
62 #define BROWSELDAP_HEIGHT 420
65 #define COL_WIDTH_NAME 140
66 #define COL_WIDTH_VALUE 140
68 static struct _LDAPEntry_dlg
{
70 GtkWidget
*label_server
;
71 GtkWidget
*label_address
;
72 GtkWidget
*list_entry
;
79 static GList
*_displayQueue_
= NULL
;
82 * Mutex to protect callback from multiple threads.
84 static pthread_mutex_t _browseMutex_
= PTHREAD_MUTEX_INITIALIZER
;
89 static gint _queryID_
= 0;
94 static guint _browseIdleID_
= 0;
97 * Search complete indicator.
99 static gboolean _searchComplete_
= FALSE
;
102 * Callback entry point for each LDAP entry processed. The background thread
103 * (if any) appends the address list to the display queue.
105 * \param qry LDAP query object.
106 * \param queryID Query ID of search request.
107 * \param listEMail List of zero of more email objects that met search
109 * \param data User data.
111 static gint
browse_callback_entry(
112 LdapQuery
*qry
, gint queryID
, GList
*listValues
, gpointer data
)
117 /* printf( "browse_callback_entry...\n" ); */
118 pthread_mutex_lock( & _browseMutex_
);
119 /* Append contents to end of display queue */
122 nvp
= ( NameValuePair
* ) node
->data
;
123 /* ldapqry_print_name_value( nvp, stdout ); */
124 _displayQueue_
= g_list_append( _displayQueue_
, nvp
);
126 node
= g_list_next( node
);
128 pthread_mutex_unlock( & _browseMutex_
);
129 /* printf( "browse_callback_entry...done\n" ); */
135 * Callback entry point for end of LDAP locate search.
137 * \param qry LDAP query object.
138 * \param queryID Query ID of search request.
139 * \param status Status/error code.
140 * \param data User data.
142 static gint
browse_callback_end(
143 LdapQuery
*qry
, gint queryID
, gint status
, gpointer data
)
145 _searchComplete_
= TRUE
;
150 * Clear the display queue.
152 static void browse_clear_queue( void ) {
153 /* Clear out display queue */
154 pthread_mutex_lock( & _browseMutex_
);
156 ldapqry_free_list_name_value( _displayQueue_
);
157 g_list_free( _displayQueue_
);
158 _displayQueue_
= NULL
;
160 pthread_mutex_unlock( & _browseMutex_
);
164 * Close window callback.
165 * \param widget Widget.
166 * \param event Event.
167 * \param cancelled Cancelled flag.
169 static gint
browse_delete_event(
170 GtkWidget
*widget
, GdkEventAny
*event
, gboolean
*cancelled
)
177 * Respond to key press in window.
178 * \param widget Widget.
179 * \param event Event.
180 * \param cancelled Cancelled flag.
182 static void browse_key_pressed(
183 GtkWidget
*widget
, GdkEventKey
*event
, gboolean
*cancelled
)
185 if (event
&& event
->keyval
== GDK_Escape
) {
191 * Callback to close window.
192 * \param widget Widget.
193 * \param cancelled Cancelled flag.
195 static void browse_close( GtkWidget
*widget
, gboolean
*cancelled
) {
200 * Create the window to display data.
202 static void browse_create( void ) {
207 GtkWidget
*label_server
;
208 GtkWidget
*label_addr
;
209 GtkWidget
*list_entry
;
213 GtkWidget
*close_btn
;
216 window
= gtk_dialog_new();
217 gtk_widget_set_size_request( window
, BROWSELDAP_WIDTH
, BROWSELDAP_HEIGHT
);
218 gtk_container_set_border_width( GTK_CONTAINER(window
), 0 );
219 gtk_window_set_title( GTK_WINDOW(window
), _("Browse Directory Entry") );
220 gtk_window_set_position( GTK_WINDOW(window
), GTK_WIN_POS_MOUSE
);
221 gtk_window_set_modal( GTK_WINDOW(window
), TRUE
);
222 g_signal_connect(G_OBJECT(window
), "delete_event",
223 G_CALLBACK(browse_delete_event
), NULL
);
224 g_signal_connect(G_OBJECT(window
), "key_press_event",
225 G_CALLBACK(browse_key_pressed
), NULL
);
227 vbox
= gtk_vbox_new(FALSE
, 8);
228 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window
)->vbox
), vbox
, TRUE
, TRUE
, 0);
229 gtk_container_set_border_width( GTK_CONTAINER(vbox
), 8 );
231 table
= gtk_table_new(2, 2, FALSE
);
232 gtk_box_pack_start(GTK_BOX(vbox
), table
, FALSE
, FALSE
, 0);
233 gtk_container_set_border_width( GTK_CONTAINER(table
), 8 );
234 gtk_table_set_row_spacings(GTK_TABLE(table
), 8);
235 gtk_table_set_col_spacings(GTK_TABLE(table
), 8);
239 label
= gtk_label_new(_("Server Name :"));
240 gtk_table_attach(GTK_TABLE(table
), label
, 0, 1, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
241 gtk_misc_set_alignment(GTK_MISC(label
), 1, 0.5);
243 label_server
= gtk_label_new("");
244 gtk_table_attach(GTK_TABLE(table
), label_server
, 1, 2, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
245 gtk_misc_set_alignment(GTK_MISC(label_server
), 0, 0.5);
249 label
= gtk_label_new(_("Distinguished Name (dn) :"));
250 gtk_table_attach(GTK_TABLE(table
), label
, 0, 1, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
251 gtk_misc_set_alignment(GTK_MISC(label
), 1, 0.5);
253 label_addr
= gtk_label_new("");
254 gtk_table_attach(GTK_TABLE(table
), label_addr
, 1, 2, top
, (top
+ 1), GTK_FILL
, 0, 0, 0);
255 gtk_misc_set_alignment(GTK_MISC(label_addr
), 0, 0.5);
257 /* Address book/folder tree */
258 vlbox
= gtk_vbox_new(FALSE
, 8);
259 gtk_box_pack_start(GTK_BOX(vbox
), vlbox
, TRUE
, TRUE
, 0);
260 gtk_container_set_border_width( GTK_CONTAINER(vlbox
), 8 );
262 tree_win
= gtk_scrolled_window_new( NULL
, NULL
);
263 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tree_win
),
264 GTK_POLICY_AUTOMATIC
,
265 GTK_POLICY_AUTOMATIC
);
266 gtk_box_pack_start( GTK_BOX(vlbox
), tree_win
, TRUE
, TRUE
, 0 );
268 list_entry
= gtk_clist_new( N_COLS
);
269 gtk_container_add( GTK_CONTAINER(tree_win
), list_entry
);
270 gtk_clist_column_titles_show( GTK_CLIST(list_entry
) );
271 gtk_clist_set_column_title(
272 GTK_CLIST(list_entry
), COL_NAME
, _( "LDAP Name" ) );
273 gtk_clist_set_column_title(
274 GTK_CLIST(list_entry
), COL_VALUE
, _( "Attribute Value" ) );
275 gtk_clist_set_selection_mode(
276 GTK_CLIST(list_entry
), GTK_SELECTION_BROWSE
);
277 gtk_clist_set_column_width( GTK_CLIST(list_entry
),
278 COL_NAME
, COL_WIDTH_NAME
);
279 gtk_clist_set_auto_sort( GTK_CLIST(list_entry
), TRUE
);
282 gtkut_stock_button_set_create(&hbbox
, &close_btn
, GTK_STOCK_CLOSE
,
283 NULL
, NULL
, NULL
, NULL
);
284 gtk_box_pack_end(GTK_BOX(vbox
), hbbox
, FALSE
, FALSE
, 0);
285 gtk_container_set_border_width( GTK_CONTAINER(hbbox
), 0 );
287 g_signal_connect(G_OBJECT(close_btn
), "clicked",
288 G_CALLBACK(browse_close
), NULL
);
289 gtk_widget_grab_default(close_btn
);
291 gtk_widget_show_all(vbox
);
293 browseldap_dlg
.window
= window
;
294 browseldap_dlg
.label_server
= label_server
;
295 browseldap_dlg
.label_address
= label_addr
;
296 browseldap_dlg
.list_entry
= list_entry
;
297 browseldap_dlg
.close_btn
= close_btn
;
299 gtk_widget_show_all( window
);
304 * Idler function. This function is called by the main (UI) thread during UI
305 * idle time while an address search is in progress. Items from the display
306 * queue are processed and appended to the address list.
308 * \param data Target data object.
309 * \return <i>TRUE</i> to ensure that idle event do not get ignored.
311 static gboolean
browse_idle( gpointer data
) {
316 /* Process all entries in display queue */
317 pthread_mutex_lock( & _browseMutex_
);
318 if( _displayQueue_
) {
319 node
= _displayQueue_
;
321 /* Add entry into list */
322 nvp
= ( NameValuePair
* ) node
->data
;
323 text
[COL_NAME
] = nvp
->name
;
324 text
[COL_VALUE
] = nvp
->value
;
326 GTK_CLIST(browseldap_dlg
.list_entry
), text
);
329 ldapqry_free_name_value( nvp
);
331 node
= g_list_next( node
);
333 g_list_free( _displayQueue_
);
334 _displayQueue_
= NULL
;
336 pthread_mutex_unlock( & _browseMutex_
);
338 if( _searchComplete_
) {
340 if( _browseIdleID_
!= 0 ) {
341 g_source_remove( _browseIdleID_
);
343 gtk_clist_select_row(
344 GTK_CLIST( browseldap_dlg
.list_entry
), 0, 0 );
352 * Main entry point to browse LDAP entries.
353 * \param ds Data source to process.
354 * \param dn Distinguished name to retrieve.
355 * \return <code>TRUE</code>
357 gboolean
browseldap_entry( AddressDataSource
*ds
, const gchar
*dn
) {
363 server
= ds
->rawDataSource
;
365 if( ! browseldap_dlg
.window
) browse_create();
366 gtk_widget_grab_focus(browseldap_dlg
.close_btn
);
367 gtk_widget_show(browseldap_dlg
.window
);
368 manage_window_set_transient(GTK_WINDOW(browseldap_dlg
.window
));
370 gtk_clist_select_row( GTK_CLIST( browseldap_dlg
.list_entry
), 0, 0 );
371 gtk_widget_show(browseldap_dlg
.window
);
373 gtk_label_set_text( GTK_LABEL(browseldap_dlg
.label_address
), "" );
376 GTK_LABEL(browseldap_dlg
.label_address
), dn
);
379 GTK_LABEL(browseldap_dlg
.label_server
),
380 ldapsvr_get_name( server
) );
383 _searchComplete_
= FALSE
;
384 _queryID_
= ldaplocate_search_setup(
385 server
, dn
, browse_callback_entry
, browse_callback_end
);
386 _browseIdleID_
= g_idle_add( ( GtkFunction
) browse_idle
, NULL
);
389 ldaplocate_search_start( _queryID_
);
393 gtk_widget_hide( browseldap_dlg
.window
);
396 ldaplocate_search_stop( _queryID_
);
398 if( _browseIdleID_
!= 0 ) {
399 g_source_remove( _browseIdleID_
);
402 browse_clear_queue();
403 gtk_clist_clear( GTK_CLIST( browseldap_dlg
.list_entry
) );
408 #endif /* USE_LDAP */