[gimp] app: update a GimpMessageBox repeated in a idle function.



commit 110779eba3cc24e09d9e4d369bbec705230a1477
Author: Jehan <jehan girinstud io>
Date:   Sat Feb 3 22:37:47 2018 +0100

    app: update a GimpMessageBox repeated in a idle function.
    
    I was directed by Massimo to some bug which was repeatedly generating
    dozens of thousands of GEGL WARNINGs and that was completely taking over
    the GUI if redirected to GimpErrorDialog. Currently GEGL warnings are
    not redirected there, but the problem is still there, and we don't want
    GIMP warnings to freeze the whole GUI either.
    So only increment the repeat variable upon gimp_message_box_repeat() and
    delay actual GUI update to a later low-priority idle function.

 app/widgets/gimpmessagebox.c |   72 +++++++++++++++++++++++++++++-------------
 app/widgets/gimpmessagebox.h |    2 +
 2 files changed, 52 insertions(+), 22 deletions(-)
---
diff --git a/app/widgets/gimpmessagebox.c b/app/widgets/gimpmessagebox.c
index f67205e..249b151 100644
--- a/app/widgets/gimpmessagebox.c
+++ b/app/widgets/gimpmessagebox.c
@@ -73,6 +73,7 @@ static void   gimp_message_box_set_label_markup (GimpMessageBox *box,
                                                  const gchar    *format,
                                                  va_list         args) G_GNUC_PRINTF (3, 0);
 
+static gboolean gimp_message_box_update         (gpointer        data);
 
 G_DEFINE_TYPE (GimpMessageBox, gimp_message_box, GTK_TYPE_BOX)
 
@@ -144,6 +145,7 @@ gimp_message_box_init (GimpMessageBox *box)
 
   box->repeat   = 0;
   box->label[2] = NULL;
+  box->idle_id  = 0;
 }
 
 static void
@@ -185,6 +187,10 @@ gimp_message_box_finalize (GObject *object)
 {
   GimpMessageBox *box = GIMP_MESSAGE_BOX (object);
 
+  if (box->idle_id)
+    g_source_remove (box->idle_id);
+  box->idle_id = 0;
+
   if (box->icon_name)
     {
       g_free (box->icon_name);
@@ -378,6 +384,40 @@ gimp_message_box_set_label_markup (GimpMessageBox *box,
     }
 }
 
+static gboolean
+gimp_message_box_update (gpointer data)
+{
+  GimpMessageBox *box = data;
+  gchar          *message;
+
+  box->idle_id = 0;
+
+  message = g_strdup_printf (ngettext ("Message repeated once.",
+                                       "Message repeated %d times.",
+                                       box->repeat),
+                             box->repeat);
+
+  if (box->label[2])
+    {
+      gtk_label_set_text (GTK_LABEL (box->label[2]), message);
+    }
+  else
+    {
+      GtkWidget *label = box->label[2] = gtk_label_new (message);
+
+      gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+      gimp_label_set_attributes (GTK_LABEL (label),
+                                 PANGO_ATTR_STYLE, PANGO_STYLE_OBLIQUE,
+                                 -1);
+      gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+    }
+
+  g_free (message);
+
+  return G_SOURCE_REMOVE;
+}
+
 /*  public functions  */
 
 GtkWidget *
@@ -433,34 +473,22 @@ gimp_message_box_set_markup (GimpMessageBox *box,
 gint
 gimp_message_box_repeat (GimpMessageBox *box)
 {
-  gchar *message;
-
   g_return_val_if_fail (GIMP_IS_MESSAGE_BOX (box), 0);
 
   box->repeat++;
 
-  message = g_strdup_printf (ngettext ("Message repeated once.",
-                                       "Message repeated %d times.",
-                                       box->repeat),
-                             box->repeat);
-
-  if (box->label[2])
+  if (box->idle_id == 0)
     {
-      gtk_label_set_text (GTK_LABEL (box->label[2]), message);
+      /* When a same message is repeated dozens of thousands of times in
+       * a short span of time, updating the GUI at each increment is
+       * extremely slow (like really really slow, your GUI gets stuck
+       * for 10 minutes). So let's just delay GUI update as a low
+       * priority idle task.
+       */
+      box->idle_id = g_idle_add_full (G_PRIORITY_LOW,
+                                      gimp_message_box_update,
+                                      box, NULL);
     }
-  else
-    {
-      GtkWidget *label = box->label[2] = gtk_label_new (message);
-
-      gtk_label_set_xalign (GTK_LABEL (label), 0.0);
-      gimp_label_set_attributes (GTK_LABEL (label),
-                                 PANGO_ATTR_STYLE, PANGO_STYLE_OBLIQUE,
-                                 -1);
-      gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
-      gtk_widget_show (label);
-    }
-
-  g_free (message);
 
   return box->repeat;
 }
diff --git a/app/widgets/gimpmessagebox.h b/app/widgets/gimpmessagebox.h
index 7ebd413..5a3a49d 100644
--- a/app/widgets/gimpmessagebox.h
+++ b/app/widgets/gimpmessagebox.h
@@ -42,6 +42,8 @@ struct _GimpMessageBox
   gint       repeat;
   GtkWidget *label[3];
   GtkWidget *image;
+
+  guint      idle_id;
 };
 
 struct _GimpMessageBoxClass


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]