From 7b9727379e1c3f2aefc4ac0db0e91d0cfb0a481f Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 3 Dec 2018 14:16:32 +0100
Subject: Built a dialog box to change storage options.

---
 src/analysis/binary.c         |  48 ++++---
 src/analysis/binary.h         |  15 +--
 src/analysis/db/collection.c  |  22 +++
 src/analysis/db/collection.h  |   3 +
 src/analysis/db/protocol.h    |   7 +-
 src/gui/dialogs/Makefile.am   |   4 +-
 src/gui/dialogs/binadmin.ui   | 183 -------------------------
 src/gui/dialogs/gresource.xml |   2 +-
 src/gui/dialogs/storage.c     | 195 +++++++++++++++++++++++----
 src/gui/dialogs/storage.h     |   3 +
 src/gui/dialogs/storage.ui    | 302 ++++++++++++++++++++++++++++++++++++++++++
 src/gui/menus/binary.c        |   6 +-
 src/gui/panels/history.c      |  37 +++---
 13 files changed, 565 insertions(+), 262 deletions(-)
 delete mode 100644 src/gui/dialogs/binadmin.ui
 create mode 100644 src/gui/dialogs/storage.ui

diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index c327696..6cc3c74 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -69,7 +69,7 @@ struct _GLoadedBinary
     char *username;                         /* Identifiant de l'utilisateur*/
     bool username_changed;                  /* Mémorise les changements    */
 
-    bool local_storage;                     /* Enregistrements locaux ?    */
+    bool use_remote;                        /* Enregistrements distants ?  */
     char *remote_host;                      /* Nom du serveur distant      */
     unsigned short remote_port;             /* Port du serveur distant     */
 
