summaryrefslogtreecommitdiff
path: root/src/gui/dialogs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/dialogs')
-rw-r--r--src/gui/dialogs/Makefile.am4
-rw-r--r--src/gui/dialogs/export_disass.c (renamed from src/gui/dialogs/export.c)4
-rw-r--r--src/gui/dialogs/export_disass.h (renamed from src/gui/dialogs/export.h)8
-rw-r--r--src/gui/dialogs/export_graph.c459
-rw-r--r--src/gui/dialogs/export_graph.h41
-rw-r--r--src/gui/dialogs/export_graph.ui196
-rw-r--r--src/gui/dialogs/gresource.xml1
7 files changed, 706 insertions, 7 deletions
diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am
index 869fa7a..ae5180b 100644
--- a/src/gui/dialogs/Makefile.am
+++ b/src/gui/dialogs/Makefile.am
@@ -5,6 +5,7 @@ noinst_LTLIBRARIES = libguidialogs.la
UI_FILES = \
bookmark.ui \
+ export_graph.ui \
identity.ui \
preferences.ui \
prefs_fgraph.ui \
@@ -14,7 +15,8 @@ UI_FILES = \
libguidialogs_la_SOURCES = \
about.h about.c \
bookmark.h bookmark.c \
- export.h export.c \
+ export_disass.h export_disass.c \
+ export_graph.h export_graph.c \
goto.h goto.c \
gotox.h gotox.c \
identity.h identity.c \
diff --git a/src/gui/dialogs/export.c b/src/gui/dialogs/export_disass.c
index 5a66d02..be7d2a9 100644
--- a/src/gui/dialogs/export.c
+++ b/src/gui/dialogs/export_disass.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * export.c - assistant d'exportation de contenu binaire
+ * export_disass.c - assistant d'exportation de contenu binaire
*
* Copyright (C) 2015-2017 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "export.h"
+#include "export_disass.h"
#include <assert.h>
diff --git a/src/gui/dialogs/export.h b/src/gui/dialogs/export_disass.h
index 209dea8..86fe4a7 100644
--- a/src/gui/dialogs/export.h
+++ b/src/gui/dialogs/export_disass.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * export.h - prototypes pour l'assistant d'exportation de contenu binaire
+ * export_disass.h - prototypes pour l'assistant d'exportation de contenu binaire
*
* Copyright (C) 2015-2017 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _GUI_DIALOGS_EXPORT_H
-#define _GUI_DIALOGS_EXPORT_H
+#ifndef _GUI_DIALOGS_EXPORT_DISASS_H
+#define _GUI_DIALOGS_EXPORT_DISASS_H
#include <gtk/gtk.h>
@@ -37,4 +37,4 @@ void run_export_assistant(GLoadedBinary *, GtkWindow *);
-#endif /* _GUI_DIALOGS_EXPORT_H */
+#endif /* _GUI_DIALOGS_EXPORT_DISASS_H */
diff --git a/src/gui/dialogs/export_graph.c b/src/gui/dialogs/export_graph.c
new file mode 100644
index 0000000..55556b6
--- /dev/null
+++ b/src/gui/dialogs/export_graph.c
@@ -0,0 +1,459 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * export_graph.c - assistant d'exportation de vues graphiques
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "export_graph.h"
+
+
+#include <assert.h>
+#include <cairo-pdf.h>
+#include <cairo-svg.h>
+#include <cairo-ps.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+
+#include "../../common/extstr.h"
+#include "../../core/logs.h"
+#include "../../glibext/gbinarycursor.h"
+#include "../../glibext/gloadedpanel.h"
+#include "../../gtkext/gtkdisplaypanel.h"
+
+
+
+/* Ferme l'assistant sans dérouler la procédure. */
+static void graph_export_assistant_cancel(GtkAssistant *, GtkBuilder *);
+
+/* Réalise l'exportation du contenu sous la forme choisie. */
+static void graph_export_assistant_close(GtkAssistant *, GtkBuilder *);
+
+/* Actualise l'extension du fichier de sortie. */
+static void on_output_format_toggled(GtkToggleButton *, GtkBuilder *);
+
+/* Prend note d'un changement dans la saisie du fichier final. */
+static void on_output_filename_changed(GtkEditable *, GtkBuilder *);
+
+/* Réagit à la demande de sélection d'un nouveau fichier final. */
+static void on_output_filename_selection(GtkButton *, GtkBuilder *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = contenu bnaire chargé en mémoire. *
+* display = vue graphique à traiter. *
+* parent = fenêtre principale de l'éditeur. *
+* *
+* Description : Crée et affiche un assistant d'aide à l'exportation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void run_graph_export_assistant(GLoadedBinary *binary, GtkGraphDisplay *display, GtkWindow *parent)
+{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkWidget *assistant; /* Fenêtre à afficher */
+#if !defined CAIRO_HAS_PDF_SURFACE || !defined CAIRO_HAS_PS_SURFACE || !defined CAIRO_HAS_SVG_SURFACE
+ GtkWIdget *button; /* Bouton de sélection */
+#endif
+ GLineCursor *cursor; /* Position dans la vue */
+ vmpa2t target; /* Localisation ciblée */
+ GBinFormat *format; /* Format de fichier reconnu */
+ bool status; /* Bilan d'un appel */
+ GBinSymbol *symbol; /* Symbole affiché */
+ char *label; /* Etiquette humaine associée */
+ GtkEntry *entry; /* Zone de texte */
+
+ builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/export_graph.ui");
+
+ assistant = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+
+ gtk_window_set_transient_for(GTK_WINDOW(assistant), parent);
+
+ /* Validation des formats de sortie */
+
+#ifndef CAIRO_HAS_PDF_SURFACE
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_pdf"));
+ gtk_widget_set_sensitive(button, FALSE);
+#endif
+
+#ifndef CAIRO_HAS_PS_SURFACE
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_ps"));
+ gtk_widget_set_sensitive(button, FALSE);
+#endif
+
+#ifndef CAIRO_HAS_SVG_SURFACE
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_svg"));
+ gtk_widget_set_sensitive(button, FALSE);
+#endif
+
+ /* Choix du fichier d'exportation par défaut */
+
+ cursor = g_loaded_panel_get_cursor(G_LOADED_PANEL(display));
+
+ if (cursor != NULL)
+ {
+ g_binary_cursor_get_info(G_BINARY_CURSOR(cursor), &target);
+
+ g_object_unref(G_OBJECT(cursor));
+
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
+
+ status = g_binary_format_find_symbol_for(format, &target, &symbol);
+
+ g_object_unref(G_OBJECT(format));
+
+ if (status)
+ {
+ label = g_binary_symbol_get_label(symbol);
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "output"));
+
+ gtk_entry_set_text(entry, label);
+
+ free(label);
+
+ g_object_unref(G_OBJECT(symbol));
+
+ }
+
+ }
+
+ on_output_format_toggled(NULL, builder);
+
+ /* Mémorisation pour les traitement */
+
+ g_object_ref(G_OBJECT(display));
+ g_object_set_data_full(G_OBJECT(assistant), "display", display, g_object_unref);
+
+ /* Connexion des signaux */
+
+ gtk_builder_add_callback_symbols(builder,
+ "graph_export_assistant_cancel", G_CALLBACK(graph_export_assistant_cancel),
+ "graph_export_assistant_close", G_CALLBACK(graph_export_assistant_close),
+ "on_output_format_toggled", G_CALLBACK(on_output_format_toggled),
+ "on_output_filename_changed", G_CALLBACK(on_output_filename_changed),
+ "on_output_filename_selection", G_CALLBACK(on_output_filename_selection),
+ NULL);
+
+ gtk_builder_connect_signals(builder, builder);
+
+ gtk_widget_show_all(assistant);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : assistant = fenêtre à compléter et référencement global. *
+* builder = espace de référencement global. *
+* *
+* Description : Ferme l'assistant sans dérouler la procédure. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void graph_export_assistant_cancel(GtkAssistant *assistant, GtkBuilder *builder)
+{
+ g_object_set_data(G_OBJECT(assistant), "binary", NULL);
+ g_object_set_data(G_OBJECT(assistant), "display", NULL);
+
+ g_object_ref(G_OBJECT(assistant));
+ gtk_widget_destroy(GTK_WIDGET(assistant));
+
+ g_object_unref(G_OBJECT(builder));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Réalise l'exportation du contenu sous la forme choisie. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void graph_export_assistant_close(GtkAssistant *assistant, GtkBuilder *builder)
+{
+ GtkEntry *entry; /* Zone de texte */
+ const gchar *cur_filename; /* Fichier de sortie courant */
+ GtkGraphDisplay *display; /* Vue grahique associée */
+ GtkRequisition size; /* Taille idéale associée */
+ bool as_png; /* Exportation en PNG ? */
+ GtkToggleButton *button; /* Bouton de sélection */
+ gboolean state; /* Etat de la sélection */
+ cairo_surface_t *surface; /* Zone de dessin nouvelle */
+ cairo_t *cr; /* Contexte de rendu */
+ GtkWidget *widget; /* Composant GTK à dessiner */
+ cairo_status_t status; /* Bilan de l'écriture */
+
+ /* Collecte des informations de base */
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "output"));
+
+ cur_filename = gtk_entry_get_text(entry);
+
+ display = GTK_GRAPH_DISPLAY(g_object_get_data(G_OBJECT(assistant), "display"));
+
+ gtk_widget_get_preferred_size(GTK_WIDGET(display), &size, NULL);
+
+ /* Préparation du fichier de sortie */
+
+ as_png = false;
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_pdf"));
+ state = gtk_toggle_button_get_active(button);
+
+ if (state)
+ {
+ surface = cairo_pdf_surface_create(cur_filename, size.width, size.height);
+ goto do_export;
+ }
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_ps"));
+ state = gtk_toggle_button_get_active(button);
+
+ if (state)
+ {
+ surface = cairo_ps_surface_create(cur_filename, size.width, size.height);
+ goto do_export;
+ }
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_svg"));
+ state = gtk_toggle_button_get_active(button);
+
+ if (state)
+ {
+ surface = cairo_svg_surface_create(cur_filename, size.width, size.height);
+ goto do_export;
+ }
+
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width, size.height);
+ as_png = true;
+
+ /* Exportation du rendu */
+
+ do_export:
+
+ cr = cairo_create(surface);
+
+ gtk_display_panel_prepare_export(GTK_DISPLAY_PANEL(display), true);
+
+ widget = gtk_graph_display_get_support(display);
+
+ gtk_widget_draw(widget, cr);
+
+ g_object_unref(G_OBJECT(widget));
+
+ gtk_display_panel_prepare_export(GTK_DISPLAY_PANEL(display), false);
+
+ if (as_png)
+ {
+ status = cairo_surface_write_to_png(surface, cur_filename);
+
+ if (status != CAIRO_STATUS_SUCCESS)
+ log_variadic_message(LMT_ERROR, "Export error: %s (%u)", cairo_status_to_string(status), status);
+
+ }
+ else
+ cairo_show_page(cr);
+
+ cairo_destroy(cr);
+
+ cairo_surface_destroy(surface);
+
+ graph_export_assistant_cancel(assistant, builder);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tbutton = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Actualise l'extension du fichier de sortie. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_output_format_toggled(GtkToggleButton *tbutton, GtkBuilder *builder)
+{
+ GtkToggleButton *button; /* Bouton de sélection */
+ gboolean state; /* Etat de la sélection */
+ const char *ext; /* Extension attendue */
+ GtkEntry *entry; /* Zone de texte */
+ const gchar *cur_filename; /* Fichier de sortie courant */
+ char *found; /* Point final trouvé */
+ char *new_filename; /* Nouveau fichier de sortie */
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_pdf"));
+ state = gtk_toggle_button_get_active(button);
+
+ if (state)
+ {
+ ext = "pdf";
+ goto do_update;
+ }
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_ps"));
+ state = gtk_toggle_button_get_active(button);
+
+ if (state)
+ {
+ ext = "ps";
+ goto do_update;
+ }
+
+ button = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "as_svg"));
+ state = gtk_toggle_button_get_active(button);
+
+ if (state)
+ {
+ ext = "svg";
+ goto do_update;
+ }
+
+ ext = "png";
+
+ do_update:
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "output"));
+
+ cur_filename = gtk_entry_get_text(entry);
+
+ found = rindex(cur_filename, '.');
+
+ if (found == NULL)
+ asprintf(&new_filename, "%s.%s", cur_filename, ext);
+
+ else
+ {
+ new_filename = strndup(cur_filename, found - cur_filename);
+
+ new_filename = stradd(new_filename, ".");
+ new_filename = stradd(new_filename, ext);
+
+ }
+
+ gtk_entry_set_text(entry, new_filename);
+
+ free(new_filename);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : editable = zone de texte à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Prend note d'un changement dans la saisie du fichier final. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_output_filename_changed(GtkEditable *editable, GtkBuilder *builder)
+{
+ const gchar *cur_filename; /* Fichier de sortie courant */
+ GtkAssistant *assistant; /* Fenêtre affichée */
+ GtkWidget *page; /* Composant associé à une page*/
+
+ cur_filename = gtk_entry_get_text(GTK_ENTRY(editable));
+
+ assistant = GTK_ASSISTANT(gtk_builder_get_object(builder, "window"));
+
+ page = gtk_assistant_get_nth_page(assistant, 1);
+
+ gtk_assistant_set_page_complete(assistant, page, strlen(cur_filename) > 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* builder = espace de référencement global. *
+* *
+* Description : Réagit à la demande de sélection d'un nouveau fichier final. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_output_filename_selection(GtkButton *button, GtkBuilder *builder)
+{
+ GtkWindow *assistant; /* Fenêtre affichée */
+ GtkEntry *entry; /* Zone de texte */
+ const gchar *cur_filename; /* Fichier de sortie courant */
+ GtkWidget *dialog; /* Boîte à afficher */
+ gchar *new_filename; /* Nouveau fichier de sortie */
+
+ assistant = GTK_WINDOW(gtk_builder_get_object(builder, "window"));
+
+ entry = GTK_ENTRY(gtk_builder_get_object(builder, "output"));
+
+ cur_filename = gtk_entry_get_text(entry);
+
+ dialog = gtk_file_chooser_dialog_new(_("Save the output as..."), assistant,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Save"), GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), cur_filename);
+
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ new_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+
+ gtk_entry_set_text(entry, new_filename);
+
+ g_free(new_filename);
+
+ }
+
+ gtk_widget_destroy(dialog);
+
+}
diff --git a/src/gui/dialogs/export_graph.h b/src/gui/dialogs/export_graph.h
new file mode 100644
index 0000000..a88db3e
--- /dev/null
+++ b/src/gui/dialogs/export_graph.h
@@ -0,0 +1,41 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * export_graph.h - prototypes pour l'assistant d'exportation de vues graphiques
+ *
+ * Copyright (C) 2019 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GUI_DIALOGS_EXPORT_GRAPH_H
+#define _GUI_DIALOGS_EXPORT_GRAPH_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../../analysis/binary.h"
+#include "../../gtkext/gtkgraphdisplay.h"
+
+
+
+/* Crée et affiche un assistant d'aide à l'exportation. */
+void run_graph_export_assistant(GLoadedBinary *, GtkGraphDisplay *, GtkWindow *);
+
+
+
+#endif /* _GUI_DIALOGS_EXPORT_GRAPH_H */
diff --git a/src/gui/dialogs/export_graph.ui b/src/gui/dialogs/export_graph.ui
new file mode 100644
index 0000000..1c34bd3
--- /dev/null
+++ b/src/gui/dialogs/export_graph.ui
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.21.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAssistant" id="window">
+ <property name="can_focus">False</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="default_width">440</property>
+ <property name="default_height">250</property>
+ <property name="type_hint">dialog</property>
+ <property name="use_header_bar">1</property>
+ <signal name="cancel" handler="graph_export_assistant_cancel" swapped="no"/>
+ <signal name="close" handler="graph_export_assistant_close" swapped="no"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="valign">center</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>
+ <object class="GtkRadioButton" id="as_png">
+ <property name="label" translatable="yes">PNG image</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="as_pdf">
+ <property name="label" translatable="yes">PDF document</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">as_png</property>
+ <signal name="toggled" handler="on_output_format_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="GtkRadioButton" id="as_ps">
+ <property name="label" translatable="yes">PostScript document</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">as_png</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="as_svg">
+ <property name="label" translatable="yes">SVG image</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">as_png</property>
+ <signal name="toggled" handler="on_output_format_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="title" translatable="yes">Export format</property>
+ <property name="complete">True</property>
+ <property name="has_padding">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</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>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="output">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Parcourir...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_output_filename_selection" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Warning: the output file will be overwritten if it exists. </property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="page_type">confirm</property>
+ <property name="title" translatable="yes">Output file</property>
+ <property name="complete">True</property>
+ <property name="has_padding">False</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml
index ff606ba..1d18e39 100644
--- a/src/gui/dialogs/gresource.xml
+++ b/src/gui/dialogs/gresource.xml
@@ -2,6 +2,7 @@
<gresources>
<gresource prefix="/org/chrysalide/gui/dialogs">
<file compressed="true">bookmark.ui</file>
+ <file compressed="true">export_graph.ui</file>
<file compressed="true">identity.ui</file>
<file compressed="true">preferences.ui</file>
<file compressed="true">prefs_fgraph.ui</file>