• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kaddressbook

  • sources
  • kde-4.12
  • kdepim
  • kaddressbook
  • xxport
  • csv
csvimportdialog.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KAddressBook.
3  Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 
20 #include "csvimportdialog.h"
21 
22 #include "dateparser.h"
23 #include "qcsvmodel.h"
24 #include "templateselectiondialog.h"
25 
26 #include <KApplication>
27 #include <KComboBox>
28 #include <KDebug>
29 #include <KFileDialog>
30 #include <KInputDialog>
31 #include <KLineEdit>
32 #include <KLocale>
33 #include <KMessageBox>
34 #include <KProgressDialog>
35 #include <KStandardDirs>
36 #include <KUrlRequester>
37 
38 #include <QtCore/QPointer>
39 #include <QtCore/QTextCodec>
40 #include <QtCore/QThread>
41 #include <QtCore/QUuid>
42 #include <QButtonGroup>
43 #include <QCheckBox>
44 #include <QGridLayout>
45 #include <QGroupBox>
46 #include <QHBoxLayout>
47 #include <QHeaderView>
48 #include <QLabel>
49 #include <QPushButton>
50 #include <QRadioButton>
51 #include <QStyledItemDelegate>
52 #include <QTableView>
53 
54 enum {
55  Local = 0,
56  Latin1 = 1,
57  Uni = 2,
58  MSBug = 3,
59  Codec = 4
60 };
61 
62 class ContactFieldComboBox : public KComboBox
63 {
64  public:
65 
66  ContactFieldComboBox( QWidget *parent = 0 )
67  : KComboBox( parent )
68  {
69  fillFieldMap();
70 
71  addItem( ContactFields::label( ContactFields::Undefined ), ContactFields::Undefined );
72 
73  QMapIterator<QString, ContactFields::Field> it( mFieldMap );
74  while ( it.hasNext() ) {
75  it.next();
76 
77  addItem( it.key(), QVariant( it.value() ) );
78  }
79 
80  int maxLength = 0;
81  for ( int i = 0; i < count(); ++i ) {
82  maxLength = qMax( maxLength, itemText( i ).length() );
83  }
84 
85  setMinimumContentsLength( maxLength );
86  setSizeAdjustPolicy( AdjustToMinimumContentsLength );
87  setFixedSize( sizeHint() );
88  }
89 
90  void setCurrentField( ContactFields::Field field )
91  {
92  setCurrentIndex( findData( (uint)field ) );
93  }
94 
95  ContactFields::Field currentField() const
96  {
97  return ( ContactFields::Field )itemData( currentIndex() ).toUInt();
98  }
99 
100  private:
101  static void fillFieldMap()
102  {
103  if ( !mFieldMap.isEmpty() ) {
104  return;
105  }
106 
107  ContactFields::Fields fields = ContactFields::allFields();
108  fields.remove( ContactFields::Undefined );
109 
110  for ( int i = 0; i < fields.count(); ++i ) {
111  mFieldMap.insert( ContactFields::label( fields.at( i ) ), fields.at( i ) );
112  }
113  }
114 
115  static QMap<QString, ContactFields::Field> mFieldMap;
116 };
117 
118 QMap<QString, ContactFields::Field> ContactFieldComboBox::mFieldMap;
119 
120 class ContactFieldDelegate : public QStyledItemDelegate
121 {
122  public:
123  ContactFieldDelegate( QObject *parent = 0 )
124  : QStyledItemDelegate( parent )
125  {
126  }
127 
128  QString displayText( const QVariant &value, const QLocale & ) const
129  {
130  return ContactFields::label( ( ContactFields::Field )value.toUInt() );
131  }
132 
133  QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &,
134  const QModelIndex & ) const
135  {
136  ContactFieldComboBox *editor = new ContactFieldComboBox( parent );
137 
138  return editor;
139  }
140 
141  void setEditorData( QWidget *editor, const QModelIndex &index ) const
142  {
143  const unsigned int value = index.model()->data( index, Qt::EditRole ).toUInt();
144 
145  ContactFieldComboBox *fieldCombo = static_cast<ContactFieldComboBox*>( editor );
146  fieldCombo->setCurrentField( ( ContactFields::Field )value );
147  }
148 
149  void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
150  {
151  ContactFieldComboBox *fieldCombo = static_cast<ContactFieldComboBox*>( editor );
152 
153  model->setData( index, fieldCombo->currentField(), Qt::EditRole );
154  }
155 
156  void updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option,
157  const QModelIndex & ) const
158  {
159  editor->setGeometry( option.rect );
160  }
161 
162  void paint( QPainter *painter, const QStyleOptionViewItem &option,
163  const QModelIndex &index ) const
164  {
165  if ( index.row() == 0 ) {
166  QStyleOptionViewItem headerOption( option );
167  headerOption.font.setBold( true );
168 
169  QStyledItemDelegate::paint( painter, headerOption, index );
170  } else {
171  QStyledItemDelegate::paint( painter, option, index );
172  }
173  }
174 };
175 
176 CSVImportDialog::CSVImportDialog( QWidget *parent )
177  : KDialog( parent ), mDevice( 0 )
178 {
179  setCaption( i18nc( "@title:window", "CSV Import Dialog" ) );
180  setButtons( Ok | Cancel | User1 | User2 );
181  setDefaultButton( Ok );
182  setModal( true );
183  showButtonSeparator( true );
184 
185  mModel = new QCsvModel( this );
186 
187  initGUI();
188 
189  reloadCodecs();
190 
191  connect( mUrlRequester, SIGNAL(returnPressed(QString)),
192  this, SLOT(setFile(QString)) );
193  connect( mUrlRequester, SIGNAL(urlSelected(KUrl)),
194  this, SLOT(setFile(KUrl)) );
195  connect( mUrlRequester->lineEdit(), SIGNAL(textChanged(QString)),
196  this, SLOT(urlChanged(QString)) );
197  connect( mDelimiterGroup, SIGNAL(buttonClicked(int)),
198  this, SLOT(delimiterClicked(int)) );
199  connect( mDelimiterEdit, SIGNAL(returnPressed()),
200  this, SLOT(customDelimiterChanged()) );
201  connect( mDelimiterEdit, SIGNAL(textChanged(QString)),
202  this, SLOT(customDelimiterChanged(QString)) );
203  connect( mComboQuote, SIGNAL(activated(QString)),
204  this, SLOT(textQuoteChanged(QString)) );
205  connect( mCodecCombo, SIGNAL(activated(QString)),
206  this, SLOT(codecChanged()) );
207  connect( mSkipFirstRow, SIGNAL(toggled(bool)),
208  this, SLOT(skipFirstRowChanged(bool)) );
209 
210  connect( mModel, SIGNAL(finishedLoading()), this, SLOT(modelFinishedLoading()) );
211 
212  delimiterClicked( 0 );
213  textQuoteChanged( QLatin1String("\"") );
214  skipFirstRowChanged( false );
215 }
216 
217 CSVImportDialog::~CSVImportDialog()
218 {
219  delete mDevice;
220 }
221 
222 KABC::AddresseeList CSVImportDialog::contacts() const
223 {
224  KABC::AddresseeList contacts;
225  DateParser dateParser( mDatePatternEdit->text() );
226 
227  KProgressDialog progressDialog( const_cast<CSVImportDialog*>( this )->mainWidget() );
228  progressDialog.setAutoClose( true );
229  progressDialog.progressBar()->setMaximum( mModel->rowCount() );
230  progressDialog.setLabelText( i18nc( "@label", "Importing contacts" ) );
231  progressDialog.show();
232 
233  kapp->processEvents();
234 
235  for ( int row = 1; row < mModel->rowCount(); ++row ) {
236  KABC::Addressee contact;
237  bool emptyRow = true;
238 
239  for ( int column = 0; column < mModel->columnCount(); ++column ) {
240  QString value = mModel->data( mModel->index( row, column ), Qt::DisplayRole ).toString();
241 
242  if ( !value.isEmpty() ) {
243  emptyRow = false;
244 
245  const ContactFields::Field field =
246  ( ContactFields::Field )mModel->data( mModel->index( 0, column ) ).toUInt();
247 
248  // convert the custom date format to ISO format
249  if ( field == ContactFields::Birthday || field == ContactFields::Anniversary ) {
250  value = dateParser.parse( value ).toString( Qt::ISODate );
251  }
252 
253  value.replace( QLatin1String("\\n"), QLatin1String("\n") );
254 
255  ContactFields::setValue( field, value, contact );
256  }
257  }
258 
259  kapp->processEvents();
260 
261  if ( progressDialog.wasCancelled() ) {
262  return KABC::AddresseeList();
263  }
264 
265  progressDialog.progressBar()->setValue( progressDialog.progressBar()->value() + 1 );
266 
267  if ( !emptyRow && !contact.isEmpty() ) {
268  contacts.append( contact );
269  }
270  }
271 
272  return contacts;
273 }
274 
275 void CSVImportDialog::initGUI()
276 {
277  QWidget *page = new QWidget( this );
278  setMainWidget( page );
279 
280  QGridLayout *layout = new QGridLayout( page );
281  layout->setSpacing( spacingHint() );
282  layout->setMargin( 0 );
283 
284  QHBoxLayout *hbox = new QHBoxLayout();
285  hbox->setSpacing( spacingHint() );
286 
287  QLabel *label = new QLabel( i18nc( "@label", "File to import:" ), page );
288  hbox->addWidget( label );
289 
290  mUrlRequester = new KUrlRequester( page );
291  mUrlRequester->setFilter( QLatin1String("*.csv") );
292  mUrlRequester->lineEdit()->setTrapReturnKey( true );
293  mUrlRequester->setToolTip(
294  i18nc( "@info:tooltip", "Select a csv file to import" ) );
295  mUrlRequester->setWhatsThis(
296  i18nc( "@info:whatsthis",
297  "Click this button to start a file chooser that will allow you to "
298  "select a csv file to import." ) );
299  hbox->addWidget( mUrlRequester );
300 
301  layout->addLayout( hbox, 0, 0, 1, 5 );
302 
303  // Delimiter: comma, semicolon, tab, space, other
304  QGroupBox *group = new QGroupBox( i18nc( "@title:group", "Delimiter" ), page );
305  QGridLayout *delimiterLayout = new QGridLayout;
306  delimiterLayout->setMargin( marginHint() );
307  delimiterLayout->setSpacing( spacingHint() );
308  group->setLayout( delimiterLayout );
309  delimiterLayout->setAlignment( Qt::AlignTop );
310  layout->addWidget( group, 1, 0, 4, 1 );
311 
312  mDelimiterGroup = new QButtonGroup( this );
313  mDelimiterGroup->setExclusive( true );
314 
315  QRadioButton *button = new QRadioButton( i18nc( "@option:radio Field separator", "Comma" ) );
316  button->setToolTip(
317  i18nc( "@info:tooltip", "Set the field separator to a comma" ) );
318  button->setWhatsThis(
319  i18nc( "@info:whatsthis",
320  "Select this option if your csv file uses the comma as a field separator." ) );
321  button->setChecked( true );
322  mDelimiterGroup->addButton( button, 0 );
323  delimiterLayout->addWidget( button, 0, 0 );
324 
325  button = new QRadioButton( i18nc( "@option:radio Field separator", "Semicolon" ) );
326  button->setToolTip(
327  i18nc( "@info:tooltip", "Set the field separator to a semicolon" ) );
328  button->setWhatsThis(
329  i18nc( "@info:whatsthis",
330  "Select this option if your csv file uses the semicolon as a field separator." ) );
331  mDelimiterGroup->addButton( button, 1 );
332  delimiterLayout->addWidget( button, 0, 1 );
333 
334  button = new QRadioButton( i18nc( "@option:radio Field separator", "Tabulator" ) );
335  button->setToolTip(
336  i18nc( "@info:tooltip", "Set the field separator to a tab character" ) );
337  button->setWhatsThis(
338  i18nc( "@info:whatsthis",
339  "Select this option if your csv file uses the tab character as a field separator." ) );
340  mDelimiterGroup->addButton( button, 2 );
341  delimiterLayout->addWidget( button, 1, 0 );
342 
343  button = new QRadioButton( i18nc( "@option:radio Field separator", "Space" ) );
344  button->setToolTip(
345  i18nc( "@info:tooltip", "Set the field separator to a space character" ) );
346  button->setWhatsThis(
347  i18nc( "@info:whatsthis",
348  "Select this option if your csv file uses the space character as a field separator." ) );
349  mDelimiterGroup->addButton( button, 3 );
350  delimiterLayout->addWidget( button, 1, 1 );
351 
352  button = new QRadioButton( i18nc( "@option:radio Custum field separator", "Other" ) );
353  button->setToolTip(
354  i18nc( "@info:tooltip", "Set the field separator to a custom character" ) );
355  button->setWhatsThis(
356  i18nc( "@info:whatsthis",
357  "Select this option if to use some other character as the field delimiter "
358  "for the data in your csv file." ) );
359  mDelimiterGroup->addButton( button, 4 );
360  delimiterLayout->addWidget( button, 0, 2 );
361 
362  mDelimiterEdit = new KLineEdit( group );
363  mDelimiterEdit->setToolTip(
364  i18nc( "@info:tooltip",
365  "Set the custom delimiter character" ) );
366  mDelimiterEdit->setWhatsThis(
367  i18nc( "@info:whatsthis",
368  "Enter a custom character to use as the delimiter character. "
369  "If you enter more than 1 character, only the first will be used and "
370  "the remaining characters will be ignored." ) );
371  delimiterLayout->addWidget( mDelimiterEdit, 1, 2 );
372 
373  // text quote
374  label = new QLabel( i18nc( "@label:listbox", "Text quote:" ), page );
375  layout->addWidget( label, 1, 2 );
376 
377  mComboQuote = new KComboBox( page );
378  mComboQuote->setToolTip(
379  i18nc( "@info:tooltip", "Select the quote character" ) );
380  mComboQuote->setWhatsThis(
381  i18nc( "@info:whatsthis",
382  "Choose the character that your csv data uses to \"quote\" the field delimiter "
383  "if that character happens to occur within the data. For example, if the "
384  "comma is the field delimiter, then any comma occurring with the data "
385  "will be \"quoted\" by the character specified here." ) );
386  mComboQuote->setEditable( false );
387  mComboQuote->addItem( i18nc( "@item:inlistbox Qoute character option", "\"" ), 0 );
388  mComboQuote->addItem( i18nc( "@item:inlistbox Quote character option", "'" ), 1 );
389  mComboQuote->addItem( i18nc( "@item:inlistbox Quote character option", "None" ), 2 );
390  layout->addWidget( mComboQuote, 1, 3 );
391 
392  // date format
393  label = new QLabel( i18nc( "@label:listbox", "Date format:" ), page );
394  layout->addWidget( label, 2, 2 );
395 
396  mDatePatternEdit = new KLineEdit( page );
397  mDatePatternEdit->setText( QLatin1String("Y-M-D") ); // ISO 8601 date format as default
398  mDatePatternEdit->setToolTip(
399  i18nc( "@info:tooltip",
400  "<para><list><item>y: year with 2 digits</item>"
401  "<item>Y: year with 4 digits</item>"
402  "<item>m: month with 1 or 2 digits</item>"
403  "<item>M: month with 2 digits</item>"
404  "<item>d: day with 1 or 2 digits</item>"
405  "<item>D: day with 2 digits</item>"
406  "<item>H: hours with 2 digits</item>"
407  "<item>I: minutes with 2 digits</item>"
408  "<item>S: seconds with 2 digits</item>"
409  "</list></para>" ) );
410  mDatePatternEdit->setWhatsThis(
411  i18nc( "@info:whatsthis",
412  "<para>Specify a format to use for dates included in your csv data. "
413  "Use the following sequences to help you define the format:</para>"
414  "<para><list><item>y: year with 2 digits</item>"
415  "<item>Y: year with 4 digits</item>"
416  "<item>m: month with 1 or 2 digits</item>"
417  "<item>M: month with 2 digits</item>"
418  "<item>d: day with 1 or 2 digits</item>"
419  "<item>D: day with 2 digits</item>"
420  "<item>H: hours with 2 digits</item>"
421  "<item>I: minutes with 2 digits</item>"
422  "<item>S: seconds with 2 digits</item>"
423  "</list></para>"
424  "<para>Example: \"Y-M-D\" corresponds to a date like \"2012-01-04\"</para>" ) );
425  layout->addWidget( mDatePatternEdit, 2, 3 );
426 
427  // text codec
428  label = new QLabel( i18nc( "@label:listbox", "Text codec:" ), page );
429  layout->addWidget( label, 3, 2 );
430 
431  mCodecCombo = new KComboBox( page );
432  mCodecCombo->setToolTip(
433  i18nc( "@info:tooltip", "Select the text codec" ) );
434  mCodecCombo->setWhatsThis(
435  i18nc( "@info:whatsthis",
436  "Choose the character encoding of the data in your csv file." ) );
437  layout->addWidget( mCodecCombo, 3, 3 );
438 
439  // skip first line
440  mSkipFirstRow = new QCheckBox( i18nc( "@option:check", "Skip first row of file" ), page );
441  mSkipFirstRow->setToolTip(
442  i18nc( "@info:tooltip", "Skip first row of csv file when importing" ) );
443  mSkipFirstRow->setWhatsThis(
444  i18nc( "@info:whatsthis",
445  "Check this box if you want the import to skip over the first row "
446  "of the csv data. In many cases, the first line of a csv file will be a "
447  "comment line describing the order of the data fields included in the file." ) );
448  layout->addWidget( mSkipFirstRow, 4, 2, 1, 2 );
449 
450  // csv view
451  mTable = new QTableView( page );
452  mTable->setModel( mModel );
453  mTable->setItemDelegateForRow( 0, new ContactFieldDelegate( this ) );
454  mTable->horizontalHeader()->hide();
455  mTable->verticalHeader()->hide();
456  mTable->setEditTriggers( QAbstractItemView::CurrentChanged );
457  mTable->setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel );
458  layout->addWidget( mTable, 5, 0, 1, 5 );
459 
460  setButtonText( User1, i18nc( "@action:button", "Apply Template..." ) );
461  setButtonText( User2, i18nc( "@action:button", "Save Template..." ) );
462 
463  enableButton( Ok, false );
464  enableButton( User1, false );
465  enableButton( User2, false );
466 
467  resize( 500, 400 );
468 }
469 
470 void CSVImportDialog::reloadCodecs()
471 {
472  mCodecCombo->clear();
473 
474  mCodecs.clear();
475 
476  Q_FOREACH ( const QByteArray &name, QTextCodec::availableCodecs() ) {
477  mCodecs.append( QTextCodec::codecForName( name ) );
478  }
479 
480  mCodecCombo->addItem( i18nc( "@item:inlistbox Codec setting", "Local (%1)",
481  QLatin1String( QTextCodec::codecForLocale()->name() ) ), Local );
482  mCodecCombo->addItem( i18nc( "@item:inlistbox Codec setting", "Latin1" ), Latin1 );
483  mCodecCombo->addItem( i18nc( "@item:inlistbox Codec setting", "Unicode" ), Uni );
484  mCodecCombo->addItem( i18nc( "@item:inlistbox Codec setting", "Microsoft Unicode" ), MSBug );
485 
486  for ( int i = 0; i < mCodecs.count(); ++i ) {
487  mCodecCombo->addItem( QLatin1String(mCodecs.at( i )->name()), Codec + i );
488  }
489 }
490 
491 void CSVImportDialog::customDelimiterChanged()
492 {
493  if ( mDelimiterGroup->checkedId() == 4 ) {
494  delimiterClicked( 4 );
495  }
496 }
497 
498 void CSVImportDialog::customDelimiterChanged( const QString &, bool reload )
499 {
500  mDelimiterGroup->button( 4 )->setChecked ( true );
501  delimiterClicked( 4, reload ); // other
502 }
503 
504 void CSVImportDialog::delimiterClicked( int id, bool reload )
505 {
506  switch ( id ) {
507  case 0: // comma
508  mModel->setDelimiter( QLatin1Char(',') );
509  break;
510  case 4: // other
511  mDelimiterEdit->setFocus( Qt::OtherFocusReason );
512  if ( !mDelimiterEdit->text().isEmpty() ) {
513  mModel->setDelimiter( mDelimiterEdit->text().at( 0 ) );
514  }
515  break;
516  case 2: // tab
517  mModel->setDelimiter( QLatin1Char('\t') );
518  break;
519  case 3: // space
520  mModel->setDelimiter( QLatin1Char(' ') );
521  break;
522  case 1: // semicolon
523  mModel->setDelimiter( QLatin1Char(';') );
524  break;
525  }
526 
527  if ( mDevice && reload ) {
528  mModel->load( mDevice );
529  }
530 }
531 
532 void CSVImportDialog::textQuoteChanged( const QString &mark, bool reload )
533 {
534  if ( mComboQuote->currentIndex() == 2 ) {
535  mModel->setTextQuote( QChar() );
536  } else {
537  mModel->setTextQuote( mark.at( 0 ) );
538  }
539 
540  if ( mDevice && reload ) {
541  mModel->load( mDevice );
542  }
543 }
544 
545 void CSVImportDialog::skipFirstRowChanged( bool checked, bool reload )
546 {
547  mFieldSelection.clear();
548  for ( int column = 0; column < mModel->columnCount(); ++column ) {
549  mFieldSelection.append(
550  ( ContactFields::Field )mModel->data( mModel->index( 0, column ) ).toInt() );
551  }
552 
553  if ( checked ) {
554  mModel->setStartRow( 1 );
555  } else {
556  mModel->setStartRow( 0 );
557  }
558 
559  if ( mDevice && reload ) {
560  mModel->load( mDevice );
561  }
562 }
563 
564 void CSVImportDialog::slotButtonClicked( int button )
565 {
566  if ( button == KDialog::Ok ) {
567  bool assigned = false;
568 
569  for ( int column = 0; column < mModel->columnCount(); ++column ) {
570  if ( mModel->data( mModel->index( 0, column ),
571  Qt::DisplayRole ).toUInt() != ContactFields::Undefined ) {
572  assigned = true;
573  break;
574  }
575  }
576 
577  if ( !assigned ) {
578  KMessageBox::sorry(
579  this,
580  i18nc( "@info:status", "You must assign at least one column." ) );
581  } else {
582  accept();
583  }
584  } else if ( button == User1 ) {
585  applyTemplate();
586  } else if ( button == User2 ) {
587  saveTemplate();
588  } else if ( button == KDialog::Cancel ) {
589  reject();
590  }
591 }
592 
593 void CSVImportDialog::applyTemplate()
594 {
595  QPointer<TemplateSelectionDialog> dlg = new TemplateSelectionDialog( this );
596  if ( !dlg->templatesAvailable() ) {
597  KMessageBox::sorry(
598  this,
599  i18nc( "@label", "There are no templates available yet." ),
600  i18nc( "@title:window", "No templates available" ) );
601  delete dlg;
602  return;
603  }
604 
605  if ( !dlg->exec() || !dlg ) {
606  delete dlg;
607  return;
608  }
609 
610  const QString templateFileName = dlg->selectedTemplate();
611  delete dlg;
612 
613  KConfig config( templateFileName, KConfig::SimpleConfig );
614 
615  const KConfigGroup generalGroup( &config, "General" );
616  mDatePatternEdit->setText( generalGroup.readEntry( "DatePattern", "Y-M-D" ) );
617  mDelimiterEdit->setText( generalGroup.readEntry( "DelimiterOther" ) );
618 
619  const int delimiterButton = generalGroup.readEntry( "DelimiterType", 0 );
620  const int quoteType = generalGroup.readEntry( "QuoteType", 0 );
621  const bool skipFirstRow = generalGroup.readEntry( "SkipFirstRow", false );
622 
623  mDelimiterGroup->button( delimiterButton )->setChecked( true );
624  delimiterClicked( delimiterButton, false );
625 
626  mComboQuote->setCurrentIndex( quoteType );
627  textQuoteChanged( mComboQuote->currentText(), false );
628 
629  // do block signals here, otherwise it will trigger a reload of the model and
630  // the following skipFirstRowChanged call end up with an empty model
631  mSkipFirstRow->blockSignals( true );
632  mSkipFirstRow->setChecked( skipFirstRow );
633  mSkipFirstRow->blockSignals( false );
634 
635  skipFirstRowChanged( skipFirstRow, false );
636 
637  if ( mDevice ) {
638  mModel->load( mDevice );
639  }
640 
641  setProperty( "TemplateFileName", templateFileName );
642  connect( mModel, SIGNAL(finishedLoading()), this, SLOT(finalizeApplyTemplate()) );
643 }
644 
645 void CSVImportDialog::finalizeApplyTemplate()
646 {
647  const QString templateFileName = property( "TemplateFileName" ).toString();
648 
649  KConfig config( templateFileName, KConfig::SimpleConfig );
650 
651  const KConfigGroup generalGroup( &config, "General" );
652  const uint columns = generalGroup.readEntry( "Columns", 0 );
653 
654  // create the column map
655  const KConfigGroup columnMapGroup( &config, "csv column map" );
656 
657  for ( uint i = 0; i < columns; ++i ) {
658  const uint assignedField = columnMapGroup.readEntry( QString::number( i ), 0 );
659  mModel->setData( mModel->index( 0, i ), assignedField, Qt::EditRole );
660  }
661 }
662 
663 void CSVImportDialog::saveTemplate()
664 {
665  const QString name =
666  KInputDialog::getText( i18nc( "@title:window", "Template Name" ),
667  i18nc( "@info", "Please enter a name for the template:" ) );
668 
669  if ( name.isEmpty() ) {
670  return;
671  }
672 
673  const QString fileName =
674  KStandardDirs::locateLocal( "data", QLatin1String( "kaddressbook/csv-templates/") +
675  QUuid::createUuid().toString() +
676  QLatin1String(".desktop" ));
677 
678  KConfig config( fileName );
679  KConfigGroup generalGroup( &config, "General" );
680  generalGroup.writeEntry( "DatePattern", mDatePatternEdit->text() );
681  generalGroup.writeEntry( "Columns", mModel->columnCount() );
682  generalGroup.writeEntry( "DelimiterType", mDelimiterGroup->checkedId() );
683  generalGroup.writeEntry( "DelimiterOther", mDelimiterEdit->text() );
684  generalGroup.writeEntry( "SkipFirstRow", mSkipFirstRow->isChecked() );
685  generalGroup.writeEntry( "QuoteType", mComboQuote->currentIndex() );
686 
687  KConfigGroup miscGroup( &config, "Misc" );
688  miscGroup.writeEntry( "Name", name );
689 
690  KConfigGroup columnMapGroup( &config, "csv column map" );
691  for ( int column = 0; column < mModel->columnCount(); ++column ) {
692  columnMapGroup.writeEntry( QString::number( column ),
693  mModel->data( mModel->index( 0, column ),
694  Qt::DisplayRole ).toUInt() );
695  }
696 
697  config.sync();
698 }
699 
700 void CSVImportDialog::setFile( const KUrl &fileName )
701 {
702  setFile( fileName.toLocalFile() );
703 }
704 
705 void CSVImportDialog::setFile( const QString &fileName )
706 {
707  if ( fileName.isEmpty() ) {
708  return;
709  }
710 
711  QFile *file = new QFile( fileName );
712  if ( !file->open( QIODevice::ReadOnly ) ) {
713  KMessageBox::sorry( this, i18nc( "@info:status", "Cannot open input file." ) );
714  delete file;
715  return;
716  }
717 
718  delete mDevice;
719 
720  mDevice = file;
721 
722  mModel->load( mDevice );
723 }
724 
725 void CSVImportDialog::urlChanged( const QString &file )
726 {
727  bool state = !file.isEmpty();
728 
729  enableButton( Ok, state );
730  enableButton( User1, state );
731  enableButton( User2, state );
732 }
733 
734 void CSVImportDialog::codecChanged( bool reload )
735 {
736  const int code = mCodecCombo->currentIndex();
737 
738  if ( code == Local ) {
739  mModel->setTextCodec( QTextCodec::codecForLocale() );
740  } else if ( code >= Codec ) {
741  mModel->setTextCodec( mCodecs.at( code - Codec ) );
742  } else if ( code == Uni ) {
743  mModel->setTextCodec( QTextCodec::codecForName( "UTF-16" ) );
744  } else if ( code == MSBug ) {
745  mModel->setTextCodec( QTextCodec::codecForName( "UTF-16LE" ) );
746  } else if ( code == Latin1 ) {
747  mModel->setTextCodec( QTextCodec::codecForName( "ISO 8859-1" ) );
748  } else {
749  mModel->setTextCodec( QTextCodec::codecForName( "UTF-8" ) );
750  }
751 
752  if ( mDevice && reload ) {
753  mModel->load( mDevice );
754  }
755 }
756 
757 void CSVImportDialog::modelFinishedLoading()
758 {
759  ContactFieldComboBox *box = new ContactFieldComboBox();
760  int preferredWidth = box->sizeHint().width();
761  delete box;
762 
763  for ( int i = 0; i < mModel->columnCount(); ++i ) {
764  mTable->setColumnWidth( i, preferredWidth );
765  }
766 
767  for ( int column = 0; column < mFieldSelection.count(); ++column ) {
768  mModel->setData( mModel->index( 0, column ), mFieldSelection.at( column ), Qt::EditRole );
769  }
770  mFieldSelection.clear();
771 }
772 
773 #include <csvimportdialog.moc>
ContactFields::Undefined
Definition: contactfields.h:34
Local
Definition: csvimportdialog.cpp:55
QCsvModel::setTextCodec
void setTextCodec(QTextCodec *textCodec)
Sets the text codec that shall be used for parsing the csv list.
Definition: qcsvmodel.cpp:242
CSVImportDialog::contacts
KABC::AddresseeList contacts() const
Definition: csvimportdialog.cpp:222
QCsvModel::rowCount
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
Inherited from QAbstractTableModel.
Definition: qcsvmodel.cpp:272
QCsvModel::setStartRow
void setStartRow(uint startRow)
Sets the row from where the parsing shall be started.
Definition: qcsvmodel.cpp:221
QCsvModel::setDelimiter
void setDelimiter(const QChar &delimiter)
Sets the character that is used as delimiter for fields.
Definition: qcsvmodel.cpp:200
CSVImportDialog::slotButtonClicked
virtual void slotButtonClicked(int)
Definition: csvimportdialog.cpp:564
QCsvModel::data
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Inherited from QAbstractTableModel.
Definition: qcsvmodel.cpp:281
KDialog
DateParser
This class parses the datetime out of a given string with the help of a pattern.
Definition: dateparser.h:41
QObject
QCsvModel::load
bool load(QIODevice *device)
Loads the data from the device into the model.
Definition: qcsvmodel.cpp:166
ContactFields::Birthday
Definition: contactfields.h:44
MSBug
Definition: csvimportdialog.cpp:58
Latin1
Definition: csvimportdialog.cpp:56
templateselectiondialog.h
CSVImportDialog::~CSVImportDialog
~CSVImportDialog()
Definition: csvimportdialog.cpp:217
Uni
Definition: csvimportdialog.cpp:57
CSVImportDialog::CSVImportDialog
CSVImportDialog(QWidget *parent=0)
Definition: csvimportdialog.cpp:176
ContactFields::Fields
QVector< Field > Fields
Defines a list of Field enums.
Definition: contactfields.h:95
QCsvModel::columnCount
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
Inherited from QAbstractTableModel.
Definition: qcsvmodel.cpp:263
ContactFields::label
static QString label(Field field)
Returns the i18n label for the field.
Definition: contactfields.cpp:25
TemplateSelectionDialog
Definition: templateselectiondialog.h:27
csvimportdialog.h
QCsvModel::setTextQuote
void setTextQuote(const QChar &textQuote)
Sets the character that is used for quoting.
Definition: qcsvmodel.cpp:179
ContactFields::Anniversary
Definition: contactfields.h:45
ContactFields::setValue
static void setValue(Field field, const QString &value, KABC::Addressee &contact)
Sets the value of the field for the contact.
Definition: contactfields.cpp:233
dateparser.h
Codec
Definition: csvimportdialog.cpp:59
QCsvModel::setData
virtual bool setData(const QModelIndex &index, const QVariant &data, int role=Qt::EditRole)
Inherited from QAbstractTableModel.
Definition: qcsvmodel.cpp:313
ContactFields::Field
Field
Describes the standard fields that are available for every contact.
Definition: contactfields.h:33
qcsvmodel.h
ContactFields::allFields
static Fields allFields()
Returns a list of all available fields.
Definition: contactfields.cpp:177
QCsvModel
Definition: qcsvmodel.h:25
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:55:51 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kaddressbook

Skip menu "kaddressbook"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal