--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkListStore" id="lstore_treemodel_fields">
+ <columns>
+ <!-- column-name selezionato -->
+ <column type="gboolean"/>
+ <!-- column-name id -->
+ <column type="guint"/>
+ <!-- column-name nome -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="diag_gtktreemodel_to_csv">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Esporta CSV</property>
+ <property name="type_hint">normal</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <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">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label">gtk-save</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">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkPaned" id="paned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">5</property>
+ <property name="bottom_padding">5</property>
+ <property name="left_padding">5</property>
+ <property name="right_padding">5</property>
+ <child>
+ <object class="GtkBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">etched-in</property>
+ <child>
+ <object class="GtkTreeView" id="treeview1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="model">lstore_treemodel_fields</property>
+ <property name="headers_clickable">False</property>
+ <property name="search_column">0</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererToggle" id="cellrenderertoggle1"/>
+ <attributes>
+ <attribute name="active">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <property name="title">Campo</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">5</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button3">
+ <property name="label" translatable="yes">Unselect all</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button4">
+ <property name="label" translatable="yes">Select all</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</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="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes"><b>Select fields</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkGrid" id="table1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Quote</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="text" translatable="yes">"</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Quote all</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Separator</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="text" translatable="yes">,</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Fileds name as first row</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="checkbutton3">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes"><b>Export options</b></property>
+ <property name="use_markup">True</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="resize">False</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="label_xalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">5</property>
+ <property name="bottom_padding">5</property>
+ <property name="left_padding">5</property>
+ <property name="right_padding">5</property>
+ <child>
+ <object class="GtkFileChooserWidget" id="filechooserwidget1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="action">save</property>
+ <property name="local_only">False</property>
+ <property name="preview_widget_active">False</property>
+ <property name="use_preview_label">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes"><b>Select file</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">button1</action-widget>
+ <action-widget response="-5">button2</action-widget>
+ </action-widgets>
+ </object>
+</interface>
#include <config.h>
#endif
+#include <locale.h>
+#include <math.h>
+
+#include <libzakutils/libzakutils.h>
+
+#include "commons.h"
#include "treemodel.h"
+
+void
+zak_utils_gtk_liststore_select_unselect_all (GtkListStore *store, guint column, gboolean select)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
+ {
+ do
+ {
+ gtk_list_store_set (store, &iter, column, select, -1);
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
+ }
+}
+
+static gboolean
+zak_utils_gtk_treeiter_export_to_csv (GtkTreeModel *model,
+ GtkTreeIter iter,
+ GOutputStream *ostream,
+ gchar *quote,
+ gboolean quote_all,
+ gchar *separator,
+ GType *gtypes,
+ guint *columns,
+ guint n_columns)
+{
+ gboolean ret;
+
+ GError *error;
+
+ gchar *row;
+ const gchar *str;
+
+ guint i;
+
+ GValue *gval;
+ GValue *gvalstr;
+
+ ret = TRUE;
+
+ do
+ {
+ row = g_strdup ("");
+ for (i = 0; i < n_columns; i++)
+ {
+ gval = g_new0 (GValue, 1);
+ gvalstr = g_value_init (g_new0 (GValue, 1), G_TYPE_STRING);
+
+ gtk_tree_model_get_value (model, &iter, columns[i], gval);
+ g_value_transform (gval, gvalstr);
+
+ str = g_value_get_string (gvalstr);
+ row = g_strconcat (row,
+ (i > 0 ? separator : ""),
+ (quote_all || gtypes[i] == G_TYPE_STRING ? quote : ""),
+ (str == NULL ? "" : str),
+ (quote_all || gtypes[i] == G_TYPE_STRING ? quote : ""),
+ NULL);
+
+ g_value_unset (gval);
+ g_value_unset (gvalstr);
+ }
+ row = g_strconcat (row, "\n", NULL);
+
+ error = NULL;
+ if (!g_output_stream_write_all (ostream,
+ row, strlen (row), NULL, NULL, &error))
+ {
+ g_warning ("Errore nella scrittura del file di output: %s",
+ error != NULL && error->message != NULL ? error->message : "nessun dettaglio");
+ return FALSE;
+ }
+
+ g_free (row);
+
+ if (gtk_tree_model_iter_has_child (model, &iter))
+ {
+ GtkTreeIter child;
+
+ gtk_tree_model_iter_children (model, &child, &iter);
+
+ if (!zak_utils_gtk_treeiter_export_to_csv (model, child,
+ ostream,
+ quote, quote_all,
+ separator,
+ gtypes,
+ columns, n_columns))
+ {
+ return FALSE;
+ }
+ }
+ }
+ while (gtk_tree_model_iter_next (model, &iter));
+
+ return ret;
+}
+
+gboolean
+zak_utils_gtk_treemodel_to_csv (GtkTreeModel *model,
+ const gchar *filename,
+ gboolean overwrite,
+ const gchar *quote,
+ gboolean quote_all,
+ const gchar *separator,
+ gboolean fields_name_first_row,
+ gchar **columns_title,
+ guint *columns,
+ guint n_columns)
+{
+ gchar *_filename;
+ gchar *_quote;
+ gchar *_separator;
+
+ GFile *fout;
+ GFileOutputStream *ostream;
+ GError *error;
+
+ gchar *row;
+
+ guint i;
+
+ GtkTreeIter iter;
+ GType *gtypes;
+
+ gboolean ret;
+
+ g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (columns_title != NULL, FALSE);
+ g_return_val_if_fail (columns != NULL, FALSE);
+ g_return_val_if_fail (n_columns > 0, FALSE);
+
+ _filename = g_strdup (filename);
+ g_return_val_if_fail (g_strcmp0 (g_strstrip (_filename), "") != 0, FALSE);
+
+ ret = TRUE;
+
+ if (quote != NULL)
+ {
+ _quote = g_strdup (quote);
+ }
+ else
+ {
+ _quote = g_strdup ("\"");
+ }
+ if (separator != NULL)
+ {
+ _separator = g_strdup (separator);
+ }
+ else
+ {
+ _separator = g_strdup (",");
+ }
+
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ /* creo/sostituisco il file */
+ fout = g_file_new_for_path (filename);
+
+ error = NULL;
+ if (overwrite)
+ {
+ ostream = g_file_replace (fout, NULL, FALSE,
+ G_FILE_CREATE_NONE,
+ NULL, &error);
+ }
+ else
+ {
+ ostream = g_file_create (fout,
+ G_FILE_CREATE_NONE,
+ NULL, &error);
+ }
+ if (ostream == NULL)
+ {
+ g_free (_filename);
+ g_free (_quote);
+ g_free (_separator);
+ g_warning ("Errore nella creazione del file di output: %s",
+ error != NULL && error->message != NULL ? error->message : "nessun dettaglio");
+ return FALSE;
+ }
+
+ if (fields_name_first_row)
+ {
+ /* nomi dei campi come prima riga */
+ row = g_strdup ("");
+ for (i = 0; i < n_columns; i++)
+ {
+ row = g_strconcat (row,
+ (i > 0 ? _separator : ""),
+ _quote, columns_title[columns[i]], _quote,
+ NULL);
+ }
+ row = g_strconcat (row, "\n", NULL);
+
+ error = NULL;
+ if (!g_output_stream_write_all (G_OUTPUT_STREAM (ostream),
+ row, strlen (row), NULL, NULL, &error))
+ {
+ g_free (_filename);
+ g_free (_quote);
+ g_free (_separator);
+ g_warning ("Errore nella scrittura del file di output: %s",
+ error != NULL && error->message != NULL ? error->message : "nessun dettaglio");
+ return FALSE;
+ }
+
+ g_free (row);
+ }
+
+ /* cache dei GType delle colonne */
+ gtypes = g_malloc0 (n_columns * sizeof (GType));
+ for (i = 0; i < n_columns; i++)
+ {
+ gtypes[i] = gtk_tree_model_get_column_type (model, columns[i]);
+ }
+
+ zak_utils_gtk_treeiter_export_to_csv (model, iter,
+ G_OUTPUT_STREAM (ostream),
+ _quote, quote_all,
+ _separator,
+ gtypes,
+ columns, n_columns);
+
+ error = NULL;
+ if (!g_output_stream_close (G_OUTPUT_STREAM (ostream), NULL, &error))
+ {
+ g_warning ("Errore nella chiusura del file di output: %s",
+ error != NULL && error->message != NULL ? error->message : "nessun dettaglio");
+ ret = FALSE;
+ }
+ g_object_unref (ostream);
+ }
+ else
+ {
+ g_warning ("Nessun record da esportare.");
+ }
+
+ g_free (_filename);
+ g_free (_quote);
+ g_free (_separator);
+
+ return ret;
+}
+
+static void
+zak_utils_gtk_treemodel_fixed_toggled (GtkCellRendererToggle *cell,
+ gchar *path_str,
+ gpointer data)
+{
+ GtkTreeModel *model = (GtkTreeModel *)data;
+ GtkTreeIter iter;
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+
+ gboolean choosen;
+
+ /* get toggled iter */
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_model_get (model, &iter, 0, &choosen, -1);
+
+ choosen ^= 1;
+
+ /* set new value */
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, choosen, -1);
+
+ /* clean up */
+ gtk_tree_path_free (path);
+}
+
+static void
+zak_utils_gtk_treemodel_on_btn_select_all_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ zak_utils_gtk_liststore_select_unselect_all ((GtkListStore *)user_data, 0, TRUE);
+}
+
+static void
+zak_utils_gtk_treemodel_on_btn_unselect_all_clicked (GtkButton *button,
+ gpointer user_data)
+{
+ zak_utils_gtk_liststore_select_unselect_all ((GtkListStore *)user_data, 0, FALSE);
+}
+
+guint
+zak_utils_gtk_treemodel_to_csv_gui (GtkWindow *parent,
+ GtkTreeModel *model,
+ gchar **columns_title,
+ guint n_columns)
+{
+ GtkWidget *diag;
+ GError *error;
+ GtkBuilder *builder;
+
+ GtkListStore *store;
+ GtkTreeIter iter;
+
+ gchar *filename;
+
+ guint col;
+ gboolean sel;
+
+ guint *columns;
+ guint _n_columns;
+
+ guint ret;
+
+ builder = zak_utils_gtk_get_gtkbuilder ();
+
+ if (!GTK_IS_BUILDER (builder))
+ {
+ g_warning ("GtkBuilder non inizializzato.");
+ return 0;
+ }
+
+ ret = 1;
+
+ error = NULL;
+ gtk_builder_add_objects_from_file (builder,
+ zak_utils_gtk_get_guifile (),
+ g_strsplit ("diag_gtktreemodel_to_csv"
+ "|lstore_treemodel_campi",
+ "|", -1),
+ &error);
+ if (error != NULL)
+ {
+ g_warning ("Errore nell'inzializzazione della gui: %s.",
+ error->message != NULL ? error->message : "no details");
+ return 0;
+ }
+
+ diag = GTK_WIDGET (gtk_builder_get_object (builder, "diag_gtktreemodel_to_csv"));
+ if (GTK_IS_WIDGET (diag))
+ {
+ /* imposto la directory di default alla directory documenti */
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gtk_builder_get_object (builder, "filechooserwidget1")),
+ g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
+
+ /* carico i nomi campi per la selezione nel model */
+ store = GTK_LIST_STORE (gtk_builder_get_object (builder, "lstore_treemodel_campi"));
+ if (!GTK_IS_LIST_STORE (store))
+ {
+ g_warning ("Errore nell'ottenimento del list store.");
+ return 0;
+ }
+
+ g_signal_connect (gtk_builder_get_object (builder, "cellrenderertoggle1"),
+ "toggled", G_CALLBACK (zak_utils_gtk_treemodel_fixed_toggled), (gpointer)store);
+
+ g_signal_connect (gtk_builder_get_object (builder, "button3"),
+ "clicked", G_CALLBACK (zak_utils_gtk_treemodel_on_btn_unselect_all_clicked), (gpointer)store);
+ g_signal_connect (gtk_builder_get_object (builder, "button4"),
+ "clicked", G_CALLBACK (zak_utils_gtk_treemodel_on_btn_select_all_clicked), (gpointer)store);
+
+ gtk_list_store_clear (store);
+
+ for (col = 0; col < n_columns; col++)
+ {
+ if (g_strcmp0 (columns_title[col], "{SKIP}") != 0)
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, FALSE,
+ 1, col,
+ 2, columns_title[col],
+ -1);
+ }
+ }
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (gtk_builder_get_object (builder, "treeview1")),
+ GTK_TREE_MODEL (store));
+
+ gtk_window_set_transient_for (GTK_WINDOW (diag), parent);
+ do
+ {
+ if (gtk_dialog_run (GTK_DIALOG (diag)) == GTK_RESPONSE_OK)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gtk_builder_get_object (builder, "filechooserwidget1")));
+ if (filename == NULL
+ || g_strcmp0 (g_strstrip (filename), "") == 0)
+ {
+ GtkWidget *diag_req;
+
+ diag_req = gtk_message_dialog_new (GTK_WINDOW (diag),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "Immettere il nome del file nel quale esportare i dati.");
+ gtk_dialog_run (GTK_DIALOG (diag_req));
+ gtk_widget_destroy (diag_req);
+ continue;
+ }
+
+ if (zak_utils_file_exists (filename))
+ {
+ GtkWidget *diag_req;
+
+ diag_req = gtk_message_dialog_new (GTK_WINDOW (diag),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ "File esistente. Sovrascriverlo?");
+ if (gtk_dialog_run (GTK_DIALOG (diag_req)) == GTK_RESPONSE_YES)
+ {
+ gtk_widget_destroy (diag_req);
+ break;
+ }
+ gtk_widget_destroy (diag_req);
+ }
+ break;
+ }
+ else
+ {
+ gtk_widget_destroy (diag);
+ return -1;
+ }
+ } while (TRUE);
+
+ /* ricavo i campi selezionati che devono essere esportati */
+ _n_columns = 0;
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
+ {
+ columns = g_malloc0 (sizeof (guint));
+ do
+ {
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
+ 0, &sel,
+ 1, &col,
+ -1);
+ if (sel)
+ {
+ _n_columns++;
+
+ columns = g_realloc_n (columns, _n_columns, sizeof (guint));
+ columns[_n_columns - 1] = col;
+ }
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
+ }
+
+ /* export */
+ if (!zak_utils_gtk_treemodel_to_csv (model,
+ filename,
+ TRUE,
+ gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder, "entry1"))),
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "checkbutton1"))),
+ gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (builder, "entry2"))),
+ gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gtk_builder_get_object (builder, "checkbutton3"))),
+ columns_title,
+ columns,
+ _n_columns))
+ {
+ ret = 0;
+ }
+
+ g_free (columns);
+
+ gtk_widget_destroy (diag);
+ }
+
+ return ret;
+}
+
+GType
+*zak_utils_gtk_treemodel_get_gtypes (GtkTreeModel *model, guint *cols)
+{
+ GType *ret;
+
+ guint _cols;
+ guint _col;
+
+ ret = NULL;
+
+ _cols = gtk_tree_model_get_n_columns (model);
+ if (_cols > 0)
+ {
+ if (cols != NULL)
+ {
+ *cols = _cols;
+ }
+
+ ret = (GType *)g_malloc0 (_cols * sizeof (GType));
+ for (_col = 0; _col < _cols; _col++)
+ {
+ ret[_col] = gtk_tree_model_get_column_type (model, _col);
+ }
+ }
+
+ return ret;
+}
+
+static GtkTreeIter
+*zak_utils_gtk_treemodel_get_iter_child (GtkTreeIter *iter, GPtrArray *models)
+{
+ GtkTreeModel *model;
+ GtkTreeIter *iter_parent;
+ GtkTreeIter *iter_child;
+
+ guint n;
+
+ iter_parent = iter;
+ iter_child = (GtkTreeIter *)g_malloc0 (sizeof (GtkTreeIter));
+
+ for (n = 0; n < (models->len - 1); n++)
+ {
+ model = (GtkTreeModel *)g_ptr_array_index (models, n);
+ if (GTK_IS_TREE_MODEL_SORT (model))
+ {
+ gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model),
+ iter_child, iter_parent);
+ iter_parent = iter_child;
+ iter_child = (GtkTreeIter *)g_malloc0 (sizeof (GtkTreeIter));
+ }
+ else if (GTK_IS_TREE_MODEL_FILTER (model))
+ {
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
+ iter_child, iter_parent);
+ iter_parent = iter_child;
+ iter_child = (GtkTreeIter *)g_malloc0 (sizeof (GtkTreeIter));
+ }
+ }
+ g_free (iter_child);
+
+ return iter_parent;
+}
+
+static void
+zak_utils_gtk_treemodel_copy_iter (GtkTreeModel *ret,
+ GtkTreeModel *model,
+ GPtrArray *models,
+ gboolean is_list_store,
+ guint cols,
+ GtkTreeIter *iter,
+ GtkTreeIter *iter_parent)
+{
+ GtkTreeIter iter_new;
+ GtkTreeIter *iter_child;
+
+ guint col;
+
+ do
+ {
+ if (is_list_store)
+ {
+ gtk_list_store_append (GTK_LIST_STORE (ret), &iter_new);
+ }
+ else
+ {
+ gtk_tree_store_append (GTK_TREE_STORE (ret), &iter_new, iter_parent);
+ }
+
+ iter_child = zak_utils_gtk_treemodel_get_iter_child (iter, models);
+ for (col = 0; col < cols; col++)
+ {
+ GValue gval = {0};
+
+ gtk_tree_model_get_value ((GtkTreeModel *)g_ptr_array_index (models, models->len - 1),
+ iter_child,
+ col, &gval);
+
+ if (is_list_store)
+ {
+ gtk_list_store_set_value (GTK_LIST_STORE (ret), &iter_new, col, &gval);
+ }
+ else
+ {
+ gtk_tree_store_set_value (GTK_TREE_STORE (ret), &iter_new, col, &gval);
+ }
+
+ g_value_unset (&gval);
+ }
+
+ if (!is_list_store)
+ {
+ /* is_tree_store */
+ GtkTreeIter iter_children;
+
+ if (gtk_tree_model_iter_children (model, &iter_children, iter_child))
+ {
+ zak_utils_gtk_treemodel_copy_iter (ret, model, models, is_list_store, cols, &iter_children, &iter_new);
+ }
+ }
+ } while (gtk_tree_model_iter_next (model, iter));
+}
+
+static void
+zak_utils_gtk_treemodel_get_models_chain (GtkTreeModel *model, GPtrArray *models)
+{
+ GtkTreeModel *my_model;
+
+ if (GTK_IS_TREE_MODEL_SORT (model))
+ {
+ my_model = (gpointer)gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
+ g_ptr_array_add (models, my_model);
+
+ zak_utils_gtk_treemodel_get_models_chain (my_model, models);
+ }
+ else if (GTK_IS_TREE_MODEL_FILTER (model))
+ {
+ my_model = (gpointer)gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
+ g_ptr_array_add (models, my_model);
+
+ zak_utils_gtk_treemodel_get_models_chain (my_model, models);
+ }
+}
+
+GtkTreeModel
+*zak_uttils_gtk_treemodel_copy (GtkTreeModel *model, gboolean only_schema)
+{
+ GtkTreeModel *ret;
+
+ GType *gtypes;
+
+ guint cols;
+
+ GPtrArray *models; /* GtkTreeModel */
+
+ GtkTreeIter iter;
+
+ ret = NULL;
+
+ gtypes = zak_utils_gtk_treemodel_get_gtypes (model, &cols);
+ if (gtypes != NULL && cols > 0)
+ {
+ models = g_ptr_array_new ();
+ g_ptr_array_add (models, (gpointer)model);
+
+ if (GTK_IS_TREE_MODEL_SORT (model) ||
+ GTK_IS_TREE_MODEL_FILTER (model))
+ {
+ zak_utils_gtk_treemodel_get_models_chain (model, models);
+ }
+
+ if (GTK_IS_LIST_STORE ((GtkTreeModel *)g_ptr_array_index (models, models->len - 1)))
+ {
+ ret = GTK_TREE_MODEL (gtk_list_store_newv (cols, gtypes));
+
+ if (!only_schema)
+ {
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ zak_utils_gtk_treemodel_copy_iter (ret, model, models, TRUE, cols, &iter, NULL);
+ }
+ }
+ }
+ else if (GTK_IS_TREE_STORE ((GtkTreeModel *)g_ptr_array_index (models, models->len - 1)))
+ {
+ ret = GTK_TREE_MODEL (gtk_tree_store_newv (cols, gtypes));
+
+ if (!only_schema)
+ {
+ if (gtk_tree_model_get_iter_first (model, &iter))
+ {
+ zak_utils_gtk_treemodel_copy_iter (ret, model, models, FALSE, cols, &iter, NULL);
+ }
+ }
+ }
+ else
+ {
+ g_warning ("GtkTreeModel type not expected.");
+ }
+
+ g_ptr_array_free (models, TRUE);
+ }
+
+ return ret;
+}
+
+const gchar
+*zak_utils_gtk_treemodel_get_value_string (GtkTreeModel *model, GtkTreeIter *iter, gint column)
+{
+ const gchar *ret;
+ GValue *gval;
+
+ ret = NULL;
+
+ gval = g_new0 (GValue, 1);
+ gtk_tree_model_get_value (model, iter, column, gval);
+
+ ret = g_strdup (g_value_get_string (gval));
+ g_value_unset (gval);
+
+ return ret;
+}
+
+gint
+zak_utils_gtk_treemodel_get_value_integer (GtkTreeModel *model, GtkTreeIter *iter, gint column)
+{
+ gint ret;
+ GValue *gval;
+
+ ret = 0;
+
+ gval = g_new0 (GValue, 1);
+ gtk_tree_model_get_value (model, iter, column, gval);
+
+ if (G_VALUE_HOLDS_STRING (gval))
+ {
+ /* try conversion */
+ ret = (gint)trunc ((gfloat)zak_utils_unformat_money (g_value_get_string (gval)));
+ }
+ else if (G_VALUE_HOLDS_INT (gval))
+ {
+ ret = g_value_get_int (gval);
+ }
+ else if (G_VALUE_HOLDS_UINT (gval))
+ {
+ ret = (gint)g_value_get_uint (gval);
+ }
+ g_value_unset (gval);
+
+ return ret;
+}
+
+gdouble
+zak_utils_gtk_treemodel_get_value_double (GtkTreeModel *model, GtkTreeIter *iter, gint column)
+{
+ gdouble ret;
+ GValue *gval;
+
+ ret = 0.0;
+
+ gval = g_new0 (GValue, 1);
+ gtk_tree_model_get_value (model, iter, column, gval);
+
+ if (G_VALUE_HOLDS_STRING (gval))
+ {
+ /* try conversion */
+ ret = zak_utils_unformat_money (g_value_get_string (gval));
+ }
+ else
+ {
+ ret = g_value_get_double (gval);
+ }
+ g_value_unset (gval);
+
+ return ret;
+}
+
+const gchar
+*zak_utils_gtk_treemodel_get_value_double_sql (GtkTreeModel *model, GtkTreeIter *iter, gint column)
+{
+ char *cur;
+
+ const gchar *ret;
+ gdouble res;
+
+ res = zak_utils_gtk_treemodel_get_value_double (model, iter, column);
+
+ cur = g_strdup (setlocale (LC_NUMERIC, NULL));
+ setlocale (LC_NUMERIC, "C");
+
+ ret = g_strdup_printf ("%f", res);
+
+ setlocale (LC_NUMERIC, cur);
+ g_free (cur);
+
+ return ret;
+}
+
+gboolean
+zak_utils_gtk_treemodel_get_value_boolean (GtkTreeModel *model, GtkTreeIter *iter, gint column)
+{
+ gboolean ret;
+ GValue *gval;
+
+ ret = FALSE;
+
+ gval = g_new0 (GValue, 1);
+ gtk_tree_model_get_value (model, iter, column, gval);
+
+ if (G_VALUE_HOLDS_BOOLEAN (gval))
+ {
+ ret = g_value_get_boolean (gval);
+ }
+ else if (G_VALUE_HOLDS_INT (gval))
+ {
+ ret = (g_value_get_int (gval) == 0 ? FALSE : TRUE);
+ }
+ else if (G_VALUE_HOLDS_UINT (gval))
+ {
+ ret = ((gint)g_value_get_uint (gval) == 0 ? FALSE : TRUE);
+ }
+ else if (G_VALUE_HOLDS_STRING (gval))
+ {
+ ret = zak_utils_string_to_boolean (g_value_get_string (gval));
+ }
+ g_value_unset (gval);
+
+ return ret;
+}
+
+struct tm
+*zak_utils_gtk_treemodel_get_value_tm (GtkTreeModel *model, GtkTreeIter *iter, gint column, const gchar *format)
+{
+ struct tm *ret;
+ GDateTime *dt;
+
+ dt = zak_utils_gtk_treemodel_get_value_gdatetime (model, iter, column, format);
+
+ ret = zak_utils_gdatetime_to_tm (dt);
+
+ return ret;
+}
+
+GDateTime
+*zak_utils_gtk_treemodel_get_value_gdatetime (GtkTreeModel *model, GtkTreeIter *iter, gint column, const gchar *format)
+{
+ GDateTime *ret;
+ const gchar *value;
+
+ value = zak_utils_gtk_treemodel_get_value_string (model, iter, column);
+
+ ret = zak_utils_get_gdatetime_from_string (value, format);
+
+ return ret;
+}