aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog17
-rw-r--r--mail/mail-threads.c134
-rw-r--r--mail/mail-threads.h1
-rw-r--r--mail/test-thread.c20
4 files changed, 119 insertions, 53 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 9fe42f1379..ad42b1fa5e 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,20 @@
+2000-06-22 Peter Williams <peterw@curious-george.helixcode.com>
+ * mail-threads.c: Make the dialog boxes for error and
+ question non-modal. They're modal relative to the dispatch
+ thread, but before they would also eg lock up the toolbar
+ buttons (while the menus, managed by another process, were
+ active -- a weird effect).
+
+2000-06-22 Peter Williams <peterw@curious-george.helixcode.com>
+
+ * mail-threads.[ch]: Extra argument to mail_operation_try:
+ 'cleanup', a function to be called in the main thread after
+ the dispatcher thread exits. gtk_object_destroy's et al may
+ attempt to unmap windows so we can't do them in the dispatcher
+ thread :-(
+
+ * test-thread.c: Updated with demo of new argument working.
+
2000-06-22 Peter Williams <peterw@helixcode.com>
* test-thread.c (op_5): New tests for the get_password
diff --git a/mail/mail-threads.c b/mail/mail-threads.c
index c54ebd67ae..8dc6ef2d48 100644
--- a/mail/mail-threads.c
+++ b/mail/mail-threads.c
@@ -41,7 +41,8 @@
**/
typedef struct closure_s {
- void (*func)( gpointer );
+ void (*callback)( gpointer );
+ void (*cleanup)( gpointer );
gpointer data;
gchar *prettyname;
@@ -56,7 +57,10 @@ typedef struct com_msg_s {
enum com_msg_type_e { STARTING, PERCENTAGE, HIDE_PBAR, SHOW_PBAR, MESSAGE, PASSWORD, ERROR, FINISHED } type;
gfloat percentage;
gchar *message;
-
+
+ void (*func)( gpointer );
+ gpointer userdata;
+
/* Password stuff */
gchar **reply;
gboolean secret;
@@ -145,8 +149,10 @@ static void check_compipe( void );
static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer userdata );
static void remove_next_pending( void );
static void show_error( com_msg_t *msg );
+static void show_error_clicked( void );
static void get_password( com_msg_t *msg );
static void get_password_cb( gchar *string, gpointer data );
+static void get_password_clicked( GnomeDialog *dialog, gint button, gpointer user_data );
/* Pthread code */
/* FIXME: support other thread types!!!! */
@@ -177,6 +183,7 @@ choke on this: no thread type defined
* mail_operation_try:
* @description: A user-friendly string describing the operation.
* @callback: the function to call in another thread to start the operation
+ * @cleanup: the function to call in the main thread when the callback is finished
* @user_data: extra data passed to the callback
*
* Runs a mail operation asynchronously. If no other operation is running,
@@ -192,13 +199,15 @@ choke on this: no thread type defined
**/
gboolean
-mail_operation_try( const gchar *description, void (*callback)( gpointer ), gpointer user_data )
+mail_operation_try( const gchar *description, void (*callback)( gpointer ),
+ void (*cleanup)( gpointer ), gpointer user_data )
{
closure_t *clur;
g_assert( callback );
clur = g_new( closure_t, 1 );
- clur->func = callback;
+ clur->callback = callback;
+ clur->cleanup = cleanup;
clur->data = user_data;
clur->prettyname = g_strdup( description );
@@ -541,9 +550,11 @@ static void *dispatch_func( void *data )
msg.message = clur->prettyname;
write( WRITER, &msg, sizeof( msg ) );
- (clur->func)( clur->data );
+ (clur->callback)( clur->data );
msg.type = FINISHED;
+ msg.func = clur->cleanup; /* NULL is ok */
+ msg.userdata = clur->data;
write( WRITER, &msg, sizeof( msg ) );
g_free( clur->prettyname );
@@ -592,28 +603,35 @@ static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer u
case STARTING:
gtk_label_set_text( GTK_LABEL( queue_window_message ), msg->message );
gtk_progress_bar_update( GTK_PROGRESS_BAR( queue_window_progress ), 0.0 );
+ g_free( msg );
break;
case PERCENTAGE:
gtk_progress_bar_update( GTK_PROGRESS_BAR( queue_window_progress ), msg->percentage );
+ g_free( msg );
break;
case HIDE_PBAR:
gtk_widget_hide( GTK_WIDGET( queue_window_progress ) );
+ g_free( msg );
break;
case SHOW_PBAR:
gtk_widget_show( GTK_WIDGET( queue_window_progress ) );
+ g_free( msg );
break;
case MESSAGE:
gtk_label_set_text( GTK_LABEL( queue_window_message ),
msg->message );
g_free( msg->message );
+ g_free( msg );
break;
case PASSWORD:
g_assert( msg->reply );
g_assert( msg->success );
get_password( msg );
+ /* don't free msg! done later */
break;
case ERROR:
show_error( msg );
+ g_free( msg );
break;
/* Don't fall through; dispatch_func does the FINISHED
@@ -621,6 +639,9 @@ static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer u
*/
case FINISHED:
+ if( msg->func )
+ (msg->func)( msg->userdata );
+
if( op_queue == NULL ) {
/* All done! */
gtk_widget_hide( queue_window );
@@ -640,6 +661,7 @@ static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer u
/* Run run run little process */
dispatch( clur );
}
+ g_free( msg );
break;
default:
g_warning( _("Corrupted message from dispatching thread?") );
@@ -647,34 +669,10 @@ static gboolean read_msg( GIOChannel *source, GIOCondition condition, gpointer u
}
GDK_THREADS_LEAVE();
- g_free( msg );
return TRUE;
}
/**
- * show_error:
- *
- * Show the error dialog and wait for user OK
- **/
-
-static void show_error( com_msg_t *msg )
-{
- GtkWidget *err_dialog;
-
- err_dialog = gnome_error_dialog( msg->message );
- g_free( msg->message );
-
- G_LOCK( modal_lock );
-
- modal_may_proceed = FALSE;
- gnome_dialog_run_and_close( GNOME_DIALOG( err_dialog ) );
- modal_may_proceed = TRUE;
-
- g_cond_signal( modal_cond );
- G_UNLOCK( modal_lock );
-}
-
-/**
* remove_next_pending:
*
* Remove an item from the list of pending items. If
@@ -702,6 +700,42 @@ static void remove_next_pending( void )
}
/**
+ * show_error:
+ *
+ * Show the error dialog and wait for user OK
+ **/
+
+static void show_error( com_msg_t *msg )
+{
+ GtkWidget *err_dialog;
+
+ err_dialog = gnome_error_dialog( msg->message );
+ gnome_dialog_set_close( GNOME_DIALOG(err_dialog), TRUE );
+ gtk_signal_connect( GTK_OBJECT( err_dialog ), "clicked", (GtkSignalFunc) show_error_clicked, NULL );
+ g_free( msg->message );
+
+ G_LOCK( modal_lock );
+
+ modal_may_proceed = FALSE;
+ /*gnome_dialog_run_and_close( GNOME_DIALOG( err_dialog ) );*/
+ gtk_widget_show( GTK_WIDGET( err_dialog ) );
+}
+
+/**
+ * show_error_clicked:
+ *
+ * Called when the user makes hits okay to the error dialog --
+ * the dispatch thread is allowed to continue.
+ **/
+
+static void show_error_clicked( void )
+{
+ modal_may_proceed = TRUE;
+ g_cond_signal( modal_cond );
+ G_UNLOCK( modal_lock );
+}
+
+/**
* get_password:
*
* Ask for a password and put the answer in *(msg->reply)
@@ -710,12 +744,12 @@ static void remove_next_pending( void )
static void get_password( com_msg_t *msg )
{
GtkWidget *dialog;
- gint ret;
dialog = gnome_request_dialog( msg->secret, msg->message, NULL,
0, get_password_cb, msg,
NULL );
-
+ gnome_dialog_set_close( GNOME_DIALOG(dialog), TRUE );
+ gtk_signal_connect( GTK_OBJECT( dialog ), "clicked", get_password_clicked, msg );
G_LOCK( modal_lock );
@@ -724,14 +758,31 @@ static void get_password( com_msg_t *msg )
if( dialog == NULL ) {
*(msg->success) = FALSE;
*(msg->reply) = g_strdup( _("Could not create dialog box.") );
- goto done;
+ modal_may_proceed = TRUE;
+ g_cond_signal( modal_cond );
+ G_UNLOCK( modal_lock );
+ } else {
+ *(msg->reply) = NULL;
+ /*ret = gnome_dialog_run_and_close( GNOME_DIALOG(dialog) );*/
+ gtk_widget_show( GTK_WIDGET( dialog ) );
}
+}
- *(msg->reply) = NULL;
- ret = gnome_dialog_run_and_close( GNOME_DIALOG(dialog) );
+static void get_password_cb( gchar *string, gpointer data )
+{
+ com_msg_t *msg = (com_msg_t *) data;
+
+ if (string)
+ *(msg->reply) = g_strdup( string );
+ else
+ *(msg->reply) = NULL;
+}
- /* The -1 check doesn't seem to work too well. */
- if( /*ret == -1 ||*/ *(msg->reply) == NULL ) {
+static void get_password_clicked( GnomeDialog *dialog, gint button, gpointer user_data )
+{
+ com_msg_t *msg = (com_msg_t *) user_data;
+
+ if( button == 1 || *(msg->reply) == NULL ) {
*(msg->success) = FALSE;
*(msg->reply) = g_strdup( _("User cancelled query.") );
goto done;
@@ -740,17 +791,8 @@ static void get_password( com_msg_t *msg )
*(msg->success) = TRUE;
done:
+ g_free( msg );
modal_may_proceed = TRUE;
g_cond_signal( modal_cond );
G_UNLOCK( modal_lock );
}
-
-static void get_password_cb( gchar *string, gpointer data )
-{
- com_msg_t *msg = (com_msg_t *) data;
-
- if (string)
- *(msg->reply) = g_strdup( string );
- else
- *(msg->reply) = NULL;
-}
diff --git a/mail/mail-threads.h b/mail/mail-threads.h
index a56c6433a6..d3f2a184e3 100644
--- a/mail/mail-threads.h
+++ b/mail/mail-threads.h
@@ -29,6 +29,7 @@
gboolean mail_operation_try( const gchar *description,
void (*callback)( gpointer ),
+ void (*cleanup)( gpointer ),
gpointer user_data );
/* User interface hooks for the other thread */
diff --git a/mail/test-thread.c b/mail/test-thread.c
index a08cd63702..9c62e7f78c 100644
--- a/mail/test-thread.c
+++ b/mail/test-thread.c
@@ -13,6 +13,7 @@ static void op_2( gpointer userdata );
static void op_3( gpointer userdata );
static void op_4( gpointer userdata );
static void op_5( gpointer userdata );
+static void done( gpointer userdata );
static gboolean queue_ops( void );
static gboolean queue_ops( void )
@@ -22,13 +23,13 @@ static gboolean queue_ops( void )
g_message( "Top of queue_ops" );
- mail_operation_try( "The Crawling Progress Bar of Doom", op_1, NULL );
- mail_operation_try( "The Mysterious Message Setter", op_2, NULL );
- mail_operation_try( "The Error Dialog of No Return", op_3, NULL );
+ mail_operation_try( "The Crawling Progress Bar of Doom", op_1, done, "op1 finished" );
+ mail_operation_try( "The Mysterious Message Setter", op_2, done, "op2 finished" );
+ mail_operation_try( "The Error Dialog of No Return", op_3, done, "op3 finished" );
for( i = 0; i < 3; i++ ) {
sprintf( buf, "Queue Filler %d", i );
- mail_operation_try( buf, op_4, GINT_TO_POINTER( i ) );
+ mail_operation_try( buf, op_4, NULL, GINT_TO_POINTER( i ) );
}
g_message( "Waiting for finish..." );
@@ -36,18 +37,18 @@ static gboolean queue_ops( void )
g_message( "Ops done -- queue some more!" );
- mail_operation_try( "Progress Bar Redux", op_1, NULL );
+ mail_operation_try( "Progress Bar Redux", op_1, NULL, NULL );
g_message( "Waiting for finish again..." );
mail_operation_wait_for_finish();
g_message( "Ops done -- more, more!" );
- mail_operation_try( "Dastardly Password Stealer", op_5, NULL );
+ mail_operation_try( "Dastardly Password Stealer", op_5, NULL, NULL );
for( i = 0; i < 3; i++ ) {
sprintf( buf, "Queue Filler %d", i );
- mail_operation_try( buf, op_4, GINT_TO_POINTER( i ) );
+ mail_operation_try( buf, op_4, NULL, GINT_TO_POINTER( i ) );
}
g_message( "Waiting for finish AGAIN..." );
@@ -125,6 +126,11 @@ static void op_5( gpointer userdata )
sleep( 1 );
}
+static void done( gpointer userdata )
+{
+ g_message( "Operation done: %s", (gchar *) userdata );
+}
+
int main( int argc, char **argv )
{
g_thread_init( NULL );