summaryrefslogtreecommitdiff
path: root/src/gui/panels/welcome.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/panels/welcome.c')
-rw-r--r--src/gui/panels/welcome.c865
1 files changed, 865 insertions, 0 deletions
diff --git a/src/gui/panels/welcome.c b/src/gui/panels/welcome.c
new file mode 100644
index 0000000..209419f
--- /dev/null
+++ b/src/gui/panels/welcome.c
@@ -0,0 +1,865 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * welcome.c - panneau d'accueil par défaut
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "welcome.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <config.h>
+#include <i18n.h>
+
+
+#include "panel-int.h"
+#include "../../common/cpp.h"
+#include "../../common/io.h"
+#include "../../common/net.h"
+#include "../../common/shuffle.h"
+#include "../../core/params.h"
+#include "../../gtkext/support.h"
+
+
+
+/* Panneau d'accueil par défaut (instance) */
+struct _GWelcomePanel
+{
+ GPanelItem parent; /* A laisser en premier */
+
+ GtkBuilder *builder; /* Constructeur utilisé */
+ cairo_surface_t *background; /* Fond pour astuces */
+
+ char **tips; /* Liste de toutes les astuces */
+ size_t count; /* Quantité d'astuces */
+ size_t current; /* Indice de l'astuce courante */
+
+ bool uorigin; /* Origine de l'affichage */
+
+};
+
+/* Panneau d'accueil par défaut (classe) */
+struct _GWelcomePanelClass
+{
+ GPanelItemClass parent; /* A laisser en premier */
+
+};
+
+
+/* Colonnes de la liste des messages */
+typedef enum _RecentProjectColumn
+{
+ RPC_VALID, /* Validité de l'entrée */
+ RPC_FULLPATH, /* Chemin d'accès à un projet */
+
+ RPC_COUNT /* Nombre de colonnes */
+
+} RecentProjectColumn;
+
+
+/* Initialise la classe des panneaux d'accueil par défaut. */
+static void g_welcome_panel_class_init(GWelcomePanelClass *);
+
+/* Initialise une instance de panneau d'accueil par défaut. */
+static void g_welcome_panel_init(GWelcomePanel *);
+
+/* Supprime toutes les références externes. */
+static void g_welcome_panel_dispose(GWelcomePanel *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_welcome_panel_finalize(GWelcomePanel *);
+
+/* Place un panneau dans l'ensemble affiché. */
+static void g_welcome_panel_dock(GWelcomePanel *);
+
+/* Charge l'ensemble des astuces. */
+static void g_welcome_panel_load_tips(GWelcomePanel *);
+
+/* Assure le dessin du fond de la bulle d'astuce. */
+static gboolean on_tip_background_draw(GtkWidget *, cairo_t *, GWelcomePanel *);
+
+/* Réagit à la demande d'étude d'un nouveau binaire. */
+static void on_new_binary_clicked(GtkButton *, GWelcomePanel *);
+
+/* Actualise au besoin la liste des projets récents. */
+static void on_recent_list_changed(GtkRecentManager *, GWelcomePanel *);
+
+/* Recharge une liste à jour des projets récents. */
+static void g_welcome_panel_reload_project_list(GWelcomePanel *, GtkRecentManager *);
+
+/* Réagit à une sélection décidée d'un projet particulier. */
+static void on_row_activated_for_projects(GtkTreeView *, GtkTreePath *, GtkTreeViewColumn *, GWelcomePanel *);
+
+/* Enregistre les conditions d'affichage du panneau d'accueil. */
+static void on_startup_toggled(GtkToggleButton *, GWelcomePanel *);
+
+/* Consulte les versions existantes et affiche une conclusion. */
+static void g_welcome_panel_check_version(GWelcomePanel *);
+
+/* Affiche l'astuce précédente dans la liste globale. */
+static void on_tip_previous_clicked(GtkButton *, GWelcomePanel *);
+
+/* Affiche l'astuce suivante dans la liste globale. */
+static void on_tip_next_clicked(GtkButton *, GWelcomePanel *);
+
+/* Actualise l'affichage des astuces. */
+static void g_welcome_panel_refresh_tip(GWelcomePanel *);
+
+
+/* Indique le type défini pour un panneau d'accueil. */
+G_DEFINE_TYPE(GWelcomePanel, g_welcome_panel, G_TYPE_PANEL_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux d'accueil par défaut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_class_init(GWelcomePanelClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GPanelItemClass *parent; /* Version parente de classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_welcome_panel_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_welcome_panel_finalize;
+
+ parent = G_PANEL_ITEM_CLASS(klass);
+
+ parent->ack_dock = (ack_undock_process_fc)g_welcome_panel_dock;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau d'accueil par défaut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_init(GWelcomePanel *panel)
+{
+ GEditorItem *base; /* Version basique d'instance */
+ GPanelItem *pitem; /* Version parente du panneau */
+ GtkTreeView *treeview; /* Affichage de la liste */
+ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */
+ GtkTreeViewColumn *column; /* Colonne de la liste */
+ GtkToggleButton *button; /* Bouton à bascule à traiter */
+ bool state; /* Etat de la coche à définir */
+ gchar *filename; /* Chemin d'accès à une image */
+
+ /* Eléments de base */
+
+ base = G_EDITOR_ITEM(panel);
+
+ base->name = PANEL_WELCOME_ID;
+
+ pitem = G_PANEL_ITEM(panel);
+
+ pitem->personality = PIP_SINGLETON;
+ pitem->lname = _("Welcome");
+ pitem->dock_at_startup = true;
+ pitem->path = strdup("N");
+
+ panel->uorigin = !pitem->dock_at_startup;
+
+ /* Représentation graphique */
+
+ panel->builder = gtk_builder_new_from_resource("/org/chrysalide/gui/panels/welcome.ui");
+
+ base->widget = GTK_WIDGET(gtk_builder_get_object(panel->builder, "box"));
+ g_object_ref(G_OBJECT(base->widget));
+ gtk_widget_unparent(base->widget);
+
+ /* Liste des projets récents */
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(panel->builder, "treeview"));
+
+ column = gtk_tree_view_column_new();
+ gtk_tree_view_append_column(treeview, column);
+ gtk_tree_view_set_expander_column(treeview, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(column, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(column, renderer, "markup", RPC_FULLPATH);
+
+ /* Affichage au démarrage ? */
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(panel->builder, "startup"));
+
+ g_generic_config_get_value(get_main_configuration(), MPK_WELCOME_STARTUP, &state);
+
+ gtk_toggle_button_set_active(button, state);
+
+ /* Chargement de l'image de fond */
+
+ filename = find_pixmap_file("tipoftheday.png");
+
+ panel->background = cairo_image_surface_create_from_png(filename);
+
+ g_free(filename);
+
+ /* Connexion des signaux */
+
+ gtk_builder_add_callback_symbols(panel->builder,
+ "on_tip_background_draw", G_CALLBACK(on_tip_background_draw),
+ "on_new_binary_clicked", G_CALLBACK(on_new_binary_clicked),
+ "on_row_activated_for_projects", G_CALLBACK(on_row_activated_for_projects),
+ "on_startup_toggled", G_CALLBACK(on_startup_toggled),
+ "on_tip_previous_clicked", G_CALLBACK(on_tip_previous_clicked),
+ "on_tip_next_clicked", G_CALLBACK(on_tip_next_clicked),
+ NULL);
+
+ gtk_builder_connect_signals(panel->builder, panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_dispose(GWelcomePanel *panel)
+{
+ g_object_unref(G_OBJECT(panel->builder));
+
+ free(panel->tips);
+
+ G_OBJECT_CLASS(g_welcome_panel_parent_class)->dispose(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_finalize(GWelcomePanel *panel)
+{
+ cairo_surface_destroy(panel->background);
+
+ G_OBJECT_CLASS(g_welcome_panel_parent_class)->finalize(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un panneau d'accueil par défaut. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPanelItem *g_welcome_panel_new(void)
+{
+ GWelcomePanel *result; /* Structure à retourner */
+ GtkRecentManager *manager; /* Gestionnaire global */
+
+ result = g_object_new(G_TYPE_WELCOME_PANEL, NULL);
+
+ manager = get_projects_manager();
+
+ g_signal_connect(manager, "changed", G_CALLBACK(on_recent_list_changed), result);
+
+ g_welcome_panel_reload_project_list(result, manager);
+
+ g_welcome_panel_load_tips(result);
+
+ g_welcome_panel_check_version(result);
+
+ return G_PANEL_ITEM(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = composant à présenter à l'affichage. *
+* *
+* Description : Place un panneau dans l'ensemble affiché. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_dock(GWelcomePanel *panel)
+{
+ g_welcome_panel_set_user_origin(panel, true);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau d'accueil à mettre à jour. *
+* *
+* Description : Charge l'ensemble des astuces. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_load_tips(GWelcomePanel *panel)
+{
+ size_t i; /* Boucle de parcours */
+
+ char *tips[] = {
+
+ _("There is no need to install Chrysalide on your system if you only want to give it a try.\n\n"
+ "Just compile the source code and run the program from there."),
+
+ _("Chrysalide can be used in external Python scripts by setting PYTHONPATH to the directory "
+ "containing the 'pychrysalide.so' file. For instance:\n\n"
+ " cd plugins/pychrysa/.libs/\n"
+ " export PYTHONPATH=$PWD\n\n"
+ "Then run the interpreter suitable to your configuration (debug or release):\n\n"
+ " python3-dbg -c 'import pychrysalide ; print(pychrysalide.mod_version())'"),
+
+ _("All the configuration files for chrysalide are located in $HOME/.config/chrysalide/.")
+
+ };
+
+ panel->count = ARRAY_SIZE(tips);
+
+ panel->tips = (char **)calloc(panel->count, sizeof(char *));
+
+ for (i = 0; i < panel->count; i++)
+ panel->tips[i] = tips[i];
+
+ shuffle(panel->tips, panel->count, sizeof(char *));
+
+ panel->current = 0;
+
+ g_welcome_panel_refresh_tip(panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : widget = composant graphique à redessiner. *
+* cr = contexte graphique à utiliser. *
+* panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Assure le dessin du fond de la bulle d'astuce. *
+* *
+* Retour : FALSE pour poursuivre la propagation de l'événement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean on_tip_background_draw(GtkWidget *widget, cairo_t *cr, GWelcomePanel *panel)
+{
+ int wgt_width; /* Largeur disponible totale */
+ int wgt_height; /* Hauteur disponible totale */
+ int img_width; /* Largeur de l'image de fond */
+ int img_height; /* Hauteur de l'image de fond */
+ double scale; /* Echelle à appliquer */
+
+ if (cairo_surface_status(panel->background) == CAIRO_STATUS_SUCCESS)
+ {
+ wgt_width = gtk_widget_get_allocated_width(widget);
+ wgt_height = gtk_widget_get_allocated_height(widget);
+
+ img_width = cairo_image_surface_get_width(panel->background);
+ img_height = cairo_image_surface_get_height(panel->background);
+
+ scale = wgt_height / (2.0 * img_height);
+
+ cairo_scale(cr, scale, scale);
+
+ cairo_set_source_surface(cr, panel->background,
+ (wgt_width / scale) - img_width,
+ ((wgt_height / scale) - img_height) / 2);
+
+ cairo_paint(cr);
+
+ }
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton impliqué dans la procédure. *
+* panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Réagit à la demande d'étude d'un nouveau binaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_new_binary_clicked(GtkButton *button, GWelcomePanel *panel)
+{
+ GObject *ref; /* Espace de référencements */
+ GtkMenuItem *item; /* Elément de menu simulé */
+
+ ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(panel));
+
+ item = GTK_MENU_ITEM(g_object_get_data(ref, "mnu_project_add_binary"));
+
+ gtk_menu_item_activate(item);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = gestion de fichiers récemment utilisés. *
+* panel = panneau associé comportant des informations utiles.*
+* *
+* Description : Actualise au besoin la liste des projets récents. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_recent_list_changed(GtkRecentManager *manager, GWelcomePanel *panel)
+{
+ g_welcome_panel_reload_project_list(panel, manager);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau comportant des informations utiles. *
+* manager = gestion de fichiers récemment utilisés. *
+* *
+* Description : Recharge une liste à jour des projets récents. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_reload_project_list(GWelcomePanel *panel, GtkRecentManager *manager)
+{
+ GtkListStore *store; /* Modèle de gestion */
+ bool empty; /* Liste vide ? */
+ GList *recents; /* Liste des fichiers récents */
+ GList *recent; /* Elément à traiter */
+ GtkRecentInfo *info; /* Informations sur l'élément */
+ GtkTreeIter iter; /* Point d'insertion */
+
+ /* Réinitialisation */
+
+ store = GTK_LIST_STORE(gtk_builder_get_object(panel->builder, "store"));
+
+ gtk_list_store_clear(store);
+
+ empty = true;
+
+ /* Chargement */
+
+ recents = gtk_recent_manager_get_items(manager);
+
+ if (recents != NULL)
+ {
+ for (recent = g_list_first(recents); recent != NULL; recent = g_list_next(recent))
+ {
+ info = recent->data;
+
+ if (strcmp(gtk_recent_info_get_mime_type(info), "application/chrysalide.project") == 0)
+ {
+ gtk_list_store_append(store, &iter);
+
+ gtk_list_store_set(store, &iter,
+ RPC_VALID, true,
+ RPC_FULLPATH, gtk_recent_info_get_uri_display(info),
+ -1);
+
+ empty = false;
+
+ }
+
+ gtk_recent_info_unref(info);
+
+ }
+
+ g_list_free(recents);
+
+ }
+
+ /* Indication par défaut */
+ if (empty)
+ {
+ gtk_list_store_append(store, &iter);
+
+ gtk_list_store_set(store, &iter,
+ RPC_VALID, false,
+ RPC_FULLPATH, _("<i>(No recent project)</i>"),
+ -1);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : treeview = liste graphique concernée par la procédure. *
+* path = chemin d'accès à la ligne sélectionnée. *
+* column = colonne concernée par la sélection. *
+* panel = panneau associé avec des informations utiles. *
+* *
+* Description : Réagit à une sélection décidée d'un projet particulier. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_row_activated_for_projects(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, GWelcomePanel *panel)
+{
+ GtkTreeModel *model; /* Modèle de gestion */
+ GtkTreeIter iter; /* Point de la consultation */
+ gboolean valid; /* Validité de l'entrée */
+ gchar *filename; /* Chemin d'accès au projet */
+ GObject *ref; /* Espace de référencements */
+ GStudyProject *project; /* Nouveau projet à ouvrir */
+
+ model = gtk_tree_view_get_model(treeview);
+
+ if (gtk_tree_model_get_iter(model, &iter, path))
+ {
+ gtk_tree_model_get(model, &iter, RPC_VALID, &valid, RPC_FULLPATH, &filename, -1);
+
+ if (valid)
+ {
+ ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(panel));
+
+ project = g_study_project_open(ref, filename);
+
+ if (project != NULL)
+ {
+ set_current_project(project);
+
+ push_project_into_recent_list(project);
+
+ }
+
+ g_free(filename);
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton de défilement des astuces activé; *
+* panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Enregistre les conditions d'affichage du panneau d'accueil. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_startup_toggled(GtkToggleButton *button, GWelcomePanel *panel)
+{
+ g_generic_config_set_value(get_main_configuration(),
+ MPK_WELCOME_STARTUP, gtk_toggle_button_get_active(button));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau d'accueil à mettre à jour. *
+* *
+* Description : Consulte les versions existantes et affiche une conclusion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_check_version(GWelcomePanel *panel)
+{
+ bool skip; /* Saut de la vérification */
+ bool unknown; /* Impossibilité de comparaison*/
+ int current; /* Version courante */
+ int sock; /* Canal de communication */
+ bool status; /* Bilan d'une communication */
+ char buffer[1024]; /* Tampon de réception */
+ size_t got; /* Quantité de données reçues */
+ char *version; /* Version récupérée */
+ int available; /* Version disponible */
+ GtkLabel *label; /* Etiquette à éditer */
+ char *msg; /* Message à faire paraître */
+
+ g_generic_config_get_value(get_main_configuration(), MPK_WELCOME_CHECK, &skip);
+ skip = !skip;
+
+ unknown = true;
+
+ current = atoi(VERSION);
+
+ if (skip) goto check_process;
+
+ /* Recherche en ligne */
+
+ sock = connect_via_tcp("www.chrysalide.re", "80", NULL);
+ if (sock == -1) goto check_process;
+
+#define REQUEST "GET /version.last HTTP/1.1\r\nHost: www.chrysalide.re\r\n\r\n"
+
+ status = safe_send(sock, REQUEST, strlen(REQUEST), 0);
+ if (!status) goto check_done;
+
+ status = recv_all(sock, buffer, sizeof(buffer), &got);
+ if (!status) goto check_done;
+
+ version = strstr(buffer, "\r\n\r\n");
+
+ if (version != NULL)
+ {
+ available = atoi(version + 4);
+
+ unknown = false;
+
+ }
+
+ check_done:
+
+ close(sock);
+
+ check_process:
+
+ /* Affichage */
+
+ label = GTK_LABEL(gtk_builder_get_object(panel->builder, "version"));
+
+ if (skip)
+ asprintf(&msg,
+ "Your version is: <b>%d</b>\n\n" \
+ "Automatic version check is disabled.",
+ current);
+
+ else
+ {
+ if (unknown)
+ asprintf(&msg,
+ "Your version is: <b>%d</b>\n\n" \
+ "Lastest available version is unknown.",
+ current);
+
+ else
+ {
+ if (current >= available)
+ asprintf(&msg,
+ "Your version is: <b>%d</b>\n\n" \
+ "Lastest version is: <b>%d</b>\n\n" \
+ "Your software is <span color='green'><b>up-to-date</b></span>.",
+ current, available);
+
+ else
+ asprintf(&msg,
+ "Your version is: <b>%d</b>\n\n" \
+ "Lastest version is: <b>%d</b>\n\n" \
+ "Your software is <span color='red'><b>outdated</b></span>.",
+ current, available);
+
+ }
+
+ }
+
+ gtk_label_set_markup(label, msg);
+
+ free(msg);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton de défilement des astuces activé; *
+* panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Affiche l'astuce précédente dans la liste globale. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_tip_previous_clicked(GtkButton *button, GWelcomePanel *panel)
+{
+ if (panel->current > 0)
+ panel->current--;
+ else
+ panel->current = panel->count - 1;
+
+ g_welcome_panel_refresh_tip(panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton de défilement des astuces activé; *
+* panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Affiche l'astuce suivante dans la liste globale. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_tip_next_clicked(GtkButton *button, GWelcomePanel *panel)
+{
+ if ((panel->current + 1) < panel->count)
+ panel->current++;
+ else
+ panel->current = 0;
+
+ g_welcome_panel_refresh_tip(panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Actualise l'affichage des astuces. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_welcome_panel_refresh_tip(GWelcomePanel *panel)
+{
+ GtkLabel *label; /* Etiquette de présentation */
+
+ assert(panel->current < panel->count);
+
+ label = GTK_LABEL(gtk_builder_get_object(panel->builder, "tip"));
+
+ gtk_label_set_markup(label, panel->tips[panel->current]);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau associé comportant des informations utiles. *
+* *
+* Description : Indique l'origine de l'affichage du panneau d'accueil. *
+* *
+* Retour : true si l'affichage est le fait de l'utilisateur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_welcome_panel_get_user_origin(const GWelcomePanel *panel)
+{
+ return panel->uorigin;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau associé comportant des informations utiles.*
+* uorigin = true si l'affichage est le fait de l'utilisateur. *
+* *
+* Description : Détermine l'origine de l'affichage du panneau d'accueil. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_welcome_panel_set_user_origin(GWelcomePanel *panel, bool uorigin)
+{
+ panel->uorigin = uorigin;
+
+}