summaryrefslogtreecommitdiff
path: root/src/gtkext
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-03-27 20:26:06 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-03-27 20:26:06 (GMT)
commit33906ce366efc053dee0b76d5bd668797b99071e (patch)
treed04f37f89df4a0e7b2e7c2055138005707244f87 /src/gtkext
parent4bc86c5dc8d3cfa9780103b56f52024a49913c22 (diff)
Added a section in the status bar to display activity progress.
Diffstat (limited to 'src/gtkext')
-rw-r--r--src/gtkext/gtkstatusstack.c471
-rw-r--r--src/gtkext/gtkstatusstack.h26
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 */