@@ -230,7 +230,7 @@ static void g_loaded_binary_init(GLoadedBinary *binary)
 {
     binary->username = strdup("default");
 
-    binary->local_storage = true;
+    binary->use_remote = false;
     binary->remote_host = strdup("localhost");
     binary->remote_port = 1337;
 
@@ -437,10 +437,10 @@ static bool g_loaded_binary_load_storage(GLoadedBinary *binary, xmlXPathContext
     storage_path = strdup(path);
     storage_path = stradd(storage_path, "/Storage");
 
-    value = get_node_prop_value(context, storage_path, "local");
+    value = get_node_prop_value(context, storage_path, "remote");
     if (value == NULL) goto glbls_no_storage_config;
 
-    binary->local_storage = (strcmp(value, "true") == 0);
+    binary->use_remote = (strcmp(value, "true") == 0);
 
     free(value);
 
@@ -559,8 +559,8 @@ static bool g_loaded_binary_save_storage(const GLoadedBinary *binary, xmlDoc *xd
     storage_path = strdup(path);
     storage_path = stradd(storage_path, "/Storage");
 
-    result &= add_string_attribute_to_node(xdoc, context, storage_path, "local",
-                                           binary->local_storage ? "true" : "false");
+    result &= add_string_attribute_to_node(xdoc, context, storage_path, "remote",
+                                           binary->use_remote ? "true" : "false");
 
     /* Nom d'utilisateur */
 
@@ -681,9 +681,9 @@ void g_loaded_binary_set_username(GLoadedBinary *binary, const char *username)
 *                                                                             *
 ******************************************************************************/
 
-bool g_loaded_binary_get_local_storage(const GLoadedBinary *binary)
+bool g_loaded_binary_use_remote_storage(const GLoadedBinary *binary)
 {
-    return binary->local_storage;
+    return binary->use_remote;
 
 }
 
@@ -691,7 +691,7 @@ bool g_loaded_binary_get_local_storage(const GLoadedBinary *binary)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = élément binaire à consulter.                        *
-*                local  = statut de l'utilisation du serveur local.           *
+*                use    = statut de l'utilisation du serveur distant.         *
 *                                                                             *
 *  Description : Définit si tous les enregistrements sont locaux ou non.      *
 *                                                                             *
@@ -701,11 +701,11 @@ bool g_loaded_binary_get_local_storage(const GLoadedBinary *binary)
 *                                                                             *
 ******************************************************************************/
 
-void g_loaded_binary_set_local_storage(GLoadedBinary *binary, bool local)
+void g_loaded_binary_set_remote_storage_usage(GLoadedBinary *binary, bool use)
 {
-    binary->local_storage = local;
+    binary->use_remote = use;
 
-    if (local)
+    if (use)
         /* TODO : reload conn ! */;
     else
         /* TODO : stop conn ! */;
@@ -1029,18 +1029,36 @@ GDbClient *g_loaded_binary_get_db_client(const GLoadedBinary *binary)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : binary = élément binaire à consulter.                        *
+*                count  = taille de la liste constituée. [OUT]                *
 *                                                                             *
 *  Description : Fournit l'ensemble des collections utilisées par un binaire. *
 *                                                                             *
-*  Retour      : Collections en place.                                        *
+*  Retour      : Liste de collections en place à libérer après usage.         *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GList *g_loaded_binary_get_all_collections(const GLoadedBinary *binary)
+GDbCollection **g_loaded_binary_get_all_collections(const GLoadedBinary *binary, size_t *count)
 {
-    return binary->collections;
+    GDbCollection **result;                 /* Liste à retourner           */
+    GList *c;                               /* Boucle de parcours #1       */
+    size_t i;                               /* Boucle de parcours #2       */
+
+    *count = g_list_length(binary->collections);
+
+    result = malloc(*count * sizeof(GDbCollection *));
+
+    for (c = g_list_first(binary->collections), i = 0; c != NULL; c = g_list_next(c), i++)
+    {
+        assert(i < *count);
+
+        result[i] = G_DB_COLLECTION(c->data);
+        g_object_ref(G_OBJECT(result[i]));
+
+    }
+
+    return result;
 
 }
 
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index 7c2c760..831cade 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -91,10 +91,10 @@ const char *g_loaded_binary_get_username(const GLoadedBinary *);
 void g_loaded_binary_set_username(GLoadedBinary *, const char *);
 
 /* Détermine si tous les enregistrements sont locaux ou non. */
-bool g_loaded_binary_get_local_storage(const GLoadedBinary *);
+bool g_loaded_binary_use_remote_storage(const GLoadedBinary *);
 
 /* Définit si tous les enregistrements sont locaux ou non. */
-void g_loaded_binary_set_local_storage(GLoadedBinary *, bool);
+void g_loaded_binary_set_remote_storage_usage(GLoadedBinary *, bool);
 
 /* Identifie le serveur distant associé au binaire courant. */
 void g_loaded_binary_get_remote_server(const GLoadedBinary *, const char **, unsigned short *);
@@ -120,7 +120,7 @@ bool g_loaded_binary_save_cache(const GLoadedBinary *);
 GDbClient *g_loaded_binary_get_db_client(const GLoadedBinary *);
 
 /* Fournit l'ensemble des collections utilisées par un binaire. */
-GList *g_loaded_binary_get_all_collections(const GLoadedBinary *);
+GDbCollection **g_loaded_binary_get_all_collections(const GLoadedBinary *, size_t *);
 
 /* Trouve une collection assurant une fonctionnalité donnée. */
 GDbCollection *g_loaded_binary_find_collection(const GLoadedBinary *, DBFeatures);
@@ -139,15 +139,6 @@ bool _g_loaded_binary_remove_from_collection(GLoadedBinary *, DBFeatures, GDbIte
 
 
 
-/**
- * TODO :
- *
- * - connect_signal
- * - add_obj
- *
- */
-
-
 
 
 
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c
index a99c2de..adb3ad1 100644
--- a/src/analysis/db/collection.c
+++ b/src/analysis/db/collection.c
@@ -30,6 +30,9 @@
 #include <string.h>
 
 
+#include <i18n.h>
+
+
 #include "collection-int.h"
 #include "misc/rlestr.h"
 #include "../../common/extstr.h"
@@ -242,6 +245,25 @@ uint32_t g_db_collection_get_feature(const GDbCollection *collec)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : collec = collection générique d'éléments à consulter.        *
+*                                                                             *
+*  Description : Décrit le type de collection manipulée.                      *
+*                                                                             *
+*  Retour      : Description humaine de la collection.                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+const char *g_db_collection_get_name(const GDbCollection *collec)
+{
+    return _(collec->name);
+
+}
+
+
 
 
 
diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h
index 5292e89..0f0ad34 100644
--- a/src/analysis/db/collection.h
+++ b/src/analysis/db/collection.h
@@ -67,6 +67,9 @@ void g_db_collection_link_to_binary(GDbCollection *, GLoadedBinary *);
 /* Décrit le type des éléments rassemblées dans une collection. */
 uint32_t g_db_collection_get_feature(const GDbCollection *);
 
+/* Décrit le type de collection manipulée. */
+const char *g_db_collection_get_name(const GDbCollection *);
+
 
 
 
diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h
index 202a923..025f92f 100644
--- a/src/analysis/db/protocol.h
+++ b/src/analysis/db/protocol.h
@@ -46,11 +46,10 @@
 /* Comportement vis à vis des éléments */
 typedef enum _DBStorage
 {
-    DBS_ALL_LOCAL           = 0x01,         /* Enregistrements locaux      */
-    DBS_ALL_REMOTE          = 0x02,         /* Enregistrements distants    */
-    DBS_LOCAL_AND_REMOTE    = 0x03,         /* Enreg. locaux + infos dists.*/
+    DBS_ALL_LOCAL           = 0x00,         /* Enregistrements locaux      */
+    DBS_ALL_REMOTE          = 0x01,         /* Enregistrements distants    */
 
-    DBS_MAX = 3
+    DBS_MAX = 0x01
 
 } DBStorage;
 
diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am
index bfda8ad..35dfb0a 100644
--- a/src/gui/dialogs/Makefile.am
+++ b/src/gui/dialogs/Makefile.am
@@ -4,9 +4,9 @@ BUILT_SOURCES = resources.h resources.c
 noinst_LTLIBRARIES  = libguidialogs.la
 
 UI_FILES =								\
-	binadmin.ui							\
 	bookmark.ui							\
-	identity.ui
+	identity.ui							\
+	storage.ui
 
 libguidialogs_la_SOURCES =				\
 	about.h about.c						\
diff --git a/src/gui/dialogs/binadmin.ui b/src/gui/dialogs/binadmin.ui
deleted file mode 100644
index 0f68228..0000000
--- a/src/gui/dialogs/binadmin.ui
+++ /dev/null
@@ -1,183 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
-<interface>
-  <requires lib="gtk+" version="3.12"/>
-  <object class="GtkAdjustment" id="adjustment1">
-    <property name="lower">1</property>
-    <property name="upper">65535</property>
-    <property name="value">1337</property>
-    <property name="step_increment">1</property>
-    <property name="page_increment">10</property>
-  </object>
-  <object class="GtkDialog" id="window">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Storage</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
-    <property name="default_width">700</property>
-    <property name="default_height">300</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox1">
-        <property name="can_focus">False</property>
-        <property name="margin_left">8</property>
-        <property name="margin_right">8</property>
-        <property name="margin_top">8</property>
-        <property name="margin_bottom">8</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">8</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action_area1">
-            <property name="can_focus">False</property>
-            <property name="margin_top">8</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="button1">
-                <property name="label" translatable="yes">Cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button2">
-                <property name="label" translatable="yes">Apply</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox" id="box1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">8</property>
-            <child>
-              <object class="GtkRadioButton" id="local_storage">
-                <property name="label" translatable="yes">Use the internal local server.</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="xalign">0</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkRadioButton" id="server_storage">
-                <property name="label" translatable="yes">Use a remote shared server:</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="xalign">0</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">True</property>
-                <property name="group">local_storage</property>
-                <signal name="toggled" handler="on_server_use_toggled" swapped="no"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkBox" id="box2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="margin_left">16</property>
-                <property name="spacing">8</property>
-                <child>
-                  <object class="GtkLabel" id="server_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Server:</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkEntry" id="server">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="text" translatable="yes">localhost</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="port_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Port:</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkSpinButton" id="port">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="adjustment">adjustment1</property>
-                    <property name="value">1337</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">3</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="-6">button1</action-widget>
-      <action-widget response="-10">button2</action-widget>
-    </action-widgets>
-  </object>
-</interface>
diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml
index 4c2f30a..e44045c 100644
--- a/src/gui/dialogs/gresource.xml
+++ b/src/gui/dialogs/gresource.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
     <gresource prefix="/org/chrysalide/gui/dialogs">
-        <file compressed="true">binadmin.ui</file>
         <file compressed="true">bookmark.ui</file>
         <file compressed="true">identity.ui</file>
+        <file compressed="true">storage.ui</file>
     </gresource>
 </gresources>
diff --git a/src/gui/dialogs/storage.c b/src/gui/dialogs/storage.c
index 46ef675..4aed524 100644
--- a/src/gui/dialogs/storage.c
+++ b/src/gui/dialogs/storage.c
@@ -25,11 +25,26 @@
 
 
 
+/* Colonnes de la liste des collections */
+typedef enum _CollecFeatureColumn
+{
+    CFC_COLLECTION,                         /* Instance GLib               */
+
+    CFC_NAME,                               /* Désignation humaine         */
+    CFC_LOCAL,                              /* Sauvegarde locale ?         */
+    CFC_REMOTE,                             /* Sauvegarde distante ?       */
+
+} CollecFeatureColumn;
+
+
 /* Réagit à un changement dans le choix du type de serveur. */
 static void on_server_use_toggled(GtkToggleButton *, GtkBuilder *);
 
-/* Applique les paramètres d'enregistrement pour un binaire. */
-static void update_binary_storage(GtkButton *, GtkBuilder *);
+/* Bascule le lieu d'enregistrement d'un type de collection. */
+static void on_local_feature_toggled(GtkCellRendererToggle *, gchar *, GtkBuilder *);
+
+/* Bascule le lieu d'enregistrement d'un type de collection. */
+static void on_remote_feature_toggled(GtkCellRendererToggle *, gchar *, GtkBuilder *);
 
 
 
@@ -51,30 +66,32 @@ GtkWidget *create_storage_dialog(GLoadedBinary *binary, GtkWindow *parent, GtkBu
 {
     GtkWidget *result;                      /* Fenêtre à renvoyer          */
     GtkBuilder *builder;                    /* Constructeur utilisé        */
-    GtkToggleButton *local_button;          /* Choix du serveur local      */
-    GtkToggleButton *remote_button;         /* Choix du serveur distant    */
+    GtkToggleButton *use_remote;            /* Choix du serveur distant    */
     const char *host;                       /* Serveur distant à contacter */
     unsigned short port;                    /* Port d'écoute du serveur    */
     GObject *widget;                        /* Composant à mettre à jour   */
-
-    builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/binadmin.ui");
+    GtkListStore *store;                    /* Modèle de gestion           */
+    GDbCollection **collections;            /* Ensemble de collections     */
+    size_t count;                           /* Taille de cet ensemble      */
+    size_t i;                               /* Boucle de parcours          */
+    uint32_t feature;                       /* Type d'éléments gérés       */
+    GtkTreeIter iter;                       /* Point d'insertion           */
+
+    builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/storage.ui");
     *outb = builder;
 
-    g_object_set_data(G_OBJECT(builder), "binary", binary);
-
     result = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
 
     gtk_window_set_transient_for(GTK_WINDOW(result), parent);
 
     /* Mise à jour de l'interface */
 
-    local_button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "local_storage"));
-    remote_button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "remote_storage"));
+    use_remote = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "use_remote"));
 
-    if (g_loaded_binary_get_local_storage(binary))
-        gtk_toggle_button_set_active(local_button, TRUE);
+    if (g_loaded_binary_use_remote_storage(binary))
+        gtk_toggle_button_set_active(use_remote, TRUE);
     else
-        gtk_toggle_button_set_active(remote_button, TRUE);
+        gtk_toggle_button_set_active(use_remote, FALSE);
 
     g_loaded_binary_get_remote_server(binary, &host, &port);
 
@@ -84,13 +101,39 @@ GtkWidget *create_storage_dialog(GLoadedBinary *binary, GtkWindow *parent, GtkBu
     widget = gtk_builder_get_object(builder, "port");
     gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), port);
 
