Guest User

using threads and g_idle_add() in gtk+

a guest
Dec 4th, 2013
1,081
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.02 KB | None | 0 0
  1. /* compile with
  2.  *      gcc -g -Wall try147.c `pkg-config gtk+-2.0 gthread-2.0 --cflags --libs`
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8.  
  9. #include <gtk/gtk.h>
  10.  
  11. /* Restart dialog responses.
  12.  */
  13. typedef enum
  14. {
  15.   RESPONSE_RESTART,
  16.   RESPONSE_CANCEL
  17. } Resp;
  18.  
  19. /* Application state.
  20.  */
  21. typedef struct _App
  22. {
  23.   /* Background thread.
  24.    */
  25.   GThread *bg_thr;
  26.  
  27.   /* Label we update with progress.
  28.    */
  29.   GtkWidget *status;
  30.  
  31.   /* Main window.
  32.    */
  33.   GtkWidget *win;
  34. } App;
  35.  
  36. /* A message from the worker.
  37.  */
  38. typedef struct _Msg
  39. {
  40.   App *app;
  41.   char *text;
  42. } Msg;
  43.  
  44. static gboolean
  45. message_idle (Msg * msg)
  46. {
  47.   gtk_label_set_text (GTK_LABEL (msg->app->status), msg->text);
  48.  
  49.   g_free (msg->text);
  50.   g_free (msg);
  51.  
  52.   return FALSE;
  53. }
  54.  
  55. static void *background_thr (void *data);
  56.  
  57. static void
  58. start_worker (App * app)
  59. {
  60.   if (!app->bg_thr)
  61.     app->bg_thr = g_thread_new ("worker", background_thr, app);
  62. }
  63.  
  64. static gboolean
  65. alert_idle (App * app)
  66. {
  67.   GtkWidget *dia;
  68.   GtkWidget *lab;
  69.   Resp resp;
  70.  
  71.   dia = gtk_dialog_new_with_buttons ("Message", GTK_WINDOW (app->win),
  72.                      GTK_DIALOG_DESTROY_WITH_PARENT |
  73.                      GTK_DIALOG_MODAL,
  74.                      "Restart", RESPONSE_RESTART,
  75.                      "Cancel", RESPONSE_CANCEL, NULL);
  76.   lab = gtk_label_new ("Error: restart worker?");
  77.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dia)->vbox), lab);
  78.   gtk_widget_show_all (dia);
  79.   resp = gtk_dialog_run (GTK_DIALOG (dia));
  80.   gtk_widget_destroy (dia);
  81.  
  82.   if (resp == RESPONSE_RESTART)
  83.     start_worker (app);
  84.  
  85.   return FALSE;
  86. }
  87.  
  88. static gboolean
  89. done_idle (App * app)
  90. {
  91.   app->bg_thr = NULL;
  92.  
  93.   gtk_label_set_text (GTK_LABEL (app->status), "idle");
  94.  
  95.   return FALSE;
  96. }
  97.  
  98. static void *
  99. background_thr (void *data)
  100. {
  101.   App *app = (App *) data;
  102.   int i;
  103.   Msg *msg;
  104.  
  105.   for (i = 0; i < 10; i++)
  106.     {
  107.       msg = g_new (Msg, 1);
  108.       msg->app = app;
  109.       msg->text = g_strdup_printf ("working %d ..", i);
  110.       g_idle_add ((GSourceFunc) message_idle, msg);
  111.  
  112.       if ((rand () & 255) > 200)
  113.     {
  114.       g_idle_add ((GSourceFunc) alert_idle, app);
  115.       break;
  116.     }
  117.  
  118.       sleep (1);
  119.     }
  120.  
  121.   g_idle_add ((GSourceFunc) done_idle, app);
  122.  
  123.   return (0);
  124. }
  125.  
  126. static void
  127. click_cb (GtkWidget * but, App * app)
  128. {
  129.   start_worker (app);
  130. }
  131.  
  132. int
  133. main (int argc, char **argv)
  134. {
  135.   App app;
  136.   GtkWidget *vbox;
  137.   GtkWidget *but;
  138.  
  139.   gtk_init (&argc, &argv);
  140.  
  141.   app.bg_thr = NULL;
  142.  
  143.   app.win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  144.  
  145.   /* Ought to kill the bg thread too I guess.
  146.    */
  147.   g_signal_connect (app.win, "destroy", G_CALLBACK (gtk_main_quit), NULL);
  148.  
  149.   vbox = gtk_vbox_new (FALSE, 2);
  150.   gtk_container_add (GTK_CONTAINER (app.win), vbox);
  151.   but = gtk_button_new_with_label ("Start bg thread");
  152.   g_signal_connect (but, "clicked", G_CALLBACK (click_cb), &app);
  153.   gtk_container_add (GTK_CONTAINER (vbox), but);
  154.   app.status = gtk_label_new ("idle");
  155.   gtk_container_add (GTK_CONTAINER (vbox), app.status);
  156.  
  157.   gtk_widget_show_all (app.win);
  158.  
  159.   gtk_main ();
  160.  
  161.   return 0;
  162. }
Advertisement
Add Comment
Please, Sign In to add comment