From 0daafbb6b4c0e845f9e61a28adb0a68bb2d0b582 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 26 Nov 2018 00:18:38 +0100
Subject: Displayed and hidden loaded contents on project change.

---
 src/analysis/project.c | 109 ++++++++++++++++++++++---------------------------
 src/analysis/project.h |  16 +++++---
 src/gui/editor.c       |  96 ++++++++++++++++++++++++++++++++++++++-----
 src/gui/menus/file.c   |   3 --
 4 files changed, 144 insertions(+), 80 deletions(-)

diff --git a/src/analysis/project.c b/src/analysis/project.c
index 4a15ea0..4399fc4 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -257,7 +257,7 @@ static void g_study_project_dispose(GStudyProject *project)
 {
     size_t i;                               /* Boucle de parcours          */
 
-    g_mutex_lock(&project->mutex);
+    g_study_project_lock_contents(project);
 
     for (i = 0; i < project->count; i++)
         g_object_unref(G_OBJECT(project->contents[i]));
@@ -265,7 +265,7 @@ static void g_study_project_dispose(GStudyProject *project)
     if (project->contents != NULL)
         free(project->contents);
 
-    g_mutex_unlock(&project->mutex);
+    g_study_project_unlock_contents(project);
 
     g_mutex_clear(&project->mutex);
 
@@ -400,7 +400,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
 
     root_count = 0;
 
-    g_mutex_lock(&project->mutex);
+    g_study_project_lock_contents(project);
 
     for (i = 0; i < project->count && result; i++)
     {
@@ -469,7 +469,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
 
     }
 
-    g_mutex_unlock(&project->mutex);
+    g_study_project_unlock_contents(project);
 
     /* Sauvegarde finale */
 
@@ -602,6 +602,29 @@ static void on_loaded_content_analyzed(GLoadedContent *content, gboolean success
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : project = project à manipuler.                               *
+*                lock    = sélection du type de traitement à opérer.          *
+*                                                                             *
+*  Description : Verrouille ou déverrouille l'accès aux contenus chargés.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void _g_study_project_lock_unlock_contents(GStudyProject *project, bool lock)
+{
+    if (lock)
+        g_mutex_lock(&project->mutex);
+    else
+        g_mutex_unlock(&project->mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = project à manipuler.                               *
 *                content = contenu chargé à associer au projet actuel.        *
 *                                                                             *
 *  Description : Attache un contenu donné à un projet donné.                  *
@@ -614,7 +637,7 @@ static void on_loaded_content_analyzed(GLoadedContent *content, gboolean success
 
 void g_study_project_attach_content(GStudyProject *project, GLoadedContent *content)
 {
-    g_mutex_lock(&project->mutex);
+    g_study_project_lock_contents(project);
 
     project->contents = (GLoadedContent **)realloc(project->contents,
                                                    ++project->count * sizeof(GLoadedContent *));
@@ -622,7 +645,7 @@ void g_study_project_attach_content(GStudyProject *project, GLoadedContent *cont
     project->contents[project->count - 1] = content;
     g_object_ref(G_OBJECT(content));
 
-    g_mutex_unlock(&project->mutex);
+    g_study_project_unlock_contents(project);
 
     g_signal_emit_by_name(project, "content-added", content);
 
@@ -646,7 +669,7 @@ void g_study_project_detach_content(GStudyProject *project, GLoadedContent *cont
 {
     size_t i;                               /* Boucle de parcours          */
 
-    g_mutex_lock(&project->mutex);
+    g_study_project_lock_contents(project);
 
     for (i = 0; i < project->count; i++)
         if (project->contents[i] == content) break;
@@ -658,7 +681,7 @@ void g_study_project_detach_content(GStudyProject *project, GLoadedContent *cont
     project->contents = (GLoadedContent **)realloc(project->contents,
                                                    --project->count * sizeof(GLoadedContent *));
 
-    g_mutex_unlock(&project->mutex);
+    g_study_project_unlock_contents(project);
 
     g_signal_emit_by_name(project, "content-removed", content);
 
@@ -670,62 +693,34 @@ void g_study_project_detach_content(GStudyProject *project, GLoadedContent *cont
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : project = projet dont le contenu est à afficher.             *
+*                count = nombre de contenus pris en compte. [OUT]             *
 *                                                                             *
-*  Description : Met en place un projet à l'écran.                            *
+*  Description : Fournit l'ensemble des contenus associés à un projet.        *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Liste à libérer de la mémoire.                               *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_study_project_display(const GStudyProject *project)
+GLoadedContent **_g_study_project_get_contents(GStudyProject *project, size_t *count)
 {
-#if 0
-    size_t i;                               /* Boucle de parcours #1       */
-    loaded_binary *handled;                 /* Binaire prise en compte     */
-    size_t j;                               /* Boucle de parcours #2       */
-
-    for (i = 0; i < project->binaries_count; i++)
-    {
-        handled = project->binaries[i];
-
-        for (j = 0; j < handled->count; j++)
-            g_panel_item_dock(handled->items[j]);
-
-    }
-#endif
-}
-
+    GLoadedContent **result;                /* Tableau à retourner         */
+    size_t i;                               /* Boucle de parcours          */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : project = projet dont le contenu est à cacher.               *
-*                                                                             *
-*  Description : Supprime de l'écran un projet en place.                      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    assert(!g_mutex_trylock(&project->mutex));
 
-void g_study_project_hide(const GStudyProject *project)
-{
-#if 0
-    size_t i;                               /* Boucle de parcours #1       */
-    loaded_binary *handled;                 /* Binaire prise en compte     */
-    size_t j;                               /* Boucle de parcours #2       */
+    *count = project->count;
+    result = malloc(*count * sizeof(GLoadedContent *));
 
-    for (i = 0; i < project->binaries_count; i++)
+    for (i = 0; i < *count; i++)
     {
-        handled = project->binaries[i];
+        result[i] = project->contents[i];
+        g_object_ref(G_OBJECT(result[i]));
+    }
 
-        for (j = 0; j < handled->count; j++)
-            g_panel_item_undock(handled->items[j]);
+    return result;
 
-    }
-#endif
 }
 
 
@@ -745,20 +740,12 @@ void g_study_project_hide(const GStudyProject *project)
 GLoadedContent **g_study_project_get_contents(GStudyProject *project, size_t *count)
 {
     GLoadedContent **result;                /* Tableau à retourner         */
-    size_t i;                               /* Boucle de parcours          */
 
-    g_mutex_lock(&project->mutex);
+    g_study_project_lock_contents(project);
 
-    *count = project->count;
-    result = (GLoadedContent **)calloc(*count, sizeof(GLoadedContent *));
-
-    for (i = 0; i < *count; i++)
-    {
-        result[i] = project->contents[i];
-        g_object_ref(G_OBJECT(result[i]));
-    }
+    result = _g_study_project_get_contents(project, count);
 
-    g_mutex_unlock(&project->mutex);
+    g_study_project_unlock_contents(project);
 
     return result;
 
diff --git a/src/analysis/project.h b/src/analysis/project.h
index 2ee178b..c634fb2 100644
--- a/src/analysis/project.h
+++ b/src/analysis/project.h
@@ -77,17 +77,23 @@ const char *g_study_project_get_filename(const GStudyProject *);
 /* Assure l'intégration de contenus binaires dans un projet. */
 void g_study_project_discover_binary_content(GStudyProject *, GBinContent *);
 
+#define g_study_project_lock_contents(p) \
+    _g_study_project_lock_unlock_contents(p, true)
+
+#define g_study_project_unlock_contents(p) \
+    _g_study_project_lock_unlock_contents(p, false)
+
+/* Verrouille ou déverrouille l'accès aux contenus chargés. */
+void _g_study_project_lock_unlock_contents(GStudyProject *, bool);
+
 /* Attache un contenu donné à un projet donné. */
 void g_study_project_attach_content(GStudyProject *, GLoadedContent *);
 
 /* Détache un contenu donné d'un projet donné. */
 void g_study_project_detach_content(GStudyProject *, GLoadedContent *);
 
-/* Met en place un projet à l'écran. */
-void g_study_project_display(const GStudyProject *);
-
-/* Supprime de l'écran un projet en place. */
-void g_study_project_hide(const GStudyProject *);
+/* Fournit l'ensemble des contenus associés à un projet. */
+GLoadedContent **_g_study_project_get_contents(GStudyProject *, size_t *);
 
 /* Fournit l'ensemble des contenus associés à un projet. */
 GLoadedContent **g_study_project_get_contents(GStudyProject *, size_t *);
diff --git a/src/gui/editor.c b/src/gui/editor.c
index 39fd13b..16b7a59 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -132,6 +132,8 @@ static gboolean scroll_for_the_first_time(GtkWidget *, GdkEvent *, GLoadedConten
 /* Affiche le contenu qui vient de rejoindre un projet donné. */
 void on_editor_loaded_content_added(GStudyProject *, GLoadedContent *, void *);
 
+/* Recherche et retirer de l'affichage un contenu chargé. */
+static void remove_loaded_content_from_editor(GtkWidget *, GLoadedContent *);
 
 
 
@@ -893,32 +895,39 @@ static void on_dock_close_request(GtkDockStation *station, GtkWidget *button, gp
 
 static void notify_editor_project_change(GStudyProject *project, bool new)
 {
+    GLoadedContent **contents;              /* Contenus chargés à traiter  */
+    size_t count;                           /* Quantité de ces contenus    */
+    size_t i;                               /* Boucle de parcours          */
+    GtkContainer *root;                     /* Racine des panneaux         */
 
-    if (new)
-    {
+    g_study_project_lock_contents(project);
 
+    contents = _g_study_project_get_contents(project, &count);
 
+    if (new)
         g_signal_connect_to_main(project, "content-added", G_CALLBACK(on_editor_loaded_content_added), NULL,
-                               g_cclosure_marshal_VOID__OBJECT);
-
-
-
+                                 g_cclosure_marshal_VOID__OBJECT);
 
-        /* TODO : show_all()... */
+    g_study_project_unlock_contents(project);
 
+    if (new)
+    {
+        for (i = 0; i < count; i++)
+            on_editor_loaded_content_added(project, contents[i], NULL);
 
     }
 
     else
     {
+        root = GTK_CONTAINER(get_tiled_grid());
 
-        g_study_project_hide(project);
-
-
+        for (i = 0; i < count; i++)
+            gtk_container_foreach(root, (GtkCallback)remove_loaded_content_from_editor, contents[i]);
 
     }
 
-
+    if (contents != NULL)
+        free(contents);
 
 }
 
@@ -1000,3 +1009,68 @@ static gboolean scroll_for_the_first_time(GtkWidget *widget, GdkEvent *event, GL
     return FALSE;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : widget  = composant d'affichage nouvellement porté à l'écran.*
+*                content = contenu chargé associé à un composant d'affichage. *
+*                                                                             *
+*  Description : Recherche et retirer de l'affichage un contenu chargé.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void remove_loaded_content_from_editor(GtkWidget *widget, GLoadedContent *content)
+{
+    GtkNotebook *notebook;                  /* Série d'onglets à considérer*/
+    gint count;                             /* Quantité de ces onglets     */
+    gint i;                                 /* Boucle de parcours          */
+    GtkWidget *tab;                         /* Composant d'un onglet       */
+    GPanelItem *panel;                      /* Panneau encapsulé           */
+    GLoadedContent *loaded;                 /* Contenu chargé à comparer   */
+    GtkWidget *built;                       /* Composant construit         */
+
+    if (GTK_IS_DOCK_STATION(widget))
+    {
+        /**
+         * On considère qu'on est le seul à s'exécuter dans le thread d'affichage,
+         * et que donc aucun ajout ne peut venir modifier la constitution des
+         * onglets en cours de parcours !
+         */
+
+        notebook = GTK_NOTEBOOK(widget);
+
+        count = gtk_notebook_get_n_pages(notebook);
+
+        for (i = 0; i < count; i++)
+        {
+            tab = gtk_notebook_get_nth_page(notebook, i);
+
+            panel = G_PANEL_ITEM(g_object_get_data(G_OBJECT(tab), "dockable"));
+
+            if (gtk_panel_item_get_personality(panel) != PIP_BINARY_VIEW)
+                continue;
+
+            built = get_loaded_panel_from_built_view(tab);
+
+            assert(G_IS_LOADED_PANEL(built));
+
+            loaded = g_loaded_panel_get_content(G_LOADED_PANEL(built));
+
+            if (loaded == content)
+                g_panel_item_undock(panel);
+
+            g_object_unref(G_OBJECT(loaded));
+
+        }
+
+    }
+
+    else if (GTK_IS_CONTAINER(widget))
+        gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)remove_loaded_content_from_editor, content);
+
+}
diff --git a/src/gui/menus/file.c b/src/gui/menus/file.c
index 41b17e1..d9232db 100644
--- a/src/gui/menus/file.c
+++ b/src/gui/menus/file.c
@@ -146,8 +146,6 @@ static void mcb_file_new_project(GtkMenuItem *menuitem, gpointer unused)
 
     set_current_project(project);
 
-    g_study_project_display(project);
-
 }
 
 
@@ -193,7 +191,6 @@ static void mcb_file_open_project(GtkMenuItem *menuitem, gpointer unused)
         if (project != NULL)
         {
             set_current_project(project);
-            g_study_project_display(project);
             push_project_into_recent_list(project);
         }
 
-- 
cgit v0.11.2-87-g4458