-    on_server_use_toggled(remote_button, builder);
+    on_server_use_toggled(use_remote, builder);
+
+    /* Intégration des différentes collections */
+
+    store = GTK_LIST_STORE(gtk_builder_get_object(builder, "store"));
+
+    collections = g_loaded_binary_get_all_collections(binary, &count);
+
+    for (i = 0; i < count; i++)
+    {
+        feature = g_db_collection_get_feature(collections[i]);
+
+        gtk_list_store_append(store, &iter);
+        gtk_list_store_set(store, &iter,
+                           CFC_COLLECTION, collections[i],
+                           CFC_NAME, g_db_collection_get_name(collections[i]),
+                           CFC_LOCAL, g_loaded_binary_get_storage(binary, feature) == DBS_ALL_LOCAL,
+                           CFC_REMOTE, g_loaded_binary_get_storage(binary, feature) != DBS_ALL_LOCAL,
+                           -1);
+
+        g_object_unref(G_OBJECT(collections[i]));
+
+    }
+
+    if (collections != NULL)
+        free(collections);
 
     /* Connexion des signaux */
 
     gtk_builder_add_callback_symbols(builder,
                                      "on_server_use_toggled", G_CALLBACK(on_server_use_toggled),
-                                     "update_binary_storage", G_CALLBACK(update_binary_storage),
+                                     "on_local_feature_toggled", G_CALLBACK(on_local_feature_toggled),
+                                     "on_remote_feature_toggled", G_CALLBACK(on_remote_feature_toggled),
                                      NULL);
 
     gtk_builder_connect_signals(builder, builder);
