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

kaddressbook

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

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