summaryrefslogtreecommitdiff
path: root/src/gtkext/gtkextstatusbar.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-06-08 12:37:43 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-06-08 12:37:43 (GMT)
commit05a0e578f49fbd7c8614ce108ba790601663d8cd (patch)
treef2530f7dfeeff19e7d689bbb55830456e06de66a /src/gtkext/gtkextstatusbar.c
parentc23e671df7621ad85f590eee14e6fa7c7e71a526 (diff)
Removed all usages of gdk_threads_enter()/gdk_threads_leave() in the status bar.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@349 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext/gtkextstatusbar.c')
-rw-r--r--src/gtkext/gtkextstatusbar.c342
1 files changed, 292 insertions, 50 deletions
diff --git a/src/gtkext/gtkextstatusbar.c b/src/gtkext/gtkextstatusbar.c
index 47fc154..9ac2aaf 100644
--- a/src/gtkext/gtkextstatusbar.c
+++ b/src/gtkext/gtkextstatusbar.c
@@ -2,7 +2,7 @@
/* OpenIDA - Outil d'analyse de fichiers binaires
* gtkextstatusbar.h - prototypes pour la barre de statut améliorée
*
- * Copyright (C) 2009-2012 Cyrille Bagard
+ * Copyright (C) 2009-2013 Cyrille Bagard
*
* This file is part of OpenIDA.
*
@@ -29,6 +29,45 @@
+/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
+
+
+/* Elément de statut */
+typedef struct _bar_item
+{
+ char *message; /* Message à afficher */
+ bool is_progressive; /* Utilisations de progression */
+ double value; /* Valeur courante */
+
+ size_t index; /* Valeur pour l'identifiant */
+
+} bar_item;
+
+
+/* Abstration d'une gestion de barre de statut (instance) */
+struct _GtkExtStatusBar
+{
+ GtkStatusbar bar; /* Présence obligatoire en 1er */
+
+ guint context; /* Nouvel identifiant */
+ guint cur_msg; /* Message courant */
+
+ GtkProgressBar *progress; /* Barre de progression */
+
+ bar_item *stack; /* Pile de statut de la barre */
+ size_t stack_size; /* Taille de la pile */
+ GMutex stack_access; /* Accès en à la pile */
+
+};
+
+/* Abstration d'une gestion de barre de statut (classe) */
+struct _GtkExtStatusBarClass
+{
+ GtkStatusbarClass parent_class; /* Présence obligatoire en 1er */
+
+};
+
+
/* Initialise la classe des barres de statut améliorées. */
static void gtk_extended_status_bar_class_init(GtkExtStatusBarClass *);
@@ -37,6 +76,45 @@ static void gtk_extended_status_bar_init(GtkExtStatusBar *);
+/* ----------------------- MISES A JOUR EN CONTEXTE PRINCIPAL ----------------------- */
+
+
+/* Type de commande */
+typedef enum _DelayedUpdateCmd
+{
+ DUC_CHANGE_CONTENT, /* Elément ajouté ou retiré */
+ DUC_UPDATE_ACTIVITY /* Mise à jour de progression */
+
+} DelayedUpdateCmd;
+
+/* Transfert des commandes */
+typedef struct _bar_update_info
+{
+ GtkExtStatusBar *bar; /* Barre associée */
+ DelayedUpdateCmd cmd; /* Type de commande */
+
+} bar_update_info;
+
+
+/* Met à jour la partie graphique de la barre de statut. */
+static gboolean gtk_extended_status_update(bar_update_info *);
+
+/* Libère la mémoire occupée par la transmission. */
+static void free_bar_update_info(bar_update_info *);
+
+/* Place un nouveau message dans la barre de statut. */
+static void _gtk_extended_status_bar_change_content(GtkExtStatusBar *);
+
+/* Met à jour la barre de progression de la barre de statut. */
+static void _gtk_extended_status_bar_update_activity(GtkExtStatusBar *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION EXTERIEURE DE LA BARRE */
+/* ---------------------------------------------------------------------------------- */
+
+
/* Détermine le type de la barre de statut améliorée. */
G_DEFINE_TYPE(GtkExtStatusBar, gtk_extended_status_bar, GTK_TYPE_STATUSBAR)
@@ -84,6 +162,8 @@ static void gtk_extended_status_bar_init(GtkExtStatusBar *bar)
gtk_box_pack_start(GTK_BOX(bar), GTK_WIDGET(bar->progress), FALSE, FALSE, 4);
+ g_mutex_init(&bar->stack_access);
+
}
@@ -120,33 +200,39 @@ GtkWidget *gtk_extended_status_bar_new(void)
* *
******************************************************************************/
-guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, gboolean progressive)
+bstatus_id_t gtk_extended_status_bar_push(GtkExtStatusBar *bar, const char *message, bool progressive)
{
- guint result; /* Identifiant à retourner */
+ bstatus_id_t result; /* Identifiant à retourner */
+ size_t index; /* Indice du nouvel élément */
+ bar_update_info *info; /* Informations à mémoriser */
- //gdk_threads_enter();
+ /* Mise à jour de la pile */
- result = gtk_statusbar_push(GTK_STATUSBAR(bar), bar->context, message);
+ g_mutex_lock(&bar->stack_access);
- bar->msg_count++;
- bar->msg_id = (guint *)realloc(bar->msg_id, bar->msg_count * sizeof(guint));
- bar->is_progressive = (gboolean *)realloc(bar->is_progressive, bar->msg_count * sizeof(gboolean));
+ bar->stack = (bar_item *)realloc(bar->stack, ++bar->stack_size * sizeof(bar_item));
- bar->msg_id[bar->msg_count - 1] = result;
- bar->is_progressive[bar->msg_count - 1] = progressive;
+ index = bar->stack_size - 1;
- if (progressive)
- {
- gtk_progress_bar_set_fraction(bar->progress, 0.0);
- gtk_progress_bar_set_text(bar->progress, "0%");
+ bar->stack[index].message = strdup(message);
+ bar->stack[index].is_progressive = progressive;
+ bar->stack[index].value = 0.0;
+ bar->stack[index].index = index;
- gtk_widget_show(GTK_WIDGET(bar->progress));
+ result = &bar->stack[index].index;
- }
- else gtk_widget_hide(GTK_WIDGET(bar->progress));
+ g_mutex_unlock(&bar->stack_access);
- //gdk_flush();
- //gdk_threads_leave();
+ /* Mise à jour de l'affichage */
+
+ info = (bar_update_info *)calloc(1, sizeof(bar_update_info));
+
+ info->bar = bar;
+ g_object_ref(G_OBJECT(bar));
+ info->cmd = DUC_CHANGE_CONTENT;
+
+ gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)gtk_extended_status_update,
+ info, (GDestroyNotify)free_bar_update_info);
return result;
@@ -167,28 +253,28 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g
* *
******************************************************************************/
-void gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar, guint id, gdouble value)
+void gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar, bstatus_id_t id, double value)
{
- gchar percent[5]; /* Pourcentage en version txt. */
+ bar_update_info *info; /* Informations à mémoriser */
- if (bar->msg_count == 0) return;
+ /* Mise à jour de la pile */
- if (id == bar->msg_id[bar->msg_count - 1] && bar->is_progressive[bar->msg_count - 1])
- {
- if (value != 1.0 && value - gtk_progress_bar_get_fraction(bar->progress) < 0.01)
- return;
+ g_mutex_lock(&bar->stack_access);
- g_snprintf(percent, 5, "%.0f%%", value * 100);
+ bar->stack[*id].value = value;
- gdk_threads_enter();
+ g_mutex_unlock(&bar->stack_access);
- gtk_progress_bar_set_fraction(bar->progress, value);
- gtk_progress_bar_set_text(bar->progress, percent);
+ /* Mise à jour de l'affichage */
- gdk_flush();
- gdk_threads_leave();
+ info = (bar_update_info *)calloc(1, sizeof(bar_update_info));
- }
+ info->bar = bar;
+ g_object_ref(G_OBJECT(bar));
+ info->cmd = DUC_UPDATE_ACTIVITY;
+
+ gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)gtk_extended_status_update,
+ info, (GDestroyNotify)free_bar_update_info);
}
@@ -206,35 +292,191 @@ void gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar, guint id, gdo
* *
******************************************************************************/
-void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id)
+void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, bstatus_id_t id)
{
+ size_t index; /* Indice de l'élément visé */
size_t i; /* Boucle de parcours */
+ bar_update_info *info; /* Informations à mémoriser */
- //gdk_threads_enter();
+ /* Mise à jour de la pile */
- gtk_statusbar_remove(GTK_STATUSBAR(bar), bar->context, id);
+ g_mutex_lock(&bar->stack_access);
- for (i = 0; i < bar->msg_count; i++)
- if (bar->msg_id[i] == id)
- break;
+ index = *id;
- if ((i + 1) < bar->msg_count)
+ free(bar->stack[index].message);
+
+ if ((index + 1) < bar->stack_size)
{
- memmove(&bar->msg_id[i], &bar->msg_id[i + 1], (bar->msg_count - i - 1) * sizeof(guint));
- memmove(&bar->is_progressive[i], &bar->is_progressive[i + 1], (bar->msg_count - i - 1) * sizeof(gboolean));
+ memmove(&bar->stack[index], &bar->stack[index + 1],
+ (bar->stack_size - index - 1) * sizeof(bar_item));
+
+ for (i = index; i < bar->stack_size; i++)
+ bar->stack[i].index = i;
+
}
- bar->msg_count--;
- bar->msg_id = (guint *)realloc(bar->msg_id, bar->msg_count * sizeof(guint));
- bar->is_progressive = (gboolean *)realloc(bar->is_progressive, bar->msg_count * sizeof(gboolean));
+ bar->stack = (bar_item *)realloc(bar->stack, --bar->stack_size * sizeof(bar_item));
- if (bar->msg_count > 0 && bar->is_progressive[bar->msg_count - 1])
- gtk_widget_show(GTK_WIDGET(bar->progress));
+ g_mutex_unlock(&bar->stack_access);
- else
+ /* Mise à jour de l'affichage */
+
+ info = (bar_update_info *)calloc(1, sizeof(bar_update_info));
+
+ info->bar = bar;
+ g_object_ref(G_OBJECT(bar));
+ info->cmd = DUC_CHANGE_CONTENT;
+
+ gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)gtk_extended_status_update,
+ info, (GDestroyNotify)free_bar_update_info);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MISES A JOUR EN CONTEXTE PRINCIPAL */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à consulter pour l'opération. *
+* *
+* Description : Met à jour la partie graphique de la barre de statut. *
+* *
+* Retour : FALSE pour faire disparaître la mise à jour ensuite. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_extended_status_update(bar_update_info *info)
+{
+ switch (info->cmd)
+ {
+ case DUC_CHANGE_CONTENT:
+ _gtk_extended_status_bar_change_content(info->bar);
+ /*break;*/
+
+ case DUC_UPDATE_ACTIVITY:
+ _gtk_extended_status_bar_update_activity(info->bar);
+ break;
+
+ }
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à libérer de la mémoire. *
+* *
+* Description : Libère la mémoire occupée par la transmission. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void free_bar_update_info(bar_update_info *info)
+{
+ g_object_unref(G_OBJECT(info->bar));
+
+ free(info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bar = barre de statut à manipuler. *
+* *
+* Description : Place un nouveau message dans la barre de statut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void _gtk_extended_status_bar_change_content(GtkExtStatusBar *bar)
+{
+ size_t top; /* Indice de l'élément visé */
+
+ g_mutex_lock(&bar->stack_access);
+
+ if (bar->cur_msg > 0)
+ gtk_statusbar_remove(GTK_STATUSBAR(bar), bar->context, bar->cur_msg);
+
+ if (bar->stack_size == 0)
gtk_widget_hide(GTK_WIDGET(bar->progress));
- //gdk_flush();
- //gdk_threads_leave();
+ else
+ {
+ top = bar->stack_size - 1;
+
+ bar->cur_msg = gtk_statusbar_push(GTK_STATUSBAR(bar), bar->context,
+ bar->stack[top].message);
+
+ if (bar->stack[top].is_progressive)
+ gtk_widget_show(GTK_WIDGET(bar->progress));
+ else
+ gtk_widget_hide(GTK_WIDGET(bar->progress));
+
+ }
+
+ g_mutex_unlock(&bar->stack_access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bar = barre de statut à manipuler. *
+* *
+* Description : Met à jour la barre de progression de la barre de statut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void _gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar)
+{
+ size_t top; /* Indice de l'élément visé */
+ double value; /* Valeur à prendre en compte */
+ gchar percent[5]; /* Pourcentage en version txt. */
+
+ g_mutex_lock(&bar->stack_access);
+
+ if (bar->stack_size > 0)
+ {
+ top = bar->stack_size - 1;
+
+ if (bar->stack[top].is_progressive)
+ {
+ value = bar->stack[top].value;
+
+ if (value != 1.0 && value - gtk_progress_bar_get_fraction(bar->progress) < 0.01)
+ goto gesbua_exit;
+
+ g_snprintf(percent, 5, "%.0f%%", value * 100);
+
+ gtk_progress_bar_set_fraction(bar->progress, value);
+ gtk_progress_bar_set_text(bar->progress, percent);
+
+ }
+
+ }
+
+ gesbua_exit:
+
+ g_mutex_unlock(&bar->stack_access);
}