@@ -137,8 +180,84 @@ static void on_server_use_toggled(GtkToggleButton *button, GtkBuilder *builder)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : button  = bouton à l'origine de la procédure.                *
-*                builder = espace de référencement global.                    *
+*  Paramètres  : renderer = rendu de cellule à l'origine de la procédure.     *
+*                path     = chemin d'accès à la ligne éditée.                 *
+*                builder  = espace de référencement global.                   *
+*                                                                             *
+*  Description : Bascule le lieu d'enregistrement d'un type de collection.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_local_feature_toggled(GtkCellRendererToggle *renderer, gchar *path, GtkBuilder *builder)
+{
+    GtkTreePath *access;                    /* Véritable chemin d'accès    */
+    GtkTreeModel *model;                    /* Modèle de gestion utilisé   */
+    GtkTreeIter iter;                       /* Point d'actualisation       */
+
+    access = gtk_tree_path_new_from_string(path);
+
+    model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store"));
+
+    if (gtk_tree_model_get_iter(model, &iter, access))
+    {
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+                           CFC_LOCAL, true,
+                           CFC_REMOTE, false,
+                           -1);
+
+    }
+
+    gtk_tree_path_free(access);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : renderer = rendu de cellule à l'origine de la procédure.     *
+*                path     = chemin d'accès à la ligne éditée.                 *
+*                builder  = espace de référencement global.                   *
+*                                                                             *
+*  Description : Bascule le lieu d'enregistrement d'un type de collection.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void on_remote_feature_toggled(GtkCellRendererToggle *renderer, gchar *path, GtkBuilder *builder)
+{
+    GtkTreePath *access;                    /* Véritable chemin d'accès    */
+    GtkTreeModel *model;                    /* Modèle de gestion utilisé   */
+    GtkTreeIter iter;                       /* Point d'actualisation       */
+
+    access = gtk_tree_path_new_from_string(path);
+
+    model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store"));
+
+    if (gtk_tree_model_get_iter(model, &iter, access))
+    {
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+                           CFC_LOCAL, false,
+                           CFC_REMOTE, true,
+                           -1);
+
+    }
+
+    gtk_tree_path_free(access);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : builder = espace de référencement global.                    *
+*                binary  = binaire chargé en mémoire à traiter.               *
 *                                                                             *
 *  Description : Applique les paramètres d'enregistrement pour un binaire.    *
 *                                                                             *
