diff options
Diffstat (limited to 'src/gtkext')
-rw-r--r-- | src/gtkext/gtkstatusstack.c | 471 | ||||
-rw-r--r-- | src/gtkext/gtkstatusstack.h | 26 |
2 files changed, 472 insertions, 25 deletions
diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c index 8cc85cc..9177399 100644 --- a/src/gtkext/gtkstatusstack.c +++ b/src/gtkext/gtkstatusstack.c @@ -41,7 +41,10 @@ /* Navigation au sein d'assemblage */ -typedef union _assembly_info assembly_info; +typedef struct _assembly_info assembly_info; + +/* Mémorisation des progressions */ +typedef struct _progress_info progress_info; /* Abstration d'une gestion de barre de statut (instance) */ @@ -52,6 +55,9 @@ struct _GtkStatusStack GtkWidget *asm_status; /* Barre de status d'assemblage*/ assembly_info *asm_info; /* Informations courantes */ + GtkWidget *prog_status; /* Barre de status d'activité */ + progress_info *prog_info; /* Informations courantes */ + }; /* Abstration d'une gestion de barre de statut (classe) */ @@ -83,25 +89,21 @@ static void gtk_status_stack_switch(GtkStatusStack *, GtkWidget *); /* Navigation au sein d'assemblage */ -union _assembly_info +struct _assembly_info { bool reset; /* Réinitialisation */ - struct - { - mrange_t current; /* Emplacement correspondant */ - - char *segment; /* Segment d'appartenance */ + mrange_t current; /* Emplacement correspondant */ - VMPA_BUFFER(phys); /* Localisation physique */ - VMPA_BUFFER(virt); /* Localisation virtuelle */ + char *segment; /* Segment d'appartenance */ - char *symbol; /* Eventuel symbole concerné */ + VMPA_BUFFER(phys); /* Localisation physique */ + VMPA_BUFFER(virt); /* Localisation virtuelle */ - const char *encoding; /* Encodage de l'instruction */ - phys_t size; /* Taille de l'instruction */ + char *symbol; /* Eventuel symbole concerné */ - }; + const char *encoding; /* Encodage de l'instruction */ + phys_t size; /* Taille de l'instruction */ }; @@ -119,7 +121,45 @@ static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *); /* S'assure de l'affichage à jour de la partie "assemblage". */ -static void gtk_status_stack_show_current_instruction(GtkStatusStack *); +static gboolean gtk_status_stack_show_current_instruction(GtkStatusStack *); + + + +/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */ + + +/* Informations de progression */ +typedef struct _progress_status +{ + activity_id_t id; /* Identifiant unique */ + + char *message; /* Indication à faire valoir */ + double value; /* Centième de pourcentage */ + +} progress_status; + +/* Mémorisation des progressions */ +struct _progress_info +{ + activity_id_t generator; /* Générateur de séquence */ + + progress_status *statuses; /* Statuts de progression */ + size_t count; /* Nombre de ces statuts */ + GMutex access; /* Accès à la pile */ + + guint tag; /* Identifiant de mise à jour */ + +}; + + +/* Supprime l'empreinte mémoire d'informations d'activité. */ +static void reset_progress_info(progress_info *); + +/* Construit une barre d'état pour un suivi d'activité. */ +static GtkWidget *build_progress_status_stack(GtkStatusStack *); + +/* S'assure de l'affichage à jour de la partie "activité". */ +static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *); @@ -175,6 +215,11 @@ static void gtk_status_stack_init(GtkStatusStack *stack) reset_assembly_info(stack->asm_info); + stack->prog_status = build_progress_status_stack(stack); + stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info)); + + reset_progress_info(stack->prog_info); + } @@ -214,9 +259,11 @@ static void gtk_status_stack_dispose(GtkStatusStack *stack) static void gtk_status_stack_finalize(GtkStatusStack *stack) { reset_assembly_info(stack->asm_info); - free(stack->asm_info); + reset_progress_info(stack->prog_info); + free(stack->prog_info); + G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack)); } @@ -564,7 +611,7 @@ void gtk_status_stack_update_current_instruction(GtkStatusStack *stack, const GL /****************************************************************************** * * -* Paramètres : stack = barre de statut à actualiser. * +* Paramètres : stack = barre de statut à actualiser. * * * * Description : Réinitialise les informations associées une position. * * * @@ -593,13 +640,13 @@ void gtk_status_stack_reset_current_instruction(GtkStatusStack *stack) * * * Description : S'assure de l'affichage à jour de la partie "assemblage". * * * -* Retour : - * +* Retour : G_SOURCE_REMOVE pour une exécution unique. * * * * Remarques : - * * * ******************************************************************************/ -static void gtk_status_stack_show_current_instruction(GtkStatusStack *stack) +static gboolean gtk_status_stack_show_current_instruction(GtkStatusStack *stack) { GObject *ref; /* Espace de référencements */ assembly_info *info; /* Informations à consulter */ @@ -677,4 +724,392 @@ static void gtk_status_stack_show_current_instruction(GtkStatusStack *stack) } + return G_SOURCE_REMOVE; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* STATUT DES SUIVIS D'ACTIVITE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : info = informations à réinitialiser. * +* * +* Description : Supprime l'empreinte mémoire d'informations d'activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void reset_progress_info(progress_info *info) +{ + size_t i; /* Boucle de parcours */ + + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = 0; + + for (i = 0; i < info->count; i++) + { + if (info->statuses[i].message != NULL) + free(info->statuses[i].message); + } + + if (info->statuses != NULL) + { + free(info->statuses); + info->statuses = NULL; + } + + info->count = 0; + + g_mutex_init(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = composant global en cours de construction. * +* * +* Description : Construit une barre d'état pour un suivi d'activité. * +* * +* Retour : Composant GTK mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GtkWidget *build_progress_status_stack(GtkStatusStack *stack) +{ + GtkWidget *result; /* Support à retourner */ + GObject *ref; /* Espace de référencements */ + GtkWidget *progress; /* Barre de progression */ + GtkWidget *label; /* Désignation de l'activité */ + + result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_show(result); + + ref = G_OBJECT(result); + + progress = gtk_progress_bar_new(); + g_object_set_data(ref, "progress", progress); + gtk_widget_set_size_request(progress, 200, -1); + gtk_widget_show(progress); + gtk_box_pack_start(GTK_BOX(result), progress, FALSE, TRUE, 8); + + label = qck_create_label(ref, "message", NULL); + gtk_box_pack_start(GTK_BOX(result), label, TRUE, TRUE, 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* msg = nouveau message de statut à copier. * +* value = nouvelle valeur pour une progression donnée. * +* * +* Description : Démarre le suivi d'une nouvelle activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, double value) +{ + activity_id_t result; /* Numéro unique à renvoyer */ + progress_info *info; /* Informations à consulter */ + size_t new; /* Indice de l'activité créée */ + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + result = ++info->generator; + + new = info->count++; + + info->statuses = (progress_status *)realloc(info->statuses, + info->count * sizeof(progress_status)); + + info->statuses[new].id = new; + + /* Intitulé */ + + if (msg == NULL) + info->statuses[new].message = NULL; + else + info->statuses[new].message = strdup(msg); + + /* Valeur */ + + info->statuses[new].value = value; + + /* Actualisation */ + + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + g_mutex_unlock(&info->access); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* id = identifiant de l'activité à cibler. * +* msg = nouveau message de statut à copier. * +* value = nouvelle valeur pour une progression donnée. * +* * +* Description : Actualise les informations concernant une activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg, double value) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + bool msg_changed; /* Changement d'intitulé */ + double old; /* Conservation pour la diff. */ + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + if (i < info->count) + { + /* Intitulé */ + + if (info->statuses[i].message != NULL) + { + if (msg == NULL) + msg_changed = true; + else + msg_changed = (strcmp(info->statuses[i].message, msg) != 0); + + free(info->statuses[i].message); + + } + else + msg_changed = (msg != NULL); + + if (msg == NULL) + info->statuses[i].message = NULL; + else + info->statuses[i].message = strdup(msg); + + /* Valeur */ + + old = info->statuses[i].value; + + info->statuses[i].value = value; + + /* On n'actualise que le sommet de la pile */ + + if ((i + 1) == info->count && (msg_changed || (value - old) > 1.0)) + { + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + } + + } + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* id = identifiant de l'activité à cibler. * +* value = nouvelle valeur pour une progression donnée. * +* * +* Description : Actualise la progression d'une activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, double value) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + double old; /* Conservation pour la diff. */ + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + if (i < info->count) + { + /* Valeur */ + + old = info->statuses[i].value; + + info->statuses[i].value = value; + + /* On n'actualise que le sommet de la pile */ + + if ((i + 1) == info->count && (value - old) > 1.0) + { + if (info->tag != 0) + g_source_remove(info->tag); + + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + } + + } + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = barre de statut à actualiser. * +* * +* Description : Met fin au suivi d'une activité donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) +{ + progress_info *info; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + + info = stack->prog_info; + + g_mutex_lock(&info->access); + + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + break; + + if (i < info->count) + { + if (info->tag != 0) + g_source_remove(info->tag); + + if (info->statuses[i].message != NULL) + free(info->statuses[i].message); + + if (info->count == 1) + { + free(info->statuses); + info->statuses = NULL; + } + else + { + memmove(&info->statuses[i], &info->statuses[i + 1], + (info->count - i - 1) * sizeof(progress_status)); + + info->statuses = (progress_status *)realloc(info->statuses, + (info->count - 1) * sizeof(progress_status)); + + } + + info->count--; + + if (info->count == 0) + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_instruction, stack); + else + info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + + } + + g_mutex_unlock(&info->access); + +} + + +/****************************************************************************** +* * +* Paramètres : stack = pile de statuts à manipuler. * +* * +* Description : S'assure de l'affichage à jour de la partie "activité". * +* * +* Retour : G_SOURCE_REMOVE pour une exécution unique. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack) +{ + GObject *ref; /* Espace de référencements */ + progress_info *info; /* Informations à consulter */ + progress_status *last; /* Dernier statut à traiter */ + GtkProgressBar *progress; /* Barre de progression */ + GtkLabel *label; /* Désignation de l'activité */ + + if (!g_source_is_destroyed(g_main_current_source())) + { + gtk_status_stack_switch(stack, stack->prog_status); + + ref = G_OBJECT(stack->prog_status); + info = stack->prog_info; + + g_mutex_lock(&info->access); + + info->tag = 0; + + if (info->count > 0) + { + last = &info->statuses[info->count - 1]; + + progress = GTK_PROGRESS_BAR(g_object_get_data(ref, "progress")); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), last->value); + + label = GTK_LABEL(g_object_get_data(ref, "message")); + gtk_label_set_text(label, last->message); + + } + + g_mutex_unlock(&info->access); + + } + + return G_SOURCE_REMOVE; + } diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/gtkstatusstack.h index 8e93708..afc3213 100644 --- a/src/gtkext/gtkstatusstack.h +++ b/src/gtkext/gtkstatusstack.h @@ -25,7 +25,6 @@ #define _GTKEXT_GTKSTATUSSTACK_H - #include <gtk/gtk.h> @@ -33,12 +32,6 @@ -/* FIXME */ -typedef int bstatus_id_t; - - - - /* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */ @@ -76,6 +69,25 @@ void gtk_status_stack_reset_current_instruction(GtkStatusStack *); +/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */ + + +/* Identifiant unique de rapport de progression */ +typedef unsigned long activity_id_t; + + +/* Démarre le suivi d'une nouvelle activité. */ +activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, double); + +/* Actualise les informations concernant une activité. */ +void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *, double); + +/* Actualise la progression d'une activité. */ +void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, double); + +/* Met fin au suivi d'une activité donnée. */ +void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t); + #endif /* _GTKEXT_GTKSTATUSSTACK_H */ |