/* Chrysalide - Outil d'analyse de fichiers binaires * updating.c - mise à jour des panneaux de l'interface * * Copyright (C) 2018 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 . */ #include "updating.h" #include #include "updating-int.h" #include "../../core/global.h" #include "../../glibext/delayed-int.h" #include "../../glibext/signal.h" /* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */ /* Procède à l'initialisation de l'interface de mise à jour. */ static void g_updatable_panel_default_init(GUpdatablePanelInterface *); /* ---------------------------- AIDE POUR LA MISE A JOUR ---------------------------- */ /* Procédure de mise à jour de panneau graphique (instance) */ struct _GPanelUpdate { GDelayedWork parent; /* A laisser en premier */ GUpdatablePanel *panel; /* Panneau à manipuler */ unsigned int uid; /* Identifiant complémentaire */ size_t max; /* Marge de progression finale */ void *data; /* Données utiles au traitement*/ char *msg; /* Description d'activité */ }; /* Procédure de mise à jour de panneau graphique (classe) */ struct _GPanelUpdateClass { GDelayedWorkClass parent; /* A laisser en premier */ }; /* Initialise la classe des tâches des mises à jour de panneaux. */ static void g_panel_update_class_init(GPanelUpdateClass *); /* Initialise une tâche d'étude de mise à jour. */ static void g_panel_update_init(GPanelUpdate *); /* Supprime toutes les références externes. */ static void g_panel_update_dispose(GPanelUpdate *); /* Procède à la libération totale de la mémoire. */ static void g_panel_update_finalize(GPanelUpdate *); /* Assure la mise à jour d'un panneau en différé. */ static void g_panel_update_process(GPanelUpdate *, GtkStatusStack *); /* Marque l'achèvement d'une mise à jour de panneau. */ static void conclude_panel_update(GPanelUpdate *, GUpdatablePanel *); /* ---------------------------------------------------------------------------------- */ /* MECANISMES DE MISE A JOUR DE PANNEAU */ /* ---------------------------------------------------------------------------------- */ /* Détermine le type d'une interface pour la mise à jour de panneau. */ G_DEFINE_INTERFACE(GUpdatablePanel, g_updatable_panel, G_TYPE_OBJECT) /****************************************************************************** * * * Paramètres : iface = interface GLib à initialiser. * * * * Description : Procède à l'initialisation de l'interface de mise à jour. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_updatable_panel_default_init(GUpdatablePanelInterface *iface) { } /****************************************************************************** * * * Paramètres : panel = panneau ciblé par une mise à jour. * * uid = identifiant de la phase de traitement. * * count = nombre d'étapes à prévoir dans le traitement. [OUT] * * data = données sur lesquelles s'appuyer ensuite. [OUT] * * msg = description du message d'information. [OUT] * * * * Description : Prépare une opération de mise à jour de panneau. * * * * Retour : Bilan de la préparation. * * * * Remarques : - * * * ******************************************************************************/ bool g_updatable_panel_setup(const GUpdatablePanel *panel, unsigned int uid, size_t *count, void **data, char **msg) { bool result; /* Bilan à retourner */ GUpdatablePanelIface *iface; /* Interface utilisée */ iface = G_UPDATABLE_PANEL_GET_IFACE(panel); *count = 0; *data = NULL; *msg = NULL; result = iface->setup(panel, uid, count, data, msg); return result; } /****************************************************************************** * * * Paramètres : panel = panneau ciblé par une mise à jour. * * * * Description : Obtient le groupe de travail dédié à une mise à jour. * * * * Retour : Identifiant de groupe de travail. * * * * Remarques : - * * * ******************************************************************************/ wgroup_id_t g_updatable_panel_get_group(const GUpdatablePanel *panel) { wgroup_id_t result; /* Identifiant à retourner */ GUpdatablePanelIface *iface; /* Interface utilisée */ iface = G_UPDATABLE_PANEL_GET_IFACE(panel); result = iface->get_group(panel); return result; } /****************************************************************************** * * * Paramètres : panel = panneau ciblé par une mise à jour. * * uid = identifiant de la phase de traitement. * * data = données préparées par l'appelant. * * * * Description : Bascule l'affichage d'un panneau avant mise à jour. * * * * Retour : - * * * * Remarques : Cette fonction est appelée depuis le contexte principal. * * * ******************************************************************************/ void g_updatable_panel_introduce(const GUpdatablePanel *panel, unsigned int uid, void *data) { GUpdatablePanelIface *iface; /* Interface utilisée */ iface = G_UPDATABLE_PANEL_GET_IFACE(panel); iface->introduce(panel, uid, data); } /****************************************************************************** * * * Paramètres : panel = panneau ciblé par une mise à jour. * * uid = identifiant de la phase de traitement. * * status = barre de statut à tenir informée. * * id = identifiant pour le suivi de la progression. * * data = données préparées par l'appelant. * * * * Description : Réalise une opération de mise à jour de panneau. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_updatable_panel_process(const GUpdatablePanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, void *data) { GUpdatablePanelIface *iface; /* Interface utilisée */ iface = G_UPDATABLE_PANEL_GET_IFACE(panel); iface->process(panel, uid, status, id, data); } /****************************************************************************** * * * Paramètres : panel = panneau ciblé par une mise à jour. * * uid = identifiant de la phase de traitement. * * data = données préparées par l'appelant. * * * * Description : Bascule l'affichage d'un panneau après mise à jour. * * * * Retour : - * * * * Remarques : Cette fonction est appelée depuis le contexte principal. * * * ******************************************************************************/ void g_updatable_panel_conclude(GUpdatablePanel *panel, unsigned int uid, void *data) { GUpdatablePanelIface *iface; /* Interface utilisée */ iface = G_UPDATABLE_PANEL_GET_IFACE(panel); iface->conclude(panel, uid, data); } /****************************************************************************** * * * Paramètres : panel = panneau ciblé par une mise à jour. * * uid = identifiant de la phase de traitement. * * data = données en place à nettoyer avant suppression. * * * * Description : Supprime les données dynamiques utilisées à la mise à jour. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_updatable_panel_clean_data(const GUpdatablePanel *panel, unsigned int uid, void *data) { GUpdatablePanelIface *iface; /* Interface utilisée */ iface = G_UPDATABLE_PANEL_GET_IFACE(panel); if (iface->clean != NULL && data != NULL) iface->clean(panel, uid, data); } /* ---------------------------------------------------------------------------------- */ /* AIDE POUR LA MISE A JOUR */ /* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour les tâches de mise à jour de panneau. */ G_DEFINE_TYPE(GPanelUpdate, g_panel_update, G_TYPE_DELAYED_WORK); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des tâches des mises à jour de panneaux.* * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_panel_update_class_init(GPanelUpdateClass *klass) { GObjectClass *object; /* Autre version de la classe */ GDelayedWorkClass *work; /* Version en classe parente */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_panel_update_dispose; object->finalize = (GObjectFinalizeFunc)g_panel_update_finalize; work = G_DELAYED_WORK_CLASS(klass); work->run = (run_task_fc)g_panel_update_process; } /****************************************************************************** * * * Paramètres : update = instance à initialiser. * * * * Description : Initialise une tâche d'étude de mise à jour. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_panel_update_init(GPanelUpdate *update) { update->panel = NULL; update->uid = -1; update->max = 0; update->data = NULL; update->msg = NULL; } /****************************************************************************** * * * Paramètres : update = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_panel_update_dispose(GPanelUpdate *update) { if (update->panel != NULL) g_updatable_panel_clean_data(update->panel, update->uid, update->data); g_clear_object(&update->panel); G_OBJECT_CLASS(g_panel_update_parent_class)->dispose(G_OBJECT(update)); } /****************************************************************************** * * * Paramètres : update = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_panel_update_finalize(GPanelUpdate *update) { if (update->data != NULL) free(update->data); if (update->msg != NULL) free(update->msg); G_OBJECT_CLASS(g_panel_update_parent_class)->finalize(G_OBJECT(update)); } /****************************************************************************** * * * Paramètres : panel = interface permettant une mise à jour de panneau. * * uid = identifiant à associer à la procédure. * * * * Description : Crée une tâche de mise à jour non bloquante. * * * * Retour : Tâche créée. * * * * Remarques : - * * * ******************************************************************************/ GPanelUpdate *g_panel_update_new(GUpdatablePanel *panel, unsigned int uid) { GPanelUpdate *result; /* Tâche à retourner */ bool status; /* Bilan de la préparation */ result = g_object_new(G_TYPE_PANEL_UPDATE, NULL); g_object_ref(G_OBJECT(panel)); result->panel = panel; result->uid = uid; status = g_updatable_panel_setup(panel, uid, &result->max, &result->data, &result->msg); if (!status) g_clear_object(&result); return result; } /****************************************************************************** * * * Paramètres : update = opération de mise à jour à mener. * * status = barre de statut à tenir informée. * * * * Description : Assure la mise à jour d'un panneau en différé. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_panel_update_process(GPanelUpdate *update, GtkStatusStack *status) { activity_id_t id; /* Identifiant de progression */ id = gtk_status_stack_add_activity(status, update->msg, update->max); g_updatable_panel_process(update->panel, update->uid, status, id, update->data); gtk_status_stack_remove_activity(status, id); } /****************************************************************************** * * * Paramètres : update = tâche venant de se terminer. * * panel = interface visée par la procédure. * * * * Description : Marque l'achèvement d'une mise à jour de panneau. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void conclude_panel_update(GPanelUpdate *update, GUpdatablePanel *panel) { g_updatable_panel_conclude(panel, update->uid, update->data); } /* ---------------------------------------------------------------------------------- */ /* ENCAPSULATION DE HAUT NIVEAU */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : panel = interface permettant une mise à jour de panneau. * * uid = identifiant à associer à la procédure. * * * * Description : Prépare et lance l'actualisation d'un panneau. * * * * Retour : - * * * * Remarques : Cette fonction est à appeler depuis le contexte principal. * * * ******************************************************************************/ void run_panel_update(GUpdatablePanel *panel, unsigned int uid) { GWorkQueue *queue; /* Gestionnaire de tâches */ wgroup_id_t gid; /* Groupe de travail à utiliser*/ GPanelUpdate *update; /* Procédure de mise à jour */ update = g_panel_update_new(panel, uid); if (update != NULL) { g_signal_connect_to_main(update, "work-completed", G_CALLBACK(conclude_panel_update), panel, g_cclosure_marshal_VOID__VOID); g_updatable_panel_introduce(panel, uid, update->data); queue = get_work_queue(); gid = g_updatable_panel_get_group(panel); g_work_queue_schedule_work(queue, G_DELAYED_WORK(update), gid); } }