@@ -148,16 +267,19 @@ static void on_server_use_toggled(GtkToggleButton *button, GtkBuilder *builder)
 *                                                                             *
 ******************************************************************************/
 
-static void update_binary_storage(GtkButton *button, GtkBuilder *builder)
+void update_binary_storage(GtkBuilder *builder, GLoadedBinary *binary)
 {
-    GLoadedBinary *binary;                  /* Binaire à mettre à jour     */
     GObject *widget;                        /* Composant à mettre à jour   */
     const gchar *host;                      /* Serveur distant à contacter */
     gint port;                              /* Port d'écoute du serveur    */
-    GtkToggleButton *local_button;          /* Choix du serveur local      */
-    gboolean active;                        /* Etat du choix du local      */
-
-    binary = G_LOADED_BINARY(g_object_get_data(G_OBJECT(builder), "binary"));
+    GtkToggleButton *use_remote;            /* Choix du serveur distant    */
+    gboolean active;                        /* Etat du choix du distant    */
+    GtkTreeModel *model;                    /* Modèle de gestion utilisé   */
+    GtkTreeIter iter;                       /* Itérateur de consultation   */
+    gboolean valid;                         /* Validité de l'itérateur     */
+    GDbCollection *collec;                  /* Collection à traiter        */
+    gboolean local;                         /* Conservation locale ?       */
+    uint32_t feature;                       /* Type d'éléments gérés       */
 
     /* Infos de connexions à distance */
 
@@ -171,10 +293,31 @@ static void update_binary_storage(GtkButton *button, GtkBuilder *builder)
 
     /* Choix final du serveur */
 
-    local_button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "local_storage"));
+    use_remote = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "use_remote"));
+
+    active = gtk_toggle_button_get_active(use_remote);
+
+    g_loaded_binary_set_remote_storage_usage(binary, active);
+
+    /* Type de conservation des éléments */
+
+    model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "store"));
+
+    for (valid = gtk_tree_model_get_iter_first(model, &iter);
+         valid;
+         valid = gtk_tree_model_iter_next(model, &iter))
+    {
+        gtk_tree_model_get(model, &iter,
+                           CFC_COLLECTION, &collec,
+                           CFC_LOCAL, &local,
+                           -1);
+
+        feature = g_db_collection_get_feature(collec);
+
+        g_loaded_binary_set_storage(binary, feature, local ? DBS_ALL_LOCAL : DBS_ALL_REMOTE);
 
-    active = gtk_toggle_button_get_active(local_button);
+        g_object_unref(G_OBJECT(collec));
 
-    g_loaded_binary_set_local_storage(binary, active);
+    }
 
 }
