diff options
Diffstat (limited to 'src/gtkext')
-rw-r--r-- | src/gtkext/gtkextstatusbar.c | 342 | ||||
-rw-r--r-- | src/gtkext/gtkextstatusbar.h | 41 |
2 files changed, 302 insertions, 81 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); } diff --git a/src/gtkext/gtkextstatusbar.h b/src/gtkext/gtkextstatusbar.h index b5fe210..3c3da60 100644 --- a/src/gtkext/gtkextstatusbar.h +++ b/src/gtkext/gtkextstatusbar.h @@ -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. * @@ -25,44 +25,26 @@ #define _GTKEXT_GTKEXTSTATUSBAR_H +#include <stdbool.h> #include <gtk/gtk.h> -G_BEGIN_DECLS - - - #define GTK_TYPE_EXT_STATUS_BAR (gtk_extended_status_bar_get_type()) #define GTK_EXT_STATUS_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, gtk_extended_status_bar_get_type (), GtkExtStatusBar)) #define GTK_IS_EXT_STATUS_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, gtk_extended_status_bar_get_type())) #define GTK_EXT_STATUS_BAR_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, gtk_extended_status_bar_get_type(), GtkExtStatusBarClass)) +/* Abstration d'une gestion de barre de statut (instance) */ typedef struct _GtkExtStatusBar GtkExtStatusBar; -typedef struct _GtkExtStatusBarClass GtkExtStatusBarClass; - - - -struct _GtkExtStatusBar -{ - GtkStatusbar bar; /* Présence obligatoire en 1er */ - guint context; /* Nouvel identifiant */ - - GtkProgressBar *progress; /* Barre de progression */ - - guint *msg_id; /* Liste des identifiants */ - gboolean *is_progressive; /* Utilisations de progression */ - size_t msg_count; /* Nombre de messages empilés */ - -}; +/* Abstration d'une gestion de barre de statut (classe) */ +typedef struct _GtkExtStatusBarClass GtkExtStatusBarClass; -struct _GtkExtStatusBarClass -{ - GtkStatusbarClass parent_class; /* Présence obligatoire en 1er */ -}; +/* Identifiant d'un message de statut */ +typedef size_t * bstatus_id_t; /* Détermine le type de la barre de statut améliorée. */ @@ -72,17 +54,14 @@ GType gtk_extended_status_bar_get_type(void); GtkWidget *gtk_extended_status_bar_new(void); /* Place un nouveau message dans la barre de statut. */ -guint gtk_extended_status_bar_push(GtkExtStatusBar *, const gchar *, gboolean); +bstatus_id_t gtk_extended_status_bar_push(GtkExtStatusBar *, const gchar *, bool); /* Met à jour la barre de progression de la barre de statut. */ -void gtk_extended_status_bar_update_activity(GtkExtStatusBar *, guint, gdouble); +void gtk_extended_status_bar_update_activity(GtkExtStatusBar *, bstatus_id_t, double); /* Retire de la barre un statut, visible ou non. */ -void gtk_extended_status_bar_remove(GtkExtStatusBar *, guint); - - +void gtk_extended_status_bar_remove(GtkExtStatusBar *, bstatus_id_t); -G_END_DECLS #endif /* _GTKEXT_GTKEXTSTATUSBAR_H */ |