summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2024-09-09 08:41:59 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2024-09-09 08:41:59 (GMT)
commitec71086f6dcf69241b586f1e48e7d656dda11a6c (patch)
tree4a5cfbbe76d9407997b6b6e8f4b8e0893ddb259d
parente3ce461fec70fd638b415edef4ce3aa9d939d772 (diff)
Restore the status bar at the bottom of the main window.
-rw-r--r--src/gtkext/Makefile.am7
-rw-r--r--src/gtkext/gresource.xml1
-rw-r--r--src/gtkext/statusstack-int.h94
-rw-r--r--src/gtkext/statusstack.c904
-rw-r--r--src/gtkext/statusstack.h46
-rw-r--r--src/gtkext/statusstack.ui193
-rw-r--r--src/gui/window.c3
-rw-r--r--src/gui/window.ui13
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>