3
* Copyright (C) 2001-2004 Murray Cumming
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the
17
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
* Boston, MA 02111-1307, USA.
21
#include "dialog_import_csv_progress.h"
24
#include <glom/libglom/data_structure/glomconversions.h>
25
#include <glibmm/i18n.h>
30
Dialog_Import_CSV_Progress::Dialog_Import_CSV_Progress(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade)
31
: Gtk::Dialog(cobject), m_data_source(NULL), m_current_row(0)
33
refGlade->get_widget("import_csv_progress_progress_bar", m_progress_bar);
34
refGlade->get_widget("import_csv_progress_textview", m_text_view);
36
if(!m_progress_bar || !m_text_view)
37
throw std::runtime_error("Missing widgets from glade file for Dialog_Import_CSV_Progress");
40
bool Dialog_Import_CSV_Progress::init_db_details(const Glib::ustring& table_name)
42
const bool result = Base_DB_Table_Data::init_db_details(table_name);
43
m_field_primary_key = get_field_primary_key_for_table(table_name);
47
void Dialog_Import_CSV_Progress::import(Dialog_Import_CSV& data_source)
49
// Cancel any running operations
52
// Begin with first row from source
53
m_data_source = &data_source;
56
switch(data_source.get_state())
58
case Dialog_Import_CSV::PARSING:
59
// Wait for the parsing to finish. We do not start importing before the file has been
60
// parsed completely since we would not to rollback our changes in case of a
62
m_progress_bar->set_text(Glib::ustring::compose(_("Parsing CSV file %1"), data_source.get_filename()));
63
m_ready_connection = data_source.signal_state_changed().connect(sigc::mem_fun(*this, &Dialog_Import_CSV_Progress::on_state_changed));
65
case Dialog_Import_CSV::PARSED:
69
// This function should not be called with data_source being in other states
70
g_assert_not_reached();
74
set_response_sensitive(Gtk::RESPONSE_CANCEL, true);
75
set_response_sensitive(Gtk::RESPONSE_OK, false);
78
void Dialog_Import_CSV_Progress::clear()
80
// Cancel any running import
81
m_progress_connection.disconnect();
82
m_ready_connection.disconnect();
88
void Dialog_Import_CSV_Progress::add_text(const Glib::ustring& text)
90
m_text_view->get_buffer()->insert(m_text_view->get_buffer()->end(), text);
91
m_text_view->scroll_to(m_text_view->get_buffer()->get_insert());
94
void Dialog_Import_CSV_Progress::begin_import()
96
m_progress_bar->set_text(Glib::ustring::compose("%1 / %2", m_current_row, m_data_source->get_row_count()));
97
m_progress_bar->set_fraction(0.0);
99
m_progress_connection = Glib::signal_idle().connect(sigc::mem_fun(*this, &Dialog_Import_CSV_Progress::on_idle_import));
102
void Dialog_Import_CSV_Progress::on_state_changed()
104
switch(m_data_source->get_state())
106
case Dialog_Import_CSV::ENCODING_ERROR:
108
response(Gtk::RESPONSE_CANCEL);
110
case Dialog_Import_CSV::PARSED:
111
// Begin importing when fully parsed
113
//m_progress_connection = Glib::signal_idle().connect(sigc::mem_fun(*this, &Dialog_Import_CSV_Progress::on_idle_import));
116
// We only install the signal in state PARSING, and we should not change
117
// back to NONE state, so we must have changed to one of the states handled
118
// above, otherwise something went wrong.
119
g_assert_not_reached();
124
bool Dialog_Import_CSV_Progress::on_idle_import()
126
m_progress_bar->set_text(Glib::ustring::compose("%1 / %2", m_current_row, m_data_source->get_row_count()));
127
m_progress_bar->set_fraction(static_cast<double>(m_current_row) / static_cast<double>(m_data_source->get_row_count()));
129
if(m_current_row == m_data_source->get_row_count())
131
// Don't do the response immediately, so the user has a chance to read the
132
// warnings and errors, if any.
133
set_response_sensitive(Gtk::RESPONSE_CANCEL, false);
134
set_response_sensitive(Gtk::RESPONSE_OK, true);
135
add_text(_("Import complete\n"));
139
// Update the current row values map:
140
for(unsigned int i = 0; i < m_data_source->get_column_count(); ++ i)
142
const sharedptr<Field>& field = m_data_source->get_field_for_column(i);
146
Gnome::Gda::Value value = field->from_sql(m_data_source->get_data(m_current_row, i), success);
150
// Make the value empty if the value is not unique.
151
if(field->get_unique_key())
153
sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
154
layout_item->set_full_field_details(field);
155
if(!get_field_value_is_unique(m_table_name, layout_item, value))
157
value = Gnome::Gda::Value();
159
const Glib::ustring message(Glib::ustring::compose(_("Warning: Importing row %1: The value for field %2 must be unique, but is already in use. The value will not be imported.\n"), m_current_row + 1, field->get_name()));
164
m_current_row_values[field->get_name()] = value;
168
const Glib::ustring message(Glib::ustring::compose(_("Warning: Importing row %1: The value for field %2, \"%3\" could not be converted to the field's type. The value will not be imported.\n"), m_current_row + 1, field->get_name(), m_data_source->get_data(m_current_row, i)));
174
// Choose the primary key value
175
Gnome::Gda::Value primary_key_value;
176
if(m_field_primary_key->get_auto_increment())
178
primary_key_value = get_next_auto_increment_value(m_table_name, m_field_primary_key->get_name());
182
// No auto-increment primary key: Check for uniqueness
183
Gnome::Gda::Value primary_key_value = m_current_row_values[m_field_primary_key->get_name()];
184
sharedptr<LayoutItem_Field> layout_item = sharedptr<LayoutItem_Field>::create();
185
layout_item->set_full_field_details(m_field_primary_key);
187
if(!get_field_value_is_unique(m_table_name, layout_item, primary_key_value))
188
primary_key_value = Gnome::Gda::Value();
191
if(Glom::Conversions::value_is_empty(primary_key_value))
193
Glib::ustring message(Glib::ustring::compose(_("Error importing row %1: Cannot import the row since the primary key is empty.\n"), m_current_row + 1));
198
record_new(true /* use_entered_data */, primary_key_value);
201
m_current_row_values.clear();
207
void Dialog_Import_CSV_Progress::on_response(int response_id)
209
// Don't continue importing when the user already cancelled, or closed the
210
// window via delete event.
214
Gnome::Gda::Value Dialog_Import_CSV_Progress::get_entered_field_data(const sharedptr<const LayoutItem_Field>& field) const
216
type_mapValues::const_iterator iter = m_current_row_values.find(field->get_name());
217
if(iter == m_current_row_values.end()) return Gnome::Gda::Value();
221
void Dialog_Import_CSV_Progress::set_entered_field_data(const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value& value)
223
m_current_row_values[field->get_name()] = value;
226
sharedptr<Field> Dialog_Import_CSV_Progress::get_field_primary_key() const
228
return m_field_primary_key;
231
Gnome::Gda::Value Dialog_Import_CSV_Progress::get_primary_key_value_selected() const
233
type_mapValues::const_iterator iter = m_current_row_values.find(m_field_primary_key->get_name());
234
if(iter == m_current_row_values.end()) return Gnome::Gda::Value();
238
// These don't make sense in Dialog_Import_CSV_Progress, and thus should not
239
// be called. We need to implement them though, because they are pure abstract
240
// in Base_DB_Table_Data.
241
void Dialog_Import_CSV_Progress::set_primary_key_value(const Gtk::TreeModel::iterator& row, const Gnome::Gda::Value& value)
243
// This is actually called by Base_DB_Table_Data::record_new(), but we can safely ignore it.
244
//throw std::logic_error("Dialog_Import_CSV_Progress::set_primary_key_value() called");
247
Gnome::Gda::Value Dialog_Import_CSV_Progress::get_primary_key_value(const Gtk::TreeModel::iterator& row) const
249
throw std::logic_error("Dialog_Import_CSV_Progress::get_primary_key_value() called");