diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2024-09-09 08:41:59 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2024-09-09 08:41:59 (GMT) |
commit | ec71086f6dcf69241b586f1e48e7d656dda11a6c (patch) | |
tree | 4a5cfbbe76d9407997b6b6e8f4b8e0893ddb259d | |
parent | e3ce461fec70fd638b415edef4ce3aa9d939d772 (diff) |
Restore the status bar at the bottom of the main window.
-rw-r--r-- | src/gtkext/Makefile.am | 7 | ||||
-rw-r--r-- | src/gtkext/gresource.xml | 1 | ||||
-rw-r--r-- | src/gtkext/statusstack-int.h | 94 | ||||
-rw-r--r-- | src/gtkext/statusstack.c | 904 | ||||
-rw-r--r-- | src/gtkext/statusstack.h | 46 | ||||
-rw-r--r-- | src/gtkext/statusstack.ui | 193 | ||||
-rw-r--r-- | src/gui/window.c | 3 | ||||
-rw-r--r-- | src/gui/window.ui | 13 |
8 files changed, 773 insertions, 488 deletions
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index 9f32c7c..2a2738a 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -14,7 +14,6 @@ libgtkext_la_SOURCES = \ gtkdockable-int.h \ gtkdockable.h gtkdockable.c \ gtkgraphdisplay.h gtkgraphdisplay.c \ - statusstack.h statusstack.c \ hexdisplay.h hexdisplay.c \ named-int.h \ named.h named.c \ @@ -29,7 +28,8 @@ libgtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) RES_FILES = \ hexview.css \ - hexview.ui + hexview.ui \ + statusstack.ui libgtkext4_la_SOURCES = \ area-int.h \ @@ -47,7 +47,8 @@ libgtkext4_la_SOURCES = \ hexview.h hexview.c \ panel-int.h \ panel.h panel.c \ - resources.h resources.c + resources.h resources.c \ + statusstack.h statusstack.c libgtkext4_la_CFLAGS = $(LIBGTK4_CFLAGS) diff --git a/src/gtkext/gresource.xml b/src/gtkext/gresource.xml index 225b2a4..3bfd8c5 100644 --- a/src/gtkext/gresource.xml +++ b/src/gtkext/gresource.xml @@ -3,5 +3,6 @@ <gresource prefix="/re/chrysalide/framework/gtkext"> <file compressed="true">hexview.css</file> <file compressed="true">hexview.ui</file> + <file compressed="true">statusstack.ui</file> </gresource> </gresources> diff --git a/src/gtkext/statusstack-int.h b/src/gtkext/statusstack-int.h new file mode 100644 index 0000000..facc5af --- /dev/null +++ b/src/gtkext/statusstack-int.h @@ -0,0 +1,94 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * statusstack-int.h - définitions internes pour l'empilement d'informations de statut + * + * Copyright (C) 2024 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/>. + */ + + +#ifndef _GTKEXT_STATUSSTACK_INT_H +#define _GTKEXT_STATUSSTACK_INT_H + + +#include "statusstack.h" + + + +/* Navigation au sein d'assemblage */ +typedef struct _navigation_info_t navigation_info_t; + +/* Mémorisation des progressions au sein d'activités */ +typedef struct _activity_info_t activity_info_t; + + +#define NETWORK_UPDATE_COUNT 10 +#define NETWORK_UPDATE_INTERVAL (1000 / NETWORK_UPDATE_COUNT) + + +/* Gestion de barre de statut adaptable (instance) */ +struct _GtkStatusStack +{ + GtkBox parent; /* A laisser en premier */ + + GtkStack *main; /* Pile d'informations associée*/ + + GSourceFunc def_source; /* Appel en fin d'activité */ + + /* Navigation */ + + GtkLabel *nav_segment; /* Désignation du segment */ + GtkLabel *nav_phys; /* Adresse physique */ + GtkLabel *nav_virt; /* Adresse virtuelle */ + GtkLabel *nav_offset; /* Position dans le binaire */ + GtkLabel *nav_format; /* Architecture du binaire */ + GtkLabel *nav_details; /* Détails sur l'architecture */ + GtkEntry *zoom; /* Degré de zoom courant */ + + navigation_info_t *nav_info; /* Informations brutes liées */ + + /* Activité */ + + GtkLabel *activity_message; /* Nature de l'activité */ + GtkProgressBar *activity_progress; /* Barre de progression */ + + activity_info_t *activity_info; /* Informations brutes liées */ + + /* Tronc commun */ + + GtkLabel *net_recv_speed; /* Débit en réception */ + GtkLabel *net_send_speed; /* Débit en émission */ + + size_t last_bytes_received[NETWORK_UPDATE_COUNT]; /* Octets reçus */ + size_t last_bytes_sent[NETWORK_UPDATE_COUNT]; /* Octets émis */ + gint64 last_timestamps[NETWORK_UPDATE_COUNT]; /* Dates des mesures */ + size_t next_index; /* Indice d'écriture */ + + guint network_update_tag; /* Identifiant de mise à jour */ + +}; + +/* Gestion de barre de statut adaptable (classe) */ +struct _GtkStatusStackClass +{ + GtkBoxClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _GTKEXT_STATUSSTACK_INT_H */ diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c index fe4e4d5..0d8ef62 100644 --- a/src/gtkext/statusstack.c +++ b/src/gtkext/statusstack.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * gtkstatusstack.c - empilement d'informations de statut + * statusstack.c - empilement d'informations de statut * - * Copyright (C) 2015-2019 Cyrille Bagard + * Copyright (C) 2015-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,11 +21,10 @@ */ -#include "gtkstatusstack.h" +#include "statusstack.h" #include <assert.h> -#include <inttypes.h> #include <malloc.h> #include <string.h> @@ -33,45 +32,13 @@ #include <i18n.h> -#include "easygtk.h" -#include "../gui/agroup.h" -#include "../format/format.h" +#include "helpers.h" +#include "statusstack-int.h" +#include "../core/global.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 */ - -}; +/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */ /* Initialise la classe des barres de statut améliorées. */ @@ -86,45 +53,43 @@ static void gtk_status_stack_dispose(GtkStatusStack *); /* Procède à la libération totale de la mémoire. */ static void gtk_status_stack_finalize(GtkStatusStack *); +/* Met à jour dans la barre les débits réseau observés. */ +static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *); + /* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ /* Navigation au sein d'assemblage */ -struct _assembly_info +struct _navigation_info_t { - bool reset; /* Réinitialisation */ + char *segment; /* Segment d'appartenance */ 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 */ + char *format; /* Architecture et format */ + char *details; /* Encodage de l'instruction */ }; -/* Supprime l'empreinte mémoire d'informations d'assemblage. */ -static void reset_assembly_info(assembly_info *); +/* Met en place le suivi d'informations de navigation. */ +static void init_navigation_info(navigation_info_t *); -/* Construit une barre d'état pour language d'assemblage. */ -static GtkWidget *build_assembly_status_stack(GtkStatusStack *); +/* Supprime l'empreinte mémoire d'informations de navigation. */ +static void fini_navigation_info(navigation_info_t *); -/* Réagit à un redimensionnement de la barre de désassemblage. */ -static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *); +/* S'assure de l'affichage à jour de la partie "navigation". */ +static gboolean gtk_status_stack_show_current_location(GtkStatusStack *); /* 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 *); +static void gtk_status_stack_on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GtkStatusStack *); @@ -132,7 +97,7 @@ static gboolean gtk_status_stack_show_current_location(GtkStatusStack *); /* Informations de progression */ -typedef struct _progress_status +typedef struct _activity_status_t { activity_id_t id; /* Identifiant unique */ @@ -143,30 +108,32 @@ typedef struct _progress_status double last_updated; /* Dernière valeur poussée */ -} progress_status; +} activity_status_t; + -/* Mémorisation des progressions */ -struct _progress_info +/* Mémorisation des progressions au sein d'activités */ +struct _activity_info_t { + GMutex access; /* Accès à la pile */ + activity_id_t generator; /* Générateur de séquence */ - progress_status *statuses; /* Statuts de progression */ + activity_status_t *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 - +/* Met en place le suivi d'informations d'activité. */ +static void init_activity_info(activity_info_t *); /* Supprime l'empreinte mémoire d'informations d'activité. */ -static void reset_progress_info(progress_info *); +static void fini_activity_info(activity_info_t *); -/* Construit une barre d'état pour un suivi d'activité. */ -static GtkWidget *build_progress_status_stack(GtkStatusStack *); +/* Recherche les indications de statut d'une activité donnée. */ +static activity_status_t *find_activity_status_by_id(activity_info_t *, activity_id_t); /* S'assure de l'affichage à jour de la partie "activité". */ static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *); @@ -174,17 +141,17 @@ static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *); /* ---------------------------------------------------------------------------------- */ -/* GESTION EXTERIEURE DE LA BARRE */ +/* GESTION GENERALE DES STATUTS */ /* ---------------------------------------------------------------------------------- */ -/* Détermine le type de la barre de statut améliorée. */ -G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX) +/* Détermine le type du composant d'affichage générique. */ +G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX); /****************************************************************************** * * -* Paramètres : klass = classe GTK à initialiser. * +* Paramètres : class = classe GTK à initialiser. * * * * Description : Initialise la classe des barres de statut améliorées. * * * @@ -194,21 +161,44 @@ G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX) * * ******************************************************************************/ -static void gtk_status_stack_class_init(GtkStatusStackClass *klass) +static void gtk_status_stack_class_init(GtkStatusStackClass *class) { - GObjectClass *object; /* Autre version de la classe */ + GObjectClass *object; /* Plus haut niveau équivalent */ + GtkWidgetClass *widget; /* Classe de haut niveau */ - object = G_OBJECT_CLASS(klass); + object = G_OBJECT_CLASS(class); object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose; object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize; + widget = GTK_WIDGET_CLASS(class); + + gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/statusstack.ui"); + + gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press)); + + gtk_widget_class_bind_template_child(widget, GtkStatusStack, main); + + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_segment); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_phys); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_virt); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_offset); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_format); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_details); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, zoom); + + gtk_widget_class_bind_template_child(widget, GtkStatusStack, activity_message); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, activity_progress); + + gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_recv_speed); + gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_send_speed); + } /****************************************************************************** * * -* Paramètres : stack = instance GTK à initialiser. * +* Paramètres : stack = composant GTK à initialiser. * * * * Description : Initialise une instance de barre de statut améliorée. * * * @@ -220,40 +210,27 @@ static void gtk_status_stack_class_init(GtkStatusStackClass *klass) 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); + gtk_widget_init_template(GTK_WIDGET(stack)); - 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)); + stack->def_source = NULL; - reset_assembly_info(stack->asm_info); + stack->nav_info = calloc(1, sizeof(navigation_info_t)); + init_navigation_info(stack->nav_info); - layer = build_progress_status_stack(stack); - gtk_stack_add_named(stack->main, layer, "prog_info"); + stack->activity_info = calloc(1, sizeof(activity_info_t)); + init_activity_info(stack->activity_info); - stack->prog_ref = G_OBJECT(layer); - stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info)); + stack->next_index = 0; - reset_progress_info(stack->prog_info); - - gtk_status_stack_reset_current_location(stack); + stack->network_update_tag = g_timeout_add(NETWORK_UPDATE_INTERVAL, + G_SOURCE_FUNC(gtk_status_stack_update_network_stats), stack); } /****************************************************************************** * * -* Paramètres : view = instance d'objet GLib à traiter. * +* Paramètres : stack = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -265,6 +242,10 @@ static void gtk_status_stack_init(GtkStatusStack *stack) static void gtk_status_stack_dispose(GtkStatusStack *stack) { + g_source_remove(stack->network_update_tag); + + gtk_widget_dispose_template(GTK_WIDGET(stack), GTK_TYPE_STATUS_STACK); + G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack)); } @@ -272,7 +253,7 @@ static void gtk_status_stack_dispose(GtkStatusStack *stack) /****************************************************************************** * * -* Paramètres : view = instance d'objet GLib à traiter. * +* Paramètres : stack = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -284,11 +265,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); + fini_navigation_info(stack->nav_info); + free(stack->nav_info); - reset_progress_info(stack->prog_info); - free(stack->prog_info); + fini_activity_info(stack->activity_info); + free(stack->activity_info); G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack)); @@ -318,17 +299,11 @@ GtkStatusStack *gtk_status_stack_new(void) } - -/* ---------------------------------------------------------------------------------- */ -/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : info = informations à réinitialiser. * +* Paramètres : stack = barre de statut à actualiser. * * * -* Description : Supprime l'empreinte mémoire d'informations d'assemblage. * +* Description : Réinitialise la barre de statut à son stade par défaut. * * * * Retour : - * * * @@ -336,110 +311,146 @@ GtkStatusStack *gtk_status_stack_new(void) * * ******************************************************************************/ -static void reset_assembly_info(assembly_info *info) +void gtk_status_stack_reset(GtkStatusStack *stack) { - info->reset = true; - - if (info->segment != NULL) - { - free(info->segment); - info->segment = NULL; - } + gtk_stack_set_visible_child_name(stack->main, "default"); - if (info->symbol != NULL) - { - free(info->symbol); - info->symbol = NULL; - } + stack->def_source = NULL; } /****************************************************************************** * * -* Paramètres : stack = composant global en cours de construction. * +* Paramètres : stack = barre de statut à actualiser. * * * -* Description : Construit une barre d'état pour language d'assemblage. * +* Description : Met à jour dans la barre les débits réseau observés. * * * -* Retour : Composant GTK mis en place. * +* Retour : G_SOURCE_CONTINUE pour poursuivre les mises à jour. * * * * Remarques : - * * * ******************************************************************************/ -static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack) +static gboolean gtk_status_stack_update_network_stats(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 */ + gboolean result; /* Indication à retourner */ + gint64 timestamp; /* Position temporelle */ + size_t received; /* Quantité d'octets reçus */ + size_t sent; /* Quantité d'octets émis */ + gint64 diff_time; /* Différentiel de temps */ + size_t diff_bytes; /* Différentiel de volume */ + double speed; /* Débit de transfert constaté */ + size_t i; /* Boucle de parcours */ + char *value; /* Valeur à afficher */ - result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show(result); + const char *units[] = { _("b/s"), _("kb/s"), _("Mb/s"), _("Gb/s"), _("Tb/s") }; - ref = G_OBJECT(result); + result = G_SOURCE_CONTINUE; - g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref); + /* Mémorisation des données */ - /* Première partie : navigation */ + timestamp = g_get_monotonic_time(); - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8); + get_network_stats(&received, &sent); - label = qck_create_label(ref, "segment", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + if (stack->next_index < NETWORK_UPDATE_COUNT) + { + stack->last_bytes_received[stack->next_index] = received; + stack->last_bytes_sent[stack->next_index] = sent; + stack->last_timestamps[stack->next_index] = timestamp; - label = qck_create_label(ref, "phys", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + stack->next_index++; - label = qck_create_label(ref, "virt", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + } + else + { + memcpy(stack->last_bytes_received, stack->last_bytes_received + 1, + (NETWORK_UPDATE_COUNT - 1) * sizeof(size_t)); - label = qck_create_label(ref, "offset", NULL); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + memcpy(stack->last_bytes_sent, stack->last_bytes_sent + 1, + (NETWORK_UPDATE_COUNT - 1) * sizeof(size_t)); - /* Seconde partie : architecture */ + memcpy(stack->last_timestamps, stack->last_timestamps + 1, + (NETWORK_UPDATE_COUNT - 1) * sizeof(gint64)); - 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); + stack->last_bytes_received[NETWORK_UPDATE_COUNT - 1] = received; + stack->last_bytes_sent[NETWORK_UPDATE_COUNT - 1] = sent; + stack->last_timestamps[NETWORK_UPDATE_COUNT - 1] = timestamp; - 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); + if (stack->next_index < NETWORK_UPDATE_COUNT) + goto done; - /* Troisième partie : affichage */ + diff_time = stack->last_timestamps[NETWORK_UPDATE_COUNT - 1] - stack->last_timestamps[0]; - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_show(hbox); - gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8); + /* Débit de réception */ - zoom = qck_create_entry(ref, "zoom", "100%"); - gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic"); + diff_bytes = stack->last_bytes_received[NETWORK_UPDATE_COUNT - 1] - stack->last_bytes_received[0]; - 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); + speed = (diff_bytes * 1000000) / diff_time; - gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0); + for (i = 0; i < G_N_ELEMENTS(units); i++) + { + if (speed < 1024) + break; + + speed /= 1024; + + } + + if (i == 0) + asprintf(&value, "%d %s", (int)speed, units[i]); + else + asprintf(&value, "%.1f %s", speed, units[i]); + + gtk_label_set_label(stack->net_recv_speed, value); + + free(value); + + /* Débit de émission */ + + diff_bytes = stack->last_bytes_sent[NETWORK_UPDATE_COUNT - 1] - stack->last_bytes_sent[0]; + + speed = (diff_bytes * 1000000) / diff_time; + + for (i = 0; i < G_N_ELEMENTS(units); i++) + { + if (speed < 1024) + break; + + speed /= 1024; + + } + + if (i == 0) + asprintf(&value, "%d %s", (int)speed, units[i]); + else + asprintf(&value, "%.1f %s", speed, units[i]); + + gtk_label_set_label(stack->net_send_speed, value); + + free(value); + + done: return result; } + +/* ---------------------------------------------------------------------------------- */ +/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : widget = composant graphique qui vient d'évoluer. * -* allocation = espace réservé pour le composant visé. * -* ref = espace de référencement global. * +* Paramètres : info = informations à initialiser. * * * -* Description : Réagit à un redimensionnement de la barre de désassemblage. * +* Description : Met en place le suivi d'informations de navigation. * * * * Retour : - * * * @@ -447,33 +458,23 @@ static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack) * * ******************************************************************************/ -static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref) +static void init_navigation_info(navigation_info_t *info) { - GtkWidget *hbox; /* Sous-division horizontale */ + info->segment = NULL; - hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box")); + info->symbol = NULL; - 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)); + info->format = NULL; + info->details = NULL; } /****************************************************************************** * * -* 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. * +* Paramètres : info = informations à libérer de la mémoire. * * * -* Description : Réagit à un clic sur l'icône de zoom. * +* Description : Supprime l'empreinte mémoire d'informations de navigation. * * * * Retour : - * * * @@ -481,31 +482,31 @@ static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *all * * ******************************************************************************/ -static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack) +static void fini_navigation_info(navigation_info_t *info) { - GtkWidget *popup; /* Popup à faire surgir */ - GdkRectangle rect; /* Zone précise à cibler */ - - if (event->button != GDK_BUTTON_PRIMARY) - return; + if (info->segment != NULL) + free(info->segment); - popup = gtk_popover_new(GTK_WIDGET(entry)); + if (info->symbol != NULL) + free(info->symbol); - gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect); - gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect); + if (info->format != NULL) + free(info->format); - gtk_widget_show(popup); + if (info->details != NULL) + free(info->details); } /****************************************************************************** * * -* 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. * +* 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. * +* format = format du binaire manipulé * +* details = détails supplémentaires (liés à l'encodage ?) * * * * Description : Actualise les informations liées une position d'assemblage. * * * @@ -515,51 +516,50 @@ static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, G * * ******************************************************************************/ -void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *encoding) +void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *format, const char *details) { - assembly_info *info; /* Informations à constituer */ + navigation_info_t *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 ? */ + info = stack->nav_info; - addr = get_mrange_addr(range); - size = get_mrange_length(range); - - if (cmp_mrange(&info->current, range) == 0 - && info->size == size - && info->encoding == encoding) + if (cmp_mrange(&info->current, range) == 0) goto useless; - /* Réinitialisation */ - - reset_assembly_info(info); - - copy_mrange(&info->current, range); - /* Zone d'appartenance */ - info->segment = strdup(segment); + if (segment != NULL) + info->segment = strdup(segment); + else + info->segment = NULL; /* Adresses de base */ + copy_mrange(&info->current, range); + + addr = get_mrange_addr(range); + 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); + else + info->symbol = NULL; - /* Nettoyage et conclusion */ + /* Architecture & format */ - info->reset = false; + info->format = strdup(format); + + if (details != NULL) + info->details = strdup(details); + else + info->details = NULL; + + /* Nettoyage et conclusion */ gtk_status_stack_show_current_location(stack); @@ -572,34 +572,9 @@ void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrang /****************************************************************************** * * -* 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". * +* Description : S'assure de l'affichage à jour de la partie "navigation". * * * * Retour : G_SOURCE_REMOVE pour une exécution unique. * * * @@ -609,98 +584,104 @@ void gtk_status_stack_reset_current_location(GtkStatusStack *stack) 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 */ + navigation_info_t *info; /* Informations à constituer */ 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"); + gtk_stack_set_visible_child_name(stack->main, "navigation"); - ref = stack->asm_ref; - info = stack->asm_info; + info = stack->nav_info; /* Première partie : navigation */ - if (info->reset) - { - label = GTK_LABEL(g_object_get_data(ref, "segment")); - gtk_label_set_text(label, NULL); + gtk_label_set_text(stack->nav_segment, info->segment != NULL ? info->segment : ""); - label = GTK_LABEL(g_object_get_data(ref, "phys")); - gtk_label_set_text(label, NULL); + snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys); - label = GTK_LABEL(g_object_get_data(ref, "virt")); - gtk_label_set_text(label, NULL); + gtk_label_set_text(stack->nav_phys, raw_pos); - label = GTK_LABEL(g_object_get_data(ref, "offset")); - gtk_label_set_text(label, NULL); + snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt); - } - else - { - label = GTK_LABEL(g_object_get_data(ref, "segment")); - gtk_label_set_text(label, info->segment); + gtk_label_set_text(stack->nav_virt, raw_pos); - snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys); + gtk_label_set_text(stack->nav_offset, info->symbol != NULL ? info->symbol : ""); - label = GTK_LABEL(g_object_get_data(ref, "phys")); - gtk_label_set_text(label, raw_pos); + /* Seconde partie : format & architecture */ - snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt); + gtk_label_set_text(stack->nav_format, info->format); - label = GTK_LABEL(g_object_get_data(ref, "virt")); - gtk_label_set_text(label, raw_pos); + gtk_label_set_text(stack->nav_details, info->details != NULL ? info->details : ""); - label = GTK_LABEL(g_object_get_data(ref, "offset")); - gtk_label_set_text(label, info->symbol != NULL ? info->symbol : ""); + return G_SOURCE_REMOVE; - } +} - /* 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); +/****************************************************************************** +* * +* Paramètres : entry = zone de texte visée par la procédure. * +* icon_pos = position de l'image associée à l'entrée. * +* stack = composant graphique de gestion des statuts. * +* * +* Description : Réagit à un clic sur l'icône de zoom. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - label = GTK_LABEL(g_object_get_data(ref, "size")); - gtk_label_set_text(label, NULL); +static void gtk_status_stack_on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GtkStatusStack *stack) +{ +#if 0 + GtkWidget *popup; /* Popup à faire surgir */ + GdkRectangle rect; /* Zone précise à cibler */ - } - else - { - label = GTK_LABEL(g_object_get_data(ref, "arch")); - gtk_label_set_text(label, info->encoding); + popup = gtk_popover_new(); - if (info->size > 1) - asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes")); - else - asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte")); + gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect); + gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect); - label = GTK_LABEL(g_object_get_data(ref, "size")); - gtk_label_set_text(label, content); + gtk_widget_show(popup); +#endif +} - free(content); - } +/* ---------------------------------------------------------------------------------- */ +/* STATUT DES SUIVIS D'ACTIVITE */ +/* ---------------------------------------------------------------------------------- */ - return G_SOURCE_REMOVE; -} +/****************************************************************************** +* * +* Paramètres : info = informations à initialiser. * +* * +* Description : Met en place le suivi d'informations d'activité. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +static void init_activity_info(activity_info_t *info) +{ + g_mutex_init(&info->access); + info->generator = NO_ACTIVITY_ID; -/* ---------------------------------------------------------------------------------- */ -/* STATUT DES SUIVIS D'ACTIVITE */ -/* ---------------------------------------------------------------------------------- */ + info->statuses = NULL; + info->count = 0; + + info->tag = 0; + +} /****************************************************************************** * * -* Paramètres : info = informations à réinitialiser. * +* Paramètres : info = informations à libérer de la mémoire. * * * * Description : Supprime l'empreinte mémoire d'informations d'activité. * * * @@ -710,7 +691,7 @@ static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack) * * ******************************************************************************/ -static void reset_progress_info(progress_info *info) +static void fini_activity_info(activity_info_t *info) { size_t i; /* Boucle de parcours */ @@ -733,44 +714,39 @@ static void reset_progress_info(progress_info *info) info->count = 0; - g_mutex_init(&info->access); + g_mutex_clear(&info->access); } /****************************************************************************** * * -* Paramètres : stack = composant global en cours de construction. * +* Paramètres : info = informations relatives aux activités à consulter. * +* id = identifiant de l'activité à cibler. * * * -* Description : Construit une barre d'état pour un suivi d'activité. * +* Description : Recherche les indications de statut d'une activité donnée. * * * -* Retour : Composant GTK mis en place. * +* Retour : Structure d'encadrement trouvée ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -static GtkWidget *build_progress_status_stack(GtkStatusStack *stack) +static activity_status_t *find_activity_status_by_id(activity_info_t *info, activity_id_t id) { - 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); + activity_status_t *result; /* Statut trouvé à renvoyer */ + size_t i; /* Boucle de parcours */ - ref = G_OBJECT(result); + result = NULL; - 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); + assert(!g_mutex_trylock(&info->access)); - label = qck_create_label(ref, "message", NULL); - gtk_box_pack_start(GTK_BOX(result), label, TRUE, TRUE, 0); + for (i = 0; i < info->count; i++) + if (info->statuses[i].id == id) + { + result = info->statuses + i; + break; + } return result; @@ -794,36 +770,43 @@ static GtkWidget *build_progress_status_stack(GtkStatusStack *stack) 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; + activity_info_t *info; /* Informations à consulter */ + activity_status_t *new; /* Nouveau suivi d'activité */ - info = stack->prog_info; + info = stack->activity_info; g_mutex_lock(&info->access); - result = ++info->generator; + while (1) + { + result = ++info->generator; + + if (find_activity_status_by_id(info, result) == NULL) + break; + + } + while (0); - new = info->count++; + info->statuses = realloc(info->statuses, ++info->count * sizeof(activity_status_t)); - info->statuses = (progress_status *)realloc(info->statuses, - info->count * sizeof(progress_status)); + new = info->statuses + info->count - 1; - info->statuses[new].id = result; + /* Identifiant */ + + new->id = result; /* Intitulé */ if (msg == NULL) - info->statuses[new].message = NULL; + new->message = NULL; else - info->statuses[new].message = strdup(msg); + new->message = strdup(msg); /* Valeur */ - info->statuses[new].current = 0; - info->statuses[new].max = max; - info->statuses[new].last_updated = 0; + new->current = 0; + new->max = max; + new->last_updated = 0; /* Actualisation */ @@ -843,9 +826,9 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m * * * Paramètres : stack = barre de statut à actualiser. * * id = identifiant de l'activité à cibler. * -* extra = nouvelle échéance supplémentaire des traitements. * +* msg = nouveau message de statut à copier. * * * -* Description : Etend la portée des travaux d'une nouvelle activité. * +* Description : Actualise les informations concernant une activité. * * * * Retour : - * * * @@ -853,24 +836,55 @@ activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *m * * ******************************************************************************/ -void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra) +void gtk_status_stack_update_activity_message(GtkStatusStack *stack, activity_id_t id, const char *msg) { - progress_info *info; /* Informations à consulter */ - size_t i; /* Boucle de parcours */ - - if (stack == NULL) return; + activity_info_t *info; /* Informations à consulter */ + activity_status_t *status; /* Suivi d'activité à traiter */ + bool msg_changed; /* Changement d'intitulé */ - info = stack->prog_info; + info = stack->activity_info; g_mutex_lock(&info->access); - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; + status = find_activity_status_by_id(info, id); - assert(i < info->count); + assert(status != NULL); + + if (status == NULL) + goto exit; + + /* Intitulé */ + + if (status->message != NULL) + { + if (msg == NULL) + msg_changed = true; + else + msg_changed = (strcmp(status->message, msg) != 0); - info->statuses[i].max += extra; + free(status->message); + + } + else + msg_changed = (msg != NULL); + + if (msg == NULL) + status->message = NULL; + else + status->message = strdup(msg); + + /* On n'actualise que le sommet de la pile */ + + if ((status - info->statuses + 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); + + } + + exit: g_mutex_unlock(&info->access); @@ -881,9 +895,9 @@ void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, u * * * Paramètres : stack = barre de statut à actualiser. * * id = identifiant de l'activité à cibler. * -* msg = nouveau message de statut à copier. * +* inc = nouvelle valeur pour une progression donnée. * * * -* Description : Actualise les informations concernant une activité. * +* Description : Actualise la progression d'une activité. * * * * Retour : - * * * @@ -891,48 +905,35 @@ void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, u * * ******************************************************************************/ -void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg) +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 */ - bool msg_changed; /* Changement d'intitulé */ - - if (stack == NULL) return; + activity_info_t *info; /* Informations à consulter */ + activity_status_t *status; /* Suivi d'activité à traiter */ + double new; /* Nouvelle progression */ - info = stack->prog_info; + info = stack->activity_info; g_mutex_lock(&info->access); - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; + status = find_activity_status_by_id(info, id); - assert(i < info->count); + assert(status != NULL); - /* Intitulé */ + if (status == NULL) + goto exit; - 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); + /* Valeur */ - } - else - msg_changed = (msg != NULL); + status->current += inc; - if (msg == NULL) - info->statuses[i].message = NULL; - else - info->statuses[i].message = strdup(msg); + new = (status->current * 1.0) / status->max; /* On n'actualise que le sommet de la pile */ - if ((i + 1) == info->count && msg_changed) + if ((status - info->statuses + 1) == info->count && (new - status->last_updated) > 0.1) { + status->last_updated = new; + if (info->tag != 0) g_source_remove(info->tag); @@ -940,6 +941,8 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c } + exit: + g_mutex_unlock(&info->access); } @@ -949,9 +952,9 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c * * * Paramètres : stack = barre de statut à actualiser. * * id = identifiant de l'activité à cibler. * -* inc = nouvelle valeur pour une progression donnée. * +* extra = nouvelle échéance supplémentaire des traitements. * * * -* Description : Actualise la progression d'une activité. * +* Description : Etend la portée des travaux d'une nouvelle activité. * * * * Retour : - * * * @@ -959,39 +962,30 @@ void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, c * * ******************************************************************************/ -void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc) +void gtk_status_stack_extend_activity_max(GtkStatusStack *stack, activity_id_t id, unsigned long extra) { - 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; + activity_info_t *info; /* Informations à consulter */ + activity_status_t *status; /* Suivi d'activité à traiter */ - info = stack->prog_info; + info = stack->activity_info; g_mutex_lock(&info->access); - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; + status = find_activity_status_by_id(info, id); - assert(i < info->count); + assert(status != NULL); - status = &info->statuses[i]; + if (status == NULL) + goto exit; /* Valeur */ - status->current += inc; - - new = (status->current * 1.0) / status->max; + status->max += extra; /* On n'actualise que le sommet de la pile */ - if ((i + 1) == info->count && (new - status->last_updated) > (1.0 / PROGRESS_SIZE)) + if ((status - info->statuses + 1) == info->count) { - status->last_updated = new; - if (info->tag != 0) g_source_remove(info->tag); @@ -999,6 +993,8 @@ void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t } + exit: + g_mutex_unlock(&info->access); } @@ -1018,52 +1014,54 @@ void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t 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; + activity_info_t *info; /* Informations à consulter */ + activity_status_t *status; /* Suivi d'activité à traiter */ + bool is_last; /* Dernière position ? */ - info = stack->prog_info; + info = stack->activity_info; g_mutex_lock(&info->access); - for (i = 0; i < info->count; i++) - if (info->statuses[i].id == id) - break; + status = find_activity_status_by_id(info, id); - assert(i < info->count); + assert(status != NULL); - if (info->tag != 0) - g_source_remove(info->tag); + if (status == NULL) + goto exit; + + is_last = ((status - info->statuses + 1) == info->count); - if (info->statuses[i].message != NULL) - free(info->statuses[i].message); + /* Suppression des données */ - if (info->count == 1) + if (is_last) { - free(info->statuses); - info->statuses = NULL; + if (info->tag != 0) + g_source_remove(info->tag); } - 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)); + if (status->message != NULL) + free(status->message); - } + /* Réajustement des enregistrements */ + + if (!is_last) + memmove(status, status + 1, + (((info->statuses + info->count) - status) - 1) * sizeof(activity_status_t)); - info->count--; + info->statuses = realloc(info->statuses, --info->count * sizeof(activity_status_t)); + + /* Bascule vers un autre affichage ou actualisation ? */ if (info->count == 0) { info->tag = 0; g_idle_add(stack->def_source, stack); } - else + else if (is_last) info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack); + exit: + g_mutex_unlock(&info->access); } @@ -1083,39 +1081,33 @@ void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id) 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é */ + activity_info_t *info; /* Informations à consulter */ + activity_status_t *last; /* Dernier statut à traiter */ - if (!g_source_is_destroyed(g_main_current_source())) - { - gtk_stack_set_visible_child_name(stack->main, "prog_info"); + info = stack->activity_info; - ref = stack->prog_ref; - info = stack->prog_info; - - g_mutex_lock(&info->access); - - info->tag = 0; + g_mutex_lock(&info->access); + if (!g_source_is_destroyed(g_main_current_source())) + { if (info->count > 0) { + gtk_stack_set_visible_child_name(stack->main, "activity"); + 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); + gtk_label_set_text(stack->activity_message, last->message); - label = GTK_LABEL(g_object_get_data(ref, "message")); - gtk_label_set_text(label, last->message); + gtk_progress_bar_set_fraction(stack->activity_progress, (last->current * 1.0) / last->max); } - g_mutex_unlock(&info->access); + info->tag = 0; } + g_mutex_unlock(&info->access); + return G_SOURCE_REMOVE; } diff --git a/src/gtkext/statusstack.h b/src/gtkext/statusstack.h index f419014..66ad6db 100644 --- a/src/gtkext/statusstack.h +++ b/src/gtkext/statusstack.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * gtkstatusstack.h - prototypes pour un empilement d'informations de statut + * statusstack.h - prototypes pour l'empilement d'informations de statut * - * Copyright (C) 2015-2019 Cyrille Bagard + * Copyright (C) 2015-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,51 +21,39 @@ */ -#ifndef _GTKEXT_GTKSTATUSSTACK_H -#define _GTKEXT_GTKSTATUSSTACK_H +#ifndef _GTKEXT_STATUSSTACK_H +#define _GTKEXT_STATUSSTACK_H #include <gtk/gtk.h> #include "../arch/vmpa.h" +#include "../glibext/helpers.h" -/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */ +/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */ -#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type()) -#define GTK_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_STATUS_STACK, GtkStatusStack)) -#define GTK_STATUS_STACK_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, GTK_TYPE_STATUS_STACK, GtkStatusStackClass)) -#define GTK_IS_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK)) -#define GTK_IS_STATUS_STACK_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK)) -#define GTK_STATUS_STACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_STATUS_STACK, GtkStatusStackClass)) +#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type()) +DECLARE_GTYPE(GtkStatusStack, gtk_status_stack, GTK, STATUS_STACK); -/* Abstration d'une gestion de barre de statut (instance) */ -typedef struct _GtkStatusStack GtkStatusStack; - -/* Abstration d'une gestion de barre de statut (classe) */ -typedef struct _GtkStatusStackClass GtkStatusStackClass; - - -/* Détermine le type de la barre de statut améliorée. */ -GType gtk_status_stack_get_type(void); /* Crée une nouvelle instance de barre de statut. */ GtkStatusStack *gtk_status_stack_new(void); +/* Réinitialise la barre de statut à son stade par défaut. */ +void gtk_status_stack_reset(GtkStatusStack *); + /* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */ /* Actualise les informations liées une position d'assemblage. */ -void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *); - -/* Réinitialise les informations associées une position. */ -void gtk_status_stack_reset_current_location(GtkStatusStack *); +void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *, const char *); @@ -82,18 +70,18 @@ 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 *, unsigned long); -/* Etend la portée des travaux d'une nouvelle activité. */ -void gtk_status_stack_extend_activity(GtkStatusStack *, activity_id_t, unsigned long); - /* Actualise les informations concernant une activité. */ -void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *); +void gtk_status_stack_update_activity_message(GtkStatusStack *, activity_id_t, const char *); /* Actualise la progression d'une activité. */ void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, unsigned long); +/* Etend la portée des travaux d'une nouvelle activité. */ +void gtk_status_stack_extend_activity_max(GtkStatusStack *, activity_id_t, unsigned long); + /* Met fin au suivi d'une activité donnée. */ void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t); -#endif /* _GTKEXT_GTKSTATUSSTACK_H */ +#endif /* _GTKEXT_STATUSSTACK_H */ diff --git a/src/gtkext/statusstack.ui b/src/gtkext/statusstack.ui new file mode 100644 index 0000000..422f95d --- /dev/null +++ b/src/gtkext/statusstack.ui @@ -0,0 +1,193 @@ +<interface> + <template class="GtkStatusStack" parent="GtkBox"> + + <child> + <object class="GtkStack" id="main"> + <property name="margin-start">8</property> + <property name="margin-end">8</property> + <property name="hexpand">true</property> + + <!-- Vide par défaut --> + <child> + <object class="GtkStackPage" id="stack"> + <property name="name">default</property> + <property name="child"> + + <object class="GtkLabel"> + <property name="hexpand">true</property> + <property name="halign">fill</property> + <property name="valign">center</property> + <property name="xalign">0</property> + <property name="label"></property> + </object> + + </property> + </object> + </child> + + <!-- Informations pendant une navigation dans du contenu --> + <child> + <object class="GtkStackPage"> + <property name="name">navigation</property> + <property name="child"> + + <object class="GtkBox"> + <property name="orientation">horizontal</property> + <property name="hexpand">true</property> + <property name="halign">fill</property> + <property name="valign">center</property> + + <!-- Première partie : navigation --> + + <child> + <object class="GtkLabel" id="nav_segment"> + <property name="xalign">0</property> + <property name="label">-</property> + </object> + </child> + + <child> + <object class="GtkLabel" id="nav_phys"> + <property name="xalign">0</property> + <property name="label">-</property> + </object> + </child> + + <child> + <object class="GtkLabel" id="nav_virt"> + <property name="xalign">0</property> + <property name="label">-</property> + </object> + </child> + + <child> + <object class="GtkLabel" id="nav_offset"> + <property name="xalign">0</property> + <property name="hexpand">true</property> + <property name="halign">fill</property> + <property name="label">-</property> + </object> + </child> + + <!-- Seconde partie : architecture --> + + <child> + <object class="GtkLabel" id="nav_format"> + <property name="xalign">0</property> + <property name="label">-</property> + </object> + </child> + + <child> + <object class="GtkLabel" id="nav_details"> + <property name="xalign">0</property> + <property name="label">-</property> + </object> + </child> + + <!-- Troisième partie : affichage --> + + <child> + <object class="GtkEntry" id="zoom"> + <property name="secondary-icon-name">go-up-symbolic</property> + <signal name="icon-press" handler="gtk_status_stack_on_zoom_icon_press"/> + </object> + </child> + + </object> + + </property> + </object> + </child> + + <!-- Informations liées à une activité en cours --> + <child> + <object class="GtkStackPage"> + <property name="name">activity</property> + <property name="child"> + + <object class="GtkBox"> + <property name="orientation">horizontal</property> + <property name="hexpand">true</property> + <property name="halign">fill</property> + <property name="valign">center</property> + + <child> + <object class="GtkLabel" id="activity_message"> + <property name="xalign">0</property> + <property name="margin-end">8</property> + <property name="label">-</property> + </object> + </child> + + <child> + <object class="GtkProgressBar" id="activity_progress"> + <property name="hexpand">true</property> + <property name="halign">fill</property> + <property name="valign">center</property> + <property name="fraction">0</property> + </object> + </child> + + </object> + + </property> + </object> + </child> + + <property name="visible-child-name">default</property> + </object> + </child> + + <!-- Tronc commun --> + + <child> + <object class="GtkSeparator"> + <property name="orientation">vertical</property> + </object> + </child> + + <child> + <object class="GtkImage"> + <property name="margin-start">8</property> + <property name="icon-name">pan-down-symbolic</property> + </object> + </child> + <child> + <object class="GtkLabel" id="net_recv_speed"> + <property name="margin-start">8</property> + <property name="margin-end">8</property> + <property name="xalign">0</property> + <property name="label">0 b/s</property> + </object> + </child> + + <child> + <object class="GtkImage"> + <property name="icon-name">pan-up-symbolic</property> + </object> + </child> + <child> + <object class="GtkLabel" id="net_send_speed"> + <property name="margin-start">8</property> + <property name="margin-end">8</property> + <property name="xalign">0</property> + <property name="label">0 b/s</property> + </object> + </child> + + <child> + <object class="GtkSeparator"> + <property name="orientation">vertical</property> + </object> + </child> + + <child> + <object class="GtkToggleButton" id="bottom_toggler"> + <property name="has-frame">false</property> + <property name="icon-name">panel-bottom-symbolic</property> + </object> + </child> + + </template> +</interface> diff --git a/src/gui/window.c b/src/gui/window.c index 1f10a15..193f1bf 100644 --- a/src/gui/window.c +++ b/src/gui/window.c @@ -30,6 +30,7 @@ #include "dialogs/about.h" #include "panels/welcome.h" #include "../gtkext/helpers.h" +#include "../gtkext/statusstack.h" @@ -78,6 +79,8 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class) widget = GTK_WIDGET_CLASS(class); + g_type_ensure(GTK_TYPE_STATUS_STACK); + gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/window.ui"); gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, grid); diff --git a/src/gui/window.ui b/src/gui/window.ui index 7055695..59b8b2c 100644 --- a/src/gui/window.ui +++ b/src/gui/window.ui @@ -34,11 +34,24 @@ <child> <object class="GtkBox"> <property name="orientation">vertical</property> + <child> <object class="GtkStack" id="grid"> <property name="vexpand">TRUE</property> </object> </child> + + <child> + <object class="GtkSeparator"> + <property name="orientation">horizontal</property> + </object> + </child> + + <child> + <object class="GtkStatusStack" id="status"> + </object> + </child> + </object> </child> |