summaryrefslogtreecommitdiff
path: root/src/gtkext/gtkstatusstack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkext/gtkstatusstack.c')
-rw-r--r--src/gtkext/gtkstatusstack.c1121
1 files changed, 0 insertions, 1121 deletions
diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c
deleted file mode 100644
index fe4e4d5..0000000
--- a/src/gtkext/gtkstatusstack.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkstatusstack.c - empilement d'informations de statut
- *
- * Copyright (C) 2015-2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gtkstatusstack.h"
-
-
-#include <assert.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include <i18n.h>
-
-
-#include "easygtk.h"
-#include "../gui/agroup.h"
-#include "../format/format.h"
-
-
-
-/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
-
-
-/* Navigation au sein d'assemblage */
-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) */
-struct _GtkStatusStack
-{
- GtkBox parent; /* A laisser en premier */
-
- GtkStack *main; /* Pile d'informations associée*/
-
- GSourceFunc def_source; /* Appel en fin d'activité */
-
- GObject *asm_ref; /* Espace de référencements #1 */
- assembly_info *asm_info; /* Informations courantes #1 */
-
- GObject *prog_ref; /* Espace de référencements #2 */
- progress_info *prog_info; /* Informations courantes #2 */
-
-};
-
-/* Abstration d'une gestion de barre de statut (classe) */
-struct _GtkStatusStackClass
-{
- GtkBoxClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des barres de statut améliorées. */
-static void gtk_status_stack_class_init(GtkStatusStackClass *);
-
-/* Initialise une instance de barre de statut améliorée. */
-static void gtk_status_stack_init(GtkStatusStack *);
-
-/* Supprime toutes les références externes. */
-static void gtk_status_stack_dispose(GtkStatusStack *);
-
-/* Procède à la libération totale de la mémoire. */
-static void gtk_status_stack_finalize(GtkStatusStack *);
-
-
-
-/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
-
-
-/* Navigation au sein d'assemblage */
-struct _assembly_info
-{
- bool reset; /* Réinitialisation */
-
- mrange_t current; /* Emplacement correspondant */
-
- char *segment; /* Segment d'appartenance */
-
- VMPA_BUFFER(phys); /* Localisation physique */
- VMPA_BUFFER(virt); /* Localisation virtuelle */
-
- char *symbol; /* Eventuel symbole concerné */
-
- const char *encoding; /* Encodage de l'instruction */
- phys_t size; /* Taille de l'instruction */
-
-};
-
-
-/* Supprime l'empreinte mémoire d'informations d'assemblage. */
-static void reset_assembly_info(assembly_info *);
-
-/* Construit une barre d'état pour language d'assemblage. */
-static GtkWidget *build_assembly_status_stack(GtkStatusStack *);
-
-/* Réagit à un redimensionnement de la barre de désassemblage. */
-static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *);
-
-/* Réagit à un clic sur l'icône de zoom. */
-static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *);
-
-/* S'assure de l'affichage à jour de la partie "assemblage". */
-static gboolean gtk_status_stack_show_current_location(GtkStatusStack *);
-
-
-
-/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */
-
-
-/* Informations de progression */
-typedef struct _progress_status
-{
- activity_id_t id; /* Identifiant unique */
-
- char *message; /* Indication à faire valoir */
-
- unsigned long current; /* Position courante */
- unsigned long max; /* Couverture à parcourir */
-
- double last_updated; /* Dernière valeur poussée */
-
-} 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 */
-
-};
-
-
-#define PROGRESS_SIZE 200
-
-
-/* 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 *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION EXTERIEURE DE LA BARRE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type de la barre de statut améliorée. */
-G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX)
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe GTK à initialiser. *
-* *
-* Description : Initialise la classe des barres de statut améliorées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_class_init(GtkStatusStackClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = instance GTK à initialiser. *
-* *
-* Description : Initialise une instance de barre de statut améliorée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_init(GtkStatusStack *stack)
-{
- GtkWidget *layer; /* Couche à empiler */
-
- gtk_orientable_set_orientation(GTK_ORIENTABLE(stack), GTK_ORIENTATION_HORIZONTAL);
-
- stack->main = GTK_STACK(gtk_stack_new());
- gtk_widget_show(GTK_WIDGET(stack->main));
- gtk_box_pack_start(GTK_BOX(stack), GTK_WIDGET(stack->main), TRUE, TRUE, 8);
-
- stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location;
-
- layer = build_assembly_status_stack(stack);
- gtk_stack_add_named(stack->main, layer, "asm_info");
-
- stack->asm_ref = G_OBJECT(layer);
- stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info));
-
- reset_assembly_info(stack->asm_info);
-
- layer = build_progress_status_stack(stack);
- gtk_stack_add_named(stack->main, layer, "prog_info");
-
- stack->prog_ref = G_OBJECT(layer);
- stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info));
-
- reset_progress_info(stack->prog_info);
-
- gtk_status_stack_reset_current_location(stack);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_dispose(GtkStatusStack *stack)
-{
- G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-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));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée une nouvelle instance de barre de statut. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkStatusStack *gtk_status_stack_new(void)
-{
- GtkStatusStack *result; /* Instance à retourner */
-
- result = g_object_new(GTK_TYPE_STATUS_STACK, NULL);
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : info = informations à réinitialiser. *
-* *
-* Description : Supprime l'empreinte mémoire d'informations d'assemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void reset_assembly_info(assembly_info *info)
-{
- info->reset = true;
-
- if (info->segment != NULL)
- {
- free(info->segment);
- info->segment = NULL;
- }
-
- if (info->symbol != NULL)
- {
- free(info->symbol);
- info->symbol = NULL;
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = composant global en cours de construction. *
-* *
-* Description : Construit une barre d'état pour language d'assemblage. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack)
-{
- GtkWidget *result; /* Support à retourner */
- GObject *ref; /* Espace de référencements */
- GtkWidget *hbox; /* Sous-division horizontale */
- GtkWidget *label; /* Etiquette pour impression */
- GtkWidget *zoom; /* Sélection du zoom courant */
-
- result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show(result);
-
- ref = G_OBJECT(result);
-
- g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref);
-
- /* Première partie : navigation */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8);
-
- label = qck_create_label(ref, "segment", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "phys", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "virt", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "offset", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- /* Seconde partie : architecture */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- g_object_set_data(ref, "arch_box", hbox);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8);
-
- label = qck_create_label(ref, "arch", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "size", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- /* Troisième partie : affichage */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8);
-
- zoom = qck_create_entry(ref, "zoom", "100%");
- gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic");
-
- g_signal_connect(zoom, "focus-in-event", G_CALLBACK(track_focus_change_in_text_area), NULL);
- g_signal_connect(zoom, "focus-out-event", G_CALLBACK(track_focus_change_in_text_area), NULL);
- g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack);
-
- gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant graphique qui vient d'évoluer. *
-* allocation = espace réservé pour le composant visé. *
-* ref = espace de référencement global. *
-* *
-* Description : Réagit à un redimensionnement de la barre de désassemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref)
-{
- GtkWidget *hbox; /* Sous-division horizontale */
-
- hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box"));
-
- gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1);
-
- /**
- * On intervient après que le containeur soit passé collecter les tailles
- * de ses enfants lors de son redimensionnement.
- *
- * Donc on force un prise en compte des changements.
- */
- gtk_container_check_resize(GTK_CONTAINER(widget));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : entry = zone de texte visée par la procédure. *
-* icon_pos = position de l'image associée à l'entrée. *
-* event = informations liées à l'événement. *
-* stack = composant graphique de gestion des statuts. *
-* *
-* Description : Réagit à un clic sur l'icône de zoom. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack)
-{
- GtkWidget *popup; /* Popup à faire surgir */
- GdkRectangle rect; /* Zone précise à cibler */
-
- if (event->button != GDK_BUTTON_PRIMARY)
- return;
-
- popup = gtk_popover_new(GTK_WIDGET(entry));
-
- gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
- gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
-
- gtk_widget_show(popup);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* range = emplacement à mettre en valeur. *
-* segment = zone de binaire d'appartenance. *
-* symbol = éventuelle position par rapport à un symbole. *
-* encoding = encodage d'une éventuelle instruction ou NULL. *
-* *
-* Description : Actualise les informations liées une position d'assemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *encoding)
-{
- assembly_info *info; /* Informations à constituer */
- const vmpa2t *addr; /* Localisation de départ */
- phys_t size; /* Taille de l'emplacement */
-
- info = stack->asm_info;
-
- /* Bascule vers une zone courante nouvelle ? */
-
- addr = get_mrange_addr(range);
- size = get_mrange_length(range);
-
- if (cmp_mrange(&info->current, range) == 0
- && info->size == size
- && info->encoding == encoding)
- goto useless;
-
- /* Réinitialisation */
-
- reset_assembly_info(info);
-
- copy_mrange(&info->current, range);
-
- /* Zone d'appartenance */
-
- info->segment = strdup(segment);
-
- /* Adresses de base */
-
- vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
-
- vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
-
- info->encoding = encoding;
- info->size = size;
-
- /* Symbole concerné */
-
- if (symbol != NULL)
- info->symbol = strdup(symbol);
-
- /* Nettoyage et conclusion */
-
- info->reset = false;
-
- gtk_status_stack_show_current_location(stack);
-
- useless:
-
- ;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* *
-* Description : Réinitialise les informations associées une position. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_reset_current_location(GtkStatusStack *stack)
-{
- assembly_info *info; /* Informations à constituer */
-
- info = stack->asm_info;
-
- reset_assembly_info(info);
-
- gtk_status_stack_show_current_location(stack);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = pile de statuts à manipuler. *
-* *
-* Description : S'assure de l'affichage à jour de la partie "assemblage". *
-* *
-* Retour : G_SOURCE_REMOVE pour une exécution unique. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack)
-{
- GObject *ref; /* Espace de référencements */
- assembly_info *info; /* Informations à consulter */
- GtkLabel *label; /* Etiquette à actualiser */
- char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */
- char *content; /* Contenu dynamique */
-
- stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location;
-
- gtk_stack_set_visible_child_name(stack->main, "asm_info");
-
- ref = stack->asm_ref;
- info = stack->asm_info;
-
- /* Première partie : navigation */
-
- if (info->reset)
- {
- label = GTK_LABEL(g_object_get_data(ref, "segment"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "phys"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "virt"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "offset"));
- gtk_label_set_text(label, NULL);
-
- }
- else
- {
- label = GTK_LABEL(g_object_get_data(ref, "segment"));
- gtk_label_set_text(label, info->segment);
-
- snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
-
- label = GTK_LABEL(g_object_get_data(ref, "phys"));
- gtk_label_set_text(label, raw_pos);
-
- snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
-
- label = GTK_LABEL(g_object_get_data(ref, "virt"));
- gtk_label_set_text(label, raw_pos);
-
- label = GTK_LABEL(g_object_get_data(ref, "offset"));
- gtk_label_set_text(label, info->symbol != NULL ? info->symbol : "");
-
- }
-
- /* Seconde partie : architecture */
-
- if (info->reset || info->encoding == NULL || info->size == VMPA_NO_PHYSICAL)
- {
- label = GTK_LABEL(g_object_get_data(ref, "arch"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "size"));
- gtk_label_set_text(label, NULL);
-
- }
- else
- {
- label = GTK_LABEL(g_object_get_data(ref, "arch"));
- gtk_label_set_text(label, info->encoding);
-
- if (info->size > 1)
- asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes"));
- else
- asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte"));
-
- label = GTK_LABEL(g_object_get_data(ref, "size"));
- gtk_label_set_text(label, content);
-
- free(content);
-
- }
-
- 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, PROGRESS_SIZE, -1);
- gtk_widget_set_valign(progress, GTK_ALIGN_CENTER);
- 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. *
-* max = taille de la plage à parcourir. *
-* *
-* Description : Démarre le suivi d'une nouvelle activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max)
-{
- activity_id_t result; /* Numéro unique à renvoyer */
- progress_info *info; /* Informations à consulter */
- size_t new; /* Indice de l'activité créée */
-
- if (stack == NULL) return NO_ACTIVITY_ID;
-
- 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 = result;
-
- /* Intitulé */
-
- if (msg == NULL)
- info->statuses[new].message = NULL;
- else
- info->statuses[new].message = strdup(msg);
-
- /* Valeur */
-
- info->statuses[new].current = 0;
- info->statuses[new].max = max;
- info->statuses[new].last_updated = 0;
-
- /* 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. *
-* extra = nouvelle échéance supplémentaire des traitements. *
-* *
-* Description : Etend la portée des travaux d'une nouvelle activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- info->statuses[i].max += extra;
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* msg = nouveau message de statut à copier. *
-* *
-* Description : Actualise les informations concernant une activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- bool msg_changed; /* Changement d'intitulé */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(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);
-
- /* On n'actualise que le sommet de la pile */
-
- if ((i + 1) == info->count && msg_changed)
- {
- 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. *
-* inc = 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, unsigned long inc)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- progress_status *status; /* Raccourci de confort */
- double new; /* Nouvelle progression */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- status = &info->statuses[i];
-
- /* Valeur */
-
- status->current += inc;
-
- new = (status->current * 1.0) / status->max;
-
- /* On n'actualise que le sommet de la pile */
-
- if ((i + 1) == info->count && (new - status->last_updated) > (1.0 / PROGRESS_SIZE))
- {
- status->last_updated = new;
-
- 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 */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(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 = 0;
- g_idle_add(stack->def_source, 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_stack_set_visible_child_name(stack->main, "prog_info");
-
- ref = stack->prog_ref;
- 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->current * 1.0) / last->max);
-
- 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;
-
-}