~ubuntu-branches/ubuntu/quantal/glom/quantal

« back to all changes in this revision

Viewing changes to glom/dialog_import_csv_progress.cc

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2009-01-11 17:12:01 UTC
  • mfrom: (1.1.39 upstream)
  • Revision ID: james.westby@ubuntu.com-20090111171201-0ov9zh1fxfueshxc
Tags: 1.8.5-0ubuntu1
* New upstream release (LP: #256701), fixes LP bugs: 
  + Clear the text in property dialogs for text items (LP: #309147)
  + Don't crash when showing and then hiding the grid (LP: #303453)
  + Temporarily remember the sort order so it is the same when navigating 
    away and back (LP: #303422)
  + Use the list's sort order for the top-level records in the report 
    (LP: #303425)
  + Users/Groups: Disable drag-and-drop for the treeview, because it is
    useless and confusing (LP: #299573)
  + Import: Sort the fields list alphabetically (LP: #306593)
  + delete primary key make unusuable the database (LP: #299549)
  + Spanish translate incomplete (LP: #299556)
  + import date format error (LP: #299591)
  + can't delete data from table list view (LP: #299853)
  + Field definition: default value not saved (LP: #299896)
  + reports crashing (LP: #300054)
  + Year error with date fields (LP: #300057)
  + list view: 2 records added instead of 1 (LP: #300819)
* debian/control: Refreshed dependencies for libglom-dev.
* debian/control: Updated build-deps to match configure checks. goocavnasmm
  build-dep bumped to version without .la files.
* debian/rules: Don't delete the directory containing the templates.
* debian/control, debian/rules, debian/glom-doc.*: Split out
  arch-independent manual and examples into separate package glom-doc, which
  is now recommended by glom (glom will still work if they're not available)
* debian/copyright: Rewritten to new machine-readable format. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Glom
 
2
 *
 
3
 * Copyright (C) 2001-2004 Murray Cumming
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 */
 
20
 
 
21
#include "dialog_import_csv_progress.h"
 
22
#include "config.h"
 
23
 
 
24
#include <glom/libglom/data_structure/glomconversions.h>
 
25
#include <glibmm/i18n.h>
 
26
 
 
27
namespace Glom
 
28
{
 
29
 
 
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)
 
32
{
 
33
  refGlade->get_widget("import_csv_progress_progress_bar", m_progress_bar);
 
34
  refGlade->get_widget("import_csv_progress_textview", m_text_view);
 
35
 
 
36
  if(!m_progress_bar || !m_text_view)
 
37
    throw std::runtime_error("Missing widgets from glade file for Dialog_Import_CSV_Progress");
 
38
}
 
39
 
 
40
bool Dialog_Import_CSV_Progress::init_db_details(const Glib::ustring& table_name)
 
41
{
 
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);
 
44
  return result;
 
45
}
 
46
 
 
47
void Dialog_Import_CSV_Progress::import(Dialog_Import_CSV& data_source)
 
48
{
 
49
  // Cancel any running operations
 
50
  clear();
 
51
 
 
52
  // Begin with first row from source
 
53
  m_data_source = &data_source;
 
54
  m_current_row = 0;
 
55
 
 
56
  switch(data_source.get_state())
 
57
  {
 
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
 
61
    // parsing error.
 
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));
 
64
    break;
 
65
  case Dialog_Import_CSV::PARSED:
 
66
    begin_import();
 
67
    break;
 
68
  default:
 
69
    // This function should not be called with data_source being in other states
 
70
    g_assert_not_reached();
 
71
    break;
 
72
  }
 
73
 
 
74
  set_response_sensitive(Gtk::RESPONSE_CANCEL, true);
 
75
  set_response_sensitive(Gtk::RESPONSE_OK, false);
 
76
}
 
77
 
 
78
void Dialog_Import_CSV_Progress::clear()
 
79
{
 
80
  // Cancel any running import
 
81
  m_progress_connection.disconnect();
 
82
  m_ready_connection.disconnect();
 
83
 
 
84
  m_data_source = NULL;
 
85
  m_current_row = 0;
 
86
}
 
87
 
 
88
void Dialog_Import_CSV_Progress::add_text(const Glib::ustring& text)
 
89
{
 
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());
 
92
}
 
93
 
 
94
void Dialog_Import_CSV_Progress::begin_import()
 
95
{
 
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);
 
98
 
 
99
  m_progress_connection = Glib::signal_idle().connect(sigc::mem_fun(*this, &Dialog_Import_CSV_Progress::on_idle_import));
 
100
}
 
101
 
 
102
void Dialog_Import_CSV_Progress::on_state_changed()
 
103
{
 
104
  switch(m_data_source->get_state())
 
105
  {
 
106
  case Dialog_Import_CSV::ENCODING_ERROR:
 
107
    // Cancel on error
 
108
    response(Gtk::RESPONSE_CANCEL);
 
109
    break;
 
110
  case Dialog_Import_CSV::PARSED:
 
111
    // Begin importing when fully parsed
 
112
    begin_import();
 
113
    //m_progress_connection = Glib::signal_idle().connect(sigc::mem_fun(*this, &Dialog_Import_CSV_Progress::on_idle_import));
 
114
    break;
 
115
  default:
 
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();
 
120
    break;
 
121
  }
 
122
}
 
123
 
 
124
bool Dialog_Import_CSV_Progress::on_idle_import()
 
125
{
 
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()));
 
128
 
 
129
  if(m_current_row == m_data_source->get_row_count())
 
130
  {
 
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"));
 
136
    return false;
 
137
  }
 
138
 
 
139
  // Update the current row values map:
 
140
  for(unsigned int i = 0; i < m_data_source->get_column_count(); ++ i)
 
141
  {
 
142
    const sharedptr<Field>& field = m_data_source->get_field_for_column(i);
 
143
    if(field)
 
144
    {
 
145
      bool success;
 
146
      Gnome::Gda::Value value = field->from_sql(m_data_source->get_data(m_current_row, i), success);
 
147
 
 
148
      if(success)
 
149
      {
 
150
        // Make the value empty if the value is not unique.
 
151
        if(field->get_unique_key())
 
152
        {
 
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))
 
156
          {
 
157
            value = Gnome::Gda::Value();
 
158
 
 
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()));
 
160
            add_text(message);
 
161
          }
 
162
        }
 
163
 
 
164
        m_current_row_values[field->get_name()] = value;
 
165
      }
 
166
      else
 
167
      {
 
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)));
 
169
        add_text(message);
 
170
      }
 
171
    }
 
172
  }
 
173
 
 
174
  // Choose the primary key value
 
175
  Gnome::Gda::Value primary_key_value;
 
176
  if(m_field_primary_key->get_auto_increment())
 
177
  {
 
178
    primary_key_value = get_next_auto_increment_value(m_table_name, m_field_primary_key->get_name());
 
179
  }
 
180
  else
 
181
  {
 
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);
 
186
 
 
187
    if(!get_field_value_is_unique(m_table_name, layout_item, primary_key_value))
 
188
      primary_key_value = Gnome::Gda::Value();
 
189
  }
 