diff --git a/src/gui/dialogs/storage.h b/src/gui/dialogs/storage.h
index 6e0c9f0..f7cd65a 100644
--- a/src/gui/dialogs/storage.h
+++ b/src/gui/dialogs/storage.h
@@ -35,6 +35,9 @@
 /* Propose une définition des propriétés d'enregistrement. */
 GtkWidget *create_storage_dialog(GLoadedBinary *, GtkWindow *, GtkBuilder **);
 
+/* Applique les paramètres d'enregistrement pour un binaire. */
+void update_binary_storage(GtkBuilder *, GLoadedBinary *);
+
 
 
 #endif  /* _GUI_DIALOGS_STORAGE_H */
diff --git a/src/gui/dialogs/storage.ui b/src/gui/dialogs/storage.ui
new file mode 100644
index 0000000..0a65f47
--- /dev/null
+++ b/src/gui/dialogs/storage.ui
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.21.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkAdjustment" id="port_adj">
+    <property name="lower">1</property>
+    <property name="upper">65535</property>
+    <property name="value">0.01</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkListStore" id="store">
+    <columns>
+      <!-- column-name collec -->
+      <column type="GObject"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+      <!-- column-name local -->
+      <column type="gboolean"/>
+      <!-- column-name remote -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="window">
+    <property name="can_focus">False</property>
+    <property name="margin_left">4</property>
+    <property name="margin_right">4</property>
+    <property name="margin_top">4</property>
+    <property name="margin_bottom">4</property>
+    <property name="title" translatable="yes">Storage</property>
+    <property name="modal">True</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="default_width">500</property>
+    <property name="default_height">350</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button1">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button2">
+                <property name="label">gtk-apply</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">8</property>
+            <child>
+              <object class="GtkFrame">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
+                        <property name="spacing">8</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">Note: DB items will use local storage as fallback if this server can not be contacted.</property>
+                            <property name="wrap">True</property>
+                            <property name="xalign">0</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="spacing">8</property>
+                            <child>
+                              <object class="GtkLabel" id="server_label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="label" translatable="yes">Server:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkEntry" id="server">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                              </object>
+                              <packing>
+                                <property name="expand">True</property>
+                                <property name="fill">True</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="port_label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="label" translatable="yes">Port:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSpinButton" id="port">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="max_width_chars">5</property>
+                                <property name="text" translatable="yes">1</property>
+                                <property name="adjustment">port_adj</property>
+                                <property name="value">1</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkCheckButton" id="use_remote">
+                    <property name="label" translatable="yes">Use a remote shared server</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="draw_indicator">True</property>
+                    <signal name="toggled" handler="on_server_use_toggled" swapped="no"/>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkScrolledWindow">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="GtkTreeView">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="model">store</property>
+                            <child internal-child="selection">
+                              <object class="GtkTreeSelection"/>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn">
+                                <property name="title" translatable="yes">Name</property>
+                                <property name="expand">True</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="name"/>
+                                  <attributes>
+                                    <attribute name="text">1</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn">
+                                <property name="title" translatable="yes">Local</property>
+                                <child>
+                                  <object class="GtkCellRendererToggle" id="local">
+                                    <property name="radio">True</property>
+                                    <signal name="toggled" handler="on_local_feature_toggled" swapped="no"/>
+                                  </object>
+                                  <attributes>
+                                    <attribute name="active">2</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn">
+                                <property name="title" translatable="yes">Remote</property>
+                                <child>
+                                  <object class="GtkCellRendererToggle" id="remote">
+                                    <property name="radio">True</property>
+                                    <signal name="toggled" handler="on_remote_feature_toggled" swapped="no"/>
+                                  </object>
+                                  <attributes>
+                                    <attribute name="active">3</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">DB items</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">button1</action-widget>
+      <action-widget response="-10">button2</action-widget>
+    </action-widgets>
+    <child>
+      <placeholder/>
+    </child>
+  </object>
+</interface>
diff --git a/src/gui/menus/binary.c b/src/gui/menus/binary.c
index 954f3d4..c4c4e22 100644
--- a/src/gui/menus/binary.c
+++ b/src/gui/menus/binary.c
@@ -226,12 +226,16 @@ static void mcb_binary_storage(GtkMenuItem *menuitem, GMenuBar *bar)
     GLoadedBinary *binary;                  /* Edition courante            */
     GtkBuilder *builder;                    /* Constructeur utilisé        */
     GtkWidget *dialog;                      /* Boîte de dialogue à montrer */
