cmemory-managementglibgtk4gio

Using GCancellable with the GtkAlertDialog


For testing purposes, I wrote a small program calling a GtkAlertDialog and showing the results of the user selection.

I noticed the topic of GCancellable.

Despite studying the documentation, I did not succeed in finding a meaningful use for it. Here is the corresponding programme section:

#include"g-cancellable.h"

void presst(GObject* quelle, GAsyncResult* res, gpointer user_data)
{
      GtkAlertDialog *dialog = GTK_ALERT_DIALOG(quelle);
      GError *err = NULL;
      int button = gtk_alert_dialog_choose_finish (dialog, res, &err);

     if (err) 
     {
                g_print("An error occured!\n");
                g_print("Error Message: %s\n", err->message);
                g_free(err);
                return;
     }

     if (button == 1) 
        g_print("Cancel\n");
     if (button == 0)
        g_print("O.k.\n");
      
    g_object_unref(dialog);  // GtkAlertDialog dispose.
}

void clicked (GtkWidget *button, gpointer user_data)
{
    GtkWidget* box =gtk_widget_get_parent(button);
    GtkWidget* window = gtk_widget_get_parent(box);

    GCancellable *cancel = G_CANCELLABLE(user_data);

    GtkAlertDialog* alert_dialog = gtk_alert_dialog_new (
                                  "DANGER!\nA mistake\n");

   const char* buttons[] = {"O.k.","Cancel",NULL};

   gtk_alert_dialog_set_buttons(alert_dialog,buttons);
   // Esc - Button 
   gtk_alert_dialog_set_cancel_button (alert_dialog,1);
   // Enter - Button
   gtk_alert_dialog_set_default_button(alert_dialog,0);

   // Dialog 
   gtk_alert_dialog_choose (alert_dialog,
                   GTK_WINDOW(window),  
                   G_CANCELLABLE(cancel),  // Which function ??
                   (GAsyncReadyCallback)presst,  
                   NULL);
}

void activate (GtkApplication *app, gpointer data)
{
  GtkWidget *window;

  window =gtk_application_window_new(app);
  gtk_widget_set_size_request(window,50,50);
 
  GCancellable*  cancel = g_cancellable_new ();

  GtkWidget *button = gtk_button_new_with_label("Click me");
  g_signal_connect(button,"clicked",G_CALLBACK(clicked),cancel);
  GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,10);
  gtk_box_append(GTK_BOX(box),button);
  gtk_window_set_child(GTK_WINDOW(window),box);

  gtk_widget_set_visible(window,TRUE);
}

Can anyone help me here?


Solution

  • GCancellable is an object that is intended to stop a process. 4 steps in principle are necessary for this:

    Step 1 Create GCancellable-Object:

    GCancellable*  cancel = g_cancellable_new ();
    

    Step 2 Connect the GCancellable-Object to a process:

     // Dialog 
      gtk_alert_dialog_choose (alert_dialog,
                       GTK_WINDOW(window),  
                       G_CANCELLABLE(cancel),  // connecting to gcancellable
                      (GAsyncReadyCallback)user_action, // for user reaction 
                       cancel);
    }
    

    Step 3 Connect the signal emitting from GCancellable

    g_cancellable_connect(cancel,
                            G_CALLBACK(gecancelld), // unused 
                            GINT_TO_POINTER(timer),
                            (GDestroyNotify) timer_destroy_func); // destroy timer
                                                           // if GCancellable is
                                                           // unref 
    

    Step 4 set GCancellable to cancelled, to cancel the process.

        g_cancellable_cancel(cancel);
        g_object_unref(cancel);  // GCancellable dispose  
    

    In connection with GtkAlertDialog, this can now be used as follows:

    #include"g-cancellable.h"
    
    // if timeout
    gboolean time_out(gpointer user_data)
    {
        GCancellable *cancel = G_CANCELLABLE(user_data);
        g_cancellable_cancel(cancel);
        g_object_unref(cancel);
        return TRUE;
    }
    
    // for user interaction
    void user_action(GObject* quelle, GAsyncResult* res, gpointer user_data)
    {
          GtkAlertDialog *dialog = GTK_ALERT_DIALOG(quelle);
          GError *err = NULL;
          int button = gtk_alert_dialog_choose_finish (dialog, res, &err);
    
         if (err) 
         {
                    g_print("An error occured!\n");
                    g_print("Error Message: %s\n", err->message);
                    g_free(err);
                    g_object_unref(dialog);
                    return;
         }
    
         if (button == 1) 
            g_print("Cancel\n");
         if (button == 0)
            g_print("O.k.\n");
          
        GCancellable *cancel = G_CANCELLABLE(user_data);
        g_cancellable_cancel(cancel);
        g_object_unref(cancel);  // GCancellable dispose  
        g_object_unref(dialog);  // GtkAlertDialog dispose.
    }
    
    void timer_destroy_func(gpointer data)
    {
        guint timer = GPOINTER_TO_INT(data);
        g_source_remove(timer);
    }
    
    void gecancelld()
    {
        // unused
    };
    
    void dialog_called (GtkWidget *button, gpointer user_data)
    {
      GtkWidget* box =gtk_widget_get_parent(button);
      GtkWidget* window = gtk_widget_get_parent(box);
      // create Object GCancellable
      GCancellable*  cancel = g_cancellable_new ();
     
      guint timer = g_timeout_add(10000, G_SOURCE_FUNC(time_out), (gpointer)cancel);
    
      g_cancellable_connect(cancel,
                            G_CALLBACK(gecancelld), // unused 
                            GINT_TO_POINTER(timer),
                            (GDestroyNotify) timer_destroy_func); // destroy timer
                                      // if GCancellable is
                                      // unref 
      GtkAlertDialog* alert_dialog = gtk_alert_dialog_new (
                                      "DANGER!\nA mistake\n");
    
      const char* buttons[] = {"O.k.","Cancel",NULL};
    
      gtk_alert_dialog_set_buttons(alert_dialog,buttons);
      // Esc - Button 
      gtk_alert_dialog_set_cancel_button (alert_dialog,1);
      // Enter - Button
      gtk_alert_dialog_set_default_button(alert_dialog,0);
      // Dialog 
      gtk_alert_dialog_choose (alert_dialog,
                       GTK_WINDOW(window),  
                       G_CANCELLABLE(cancel),  // connecting to gcancellable
                       (GAsyncReadyCallback)user_action, // for user reaction 
                       cancel);
    }
    
    void activate (GtkApplication *app, gpointer data)
    {
      GtkWidget *window;
    
      window =gtk_application_window_new(app);
      gtk_widget_set_size_request(window,50,50);
    
      GtkWidget *button = gtk_button_new_with_label("Click me");
      g_signal_connect(button,"clicked",G_CALLBACK(dialog_called),NULL);
      GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,10);
      gtk_box_append(GTK_BOX(box),button);
      gtk_window_set_child(GTK_WINDOW(window),box);
    
      gtk_widget_set_visible(window,TRUE);
    }
    

    The program section shows a GtkAlertDialog, which, if the user does not react, is closed again after a timeout. At the same time, an error message is issued, which can then be used in the program.

    Enjoy testing and programming.