190
  
 
191
  if(Glom::Conversions::value_is_empty(primary_key_value))
 
192
  {
 
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));
 
194
    add_text(message);
 
195
  }
 
196
  else
 
197
  {
 
198
    record_new(true /* use_entered_data */, primary_key_value);
 
199
  }
 
200
 
 
201
  m_current_row_values.clear();
 
202
 
 
203
  ++ m_current_row;
 
204
  return true;
 
205
}
 
206
 
 
207
void Dialog_Import_CSV_Progress::on_response(int response_id)
 
208
{
 
209
  // Don't continue importing when the user already cancelled, or closed the
 
210
  // window via delete event.
 
211
  clear();
 
212
}
 
213
 
 
214
Gnome::Gda::Value Dialog_Import_CSV_Progress::get_entered_field_data(const sharedptr<const LayoutItem_Field>& field) const
 
215
{
 
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();
 
218
  return iter->second;
 
219
}
 
220
 
 
221
void Dialog_Import_CSV_Progress::set_entered_field_data(const sharedptr<const LayoutItem_Field>& field, const Gnome::Gda::Value&  value)
 
222
{
 
223
  m_current_row_values[field->get_name()] = value;
 
224
}
 
225
 
 
226
sharedptr<Field> Dialog_Import_CSV_Progress::get_field_primary_key() const
 
227
{
 
228
  return m_field_primary_key;
 
229
}
 
230
 
 
231
Gnome::Gda::Value Dialog_Import_CSV_Progress::get_primary_key_value_selected() const
 
232
{
 
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();
 
235
  return iter->second;
 
236
}
 
237
 
 
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)
 
242
{
 
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");
 
245
}
 
246
 
 
247
Gnome::Gda::Value Dialog_Import_CSV_Progress::get_primary_key_value(const Gtk::TreeModel::iterator& row) const
 
248
{
 
249
  throw std::logic_error("Dialog_Import_CSV_Progress::get_primary_key_value() called");
 
250
}
 
251
 
 
252
} //namespace Glom