+    gint ret;                               /* Retour de confirmation      */
 
     binary = G_LOADED_BINARY(get_current_content());
 
     dialog = create_storage_dialog(binary, get_editor_window(), &builder);
 
-    gtk_dialog_run(GTK_DIALOG(dialog));
+    ret = gtk_dialog_run(GTK_DIALOG(dialog));
+
+    if (ret == GTK_RESPONSE_APPLY)
+        update_binary_storage(builder, binary);
 
     gtk_widget_destroy(dialog);
 
diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c
index a1aa36b..9edd32e 100644
--- a/src/gui/panels/history.c
+++ b/src/gui/panels/history.c
@@ -272,9 +272,9 @@ GPanelItem *g_history_panel_new(void)
 static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedContent *old, GLoadedContent *new)
 {
     GLoadedBinary *binary;                  /* Autre version de l'instance */
-    GList *collections;                     /* Ensemble de collections     */
-    GList *c;                               /* Boucle de parcours #1       */
-    GDbCollection *collec;                  /* Collection visée manipulée  */
+    GDbCollection **collections;            /* Ensemble de collections     */
+    size_t count;                           /* Taille de cet ensemble      */
+    size_t k;                               /* Boucle de parcours #1       */
     GtkBuilder *builder;                    /* Constructeur utilisé        */
     GtkListStore *store;                    /* Modèle de gestion           */
     GList *items;                           /* Liste des éléments groupés  */
@@ -291,17 +291,16 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo
 
     if (panel->binary != NULL)
     {
-        collections = g_loaded_binary_get_all_collections(panel->binary);
+        collections = g_loaded_binary_get_all_collections(panel->binary, &count);
 
-        rlock_collections(collections);
-
-        for (c = g_list_first(collections); c != NULL; c = g_list_next(c))
+        for (k = 0; k < count; k++)
         {
-            collec = G_DB_COLLECTION(c->data);
-            g_signal_handlers_disconnect_by_func(collec, G_CALLBACK(on_history_changed), panel);
+            g_signal_handlers_disconnect_by_func(collections[k], G_CALLBACK(on_history_changed), panel);
+            g_object_unref(G_OBJECT(collections[k]));
         }
 
-        runlock_collections(collections);
+        if (collections != NULL)
+            free(collections);
 
         g_object_unref(G_OBJECT(panel->binary));
 
@@ -324,14 +323,13 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo
 
     /* Actualisation de l'affichage */
 
-    collections = g_loaded_binary_get_all_collections(binary);
-
-    rlock_collections(collections);
+    collections = g_loaded_binary_get_all_collections(binary, &count);
 
-    for (c = g_list_first(collections); c != NULL; c = g_list_next(c))
+    for (k = 0; k < count; k++)
     {
-        collec = G_DB_COLLECTION(c->data);
-        items = g_db_collection_list_items(collec);
+        g_db_collection_rlock(collections[k]);
+
+        items = g_db_collection_list_items(collections[k]);
 
         for (i = g_list_first(items); i != NULL; i = g_list_next(i))
         {
@@ -347,12 +345,15 @@ static void change_history_panel_current_content(GHistoryPanel *panel, GLoadedCo
 
         }
 
-        g_signal_connect_to_main(collec, "content-changed", G_CALLBACK(on_history_changed), panel,
+        g_signal_connect_to_main(collections[k], "content-changed", G_CALLBACK(on_history_changed), panel,
                                  g_cclosure_user_marshal_VOID__ENUM_OBJECT);
 
+        g_object_unref(G_OBJECT(collections[k]));
+
     }
 
-    runlock_collections(collections);
+    if (collections != NULL)
+        free(collections);
 
     /* Force une sélection initiale */
     on_history_changed(NULL, DBA_COUNT, NULL, panel);
-- 
cgit v0.11.2-87-g4458