kaddressbook Library API Documentation

csvimportdialog.cpp

00001 /* 00002 This file is part of KAddressBook. 00003 Copyright (C) 2003 Tobias Koenig <tokoe@kde.org> 00004 based on the code of KSpread's CSV Import Dialog 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 00023 #include <qbuttongroup.h> 00024 #include <qcheckbox.h> 00025 #include <qcombobox.h> 00026 #include <qlabel.h> 00027 #include <qlayout.h> 00028 #include <qlineedit.h> 00029 #include <qpushbutton.h> 00030 #include <qradiobutton.h> 00031 #include <qtable.h> 00032 #include <qtooltip.h> 00033 00034 #include <kapplication.h> 00035 #include <kdebug.h> 00036 #include <kdialogbase.h> 00037 #include <kfiledialog.h> 00038 #include <klineedit.h> 00039 #include <klocale.h> 00040 #include <kinputdialog.h> 00041 #include <kmessagebox.h> 00042 #include <kprogress.h> 00043 #include <kstandarddirs.h> 00044 #include <kurlrequester.h> 00045 00046 #include "dateparser.h" 00047 00048 #include "csvimportdialog.h" 00049 00050 CSVImportDialog::CSVImportDialog( KABC::AddressBook *ab, QWidget *parent, 00051 const char * name ) 00052 : KDialogBase( Plain, i18n ( "CSV Import Dialog" ), Ok | Cancel | User1 | 00053 User2, Ok, parent, name, true, true ), 00054 mAdjustRows( false ), 00055 mStartLine( 0 ), 00056 mTextQuote( '"' ), 00057 mDelimiter( "," ), 00058 mAddressBook( ab ) 00059 { 00060 initGUI(); 00061 00062 mTypeMap.insert( i18n( "Undefined" ), Undefined ); 00063 mTypeMap.insert( KABC::Addressee::formattedNameLabel(), FormattedName ); 00064 mTypeMap.insert( KABC::Addressee::familyNameLabel(), FamilyName ); 00065 mTypeMap.insert( KABC::Addressee::givenNameLabel(), GivenName ); 00066 mTypeMap.insert( KABC::Addressee::additionalNameLabel(), AdditionalName ); 00067 mTypeMap.insert( KABC::Addressee::prefixLabel(), Prefix ); 00068 mTypeMap.insert( KABC::Addressee::suffixLabel(), Suffix ); 00069 mTypeMap.insert( KABC::Addressee::nickNameLabel(), NickName ); 00070 mTypeMap.insert( KABC::Addressee::birthdayLabel(), Birthday ); 00071 00072 mTypeMap.insert( KABC::Addressee::homeAddressStreetLabel(), HomeAddressStreet ); 00073 mTypeMap.insert( KABC::Addressee::homeAddressLocalityLabel(), 00074 HomeAddressLocality ); 00075 mTypeMap.insert( KABC::Addressee::homeAddressRegionLabel(), HomeAddressRegion ); 00076 mTypeMap.insert( KABC::Addressee::homeAddressPostalCodeLabel(), 00077 HomeAddressPostalCode ); 00078 mTypeMap.insert( KABC::Addressee::homeAddressCountryLabel(), 00079 HomeAddressCountry ); 00080 mTypeMap.insert( KABC::Addressee::homeAddressLabelLabel(), HomeAddressLabel ); 00081 00082 mTypeMap.insert( KABC::Addressee::businessAddressStreetLabel(), 00083 BusinessAddressStreet ); 00084 mTypeMap.insert( KABC::Addressee::businessAddressLocalityLabel(), 00085 BusinessAddressLocality ); 00086 mTypeMap.insert( KABC::Addressee::businessAddressRegionLabel(), 00087 BusinessAddressRegion ); 00088 mTypeMap.insert( KABC::Addressee::businessAddressPostalCodeLabel(), 00089 BusinessAddressPostalCode ); 00090 mTypeMap.insert( KABC::Addressee::businessAddressCountryLabel(), 00091 BusinessAddressCountry ); 00092 mTypeMap.insert( KABC::Addressee::businessAddressLabelLabel(), 00093 BusinessAddressLabel ); 00094 00095 mTypeMap.insert( KABC::Addressee::homePhoneLabel(), HomePhone ); 00096 mTypeMap.insert( KABC::Addressee::businessPhoneLabel(), BusinessPhone ); 00097 mTypeMap.insert( KABC::Addressee::mobilePhoneLabel(), MobilePhone ); 00098 mTypeMap.insert( KABC::Addressee::homeFaxLabel(), HomeFax ); 00099 mTypeMap.insert( KABC::Addressee::businessFaxLabel(), BusinessFax ); 00100 mTypeMap.insert( KABC::Addressee::carPhoneLabel(), CarPhone ); 00101 mTypeMap.insert( KABC::Addressee::isdnLabel(), Isdn ); 00102 mTypeMap.insert( KABC::Addressee::pagerLabel(), Pager ); 00103 mTypeMap.insert( KABC::Addressee::emailLabel(), Email ); 00104 mTypeMap.insert( KABC::Addressee::mailerLabel(), Mailer ); 00105 mTypeMap.insert( KABC::Addressee::titleLabel(), Title ); 00106 mTypeMap.insert( KABC::Addressee::roleLabel(), Role ); 00107 mTypeMap.insert( KABC::Addressee::organizationLabel(), Organization ); 00108 mTypeMap.insert( KABC::Addressee::noteLabel(), Note ); 00109 mTypeMap.insert( KABC::Addressee::urlLabel(), URL ); 00110 00111 mCustomCounter = mTypeMap.count(); 00112 int count = mCustomCounter; 00113 00114 KABC::Field::List fields = mAddressBook->fields( KABC::Field::CustomCategory ); 00115 KABC::Field::List::Iterator it; 00116 for ( it = fields.begin(); it != fields.end(); ++it, ++count ) 00117 mTypeMap.insert( (*it)->label(), count ); 00118 00119 connect( mDelimiterBox, SIGNAL( clicked( int ) ), 00120 this, SLOT( delimiterClicked( int ) ) ); 00121 connect( mDelimiterEdit, SIGNAL( returnPressed() ), 00122 this, SLOT( returnPressed() ) ); 00123 connect( mDelimiterEdit, SIGNAL( textChanged ( const QString& ) ), 00124 this, SLOT( textChanged ( const QString& ) ) ); 00125 connect( mComboLine, SIGNAL( activated( const QString& ) ), 00126 this, SLOT( lineSelected( const QString& ) ) ); 00127 connect( mComboQuote, SIGNAL( activated( const QString& ) ), 00128 this, SLOT( textquoteSelected( const QString& ) ) ); 00129 connect( mIgnoreDuplicates, SIGNAL( stateChanged( int ) ), 00130 this, SLOT( ignoreDuplicatesChanged( int ) ) ); 00131 00132 connect( mUrlRequester, SIGNAL( returnPressed( const QString& ) ), 00133 this, SLOT( setFile( const QString& ) ) ); 00134 connect( mUrlRequester, SIGNAL( urlSelected( const QString& ) ), 00135 this, SLOT( setFile( const QString& ) ) ); 00136 connect( mUrlRequester->lineEdit(), SIGNAL( textChanged ( const QString& ) ), 00137 this, SLOT( urlChanged( const QString& ) ) ); 00138 00139 connect( this, SIGNAL( user1Clicked() ), 00140 this, SLOT( applyTemplate() ) ); 00141 00142 connect( this, SIGNAL( user2Clicked() ), 00143 this, SLOT( saveTemplate() ) ); 00144 } 00145 00146 CSVImportDialog::~CSVImportDialog() 00147 { 00148 } 00149 00150 KABC::AddresseeList CSVImportDialog::contacts() const 00151 { 00152 DateParser dateParser( mDatePatternEdit->text() ); 00153 KABC::AddresseeList contacts; 00154 00155 KProgressDialog progressDialog( mPage ); 00156 progressDialog.setAutoClose( true ); 00157 progressDialog.progressBar()->setTotalSteps( mTable->numRows() ); 00158 progressDialog.setLabel( i18n( "Importing contacts" ) ); 00159 progressDialog.show(); 00160 00161 kapp->processEvents(); 00162 00163 for ( int row = 1; row < mTable->numRows(); ++row ) { 00164 KABC::Addressee a; 00165 bool emptyRow = true; 00166 KABC::Address addrHome( KABC::Address::Home ); 00167 KABC::Address addrWork( KABC::Address::Work ); 00168 for ( int col = 0; col < mTable->numCols(); ++col ) { 00169 QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, 00170 col ) ); 00171 if ( !item ) { 00172 kdError() << "ERROR: item cast failed" << endl; 00173 continue; 00174 } 00175 00176 QString value = mTable->text( row, col ); 00177 if ( !value.isEmpty() ) 00178 emptyRow = false; 00179 00180 switch ( posToType( item->currentItem() ) ) { 00181 case Undefined: 00182 continue; 00183 break; 00184 case FormattedName: 00185 a.setFormattedName( value ); 00186 break; 00187 case GivenName: 00188 a.setGivenName( value ); 00189 break; 00190 case FamilyName: 00191 a.setFamilyName( value ); 00192 break; 00193 case AdditionalName: 00194 a.setAdditionalName( value ); 00195 break; 00196 case Prefix: 00197 a.setPrefix( value ); 00198 break; 00199 case Suffix: 00200 a.setSuffix( value ); 00201 break; 00202 case NickName: 00203 a.setNickName( value ); 00204 break; 00205 case Birthday: 00206 a.setBirthday( dateParser.parse( value ) ); 00207 break; 00208 case Email: 00209 if ( !value.isEmpty() ) 00210 a.insertEmail( value, true ); 00211 break; 00212 case Role: 00213 a.setRole( value ); 00214 break; 00215 case Title: 00216 a.setTitle( value ); 00217 break; 00218 case Mailer: 00219 a.setMailer( value ); 00220 break; 00221 case URL: 00222 a.setUrl( KURL( value ) ); 00223 break; 00224 case Organization: 00225 a.setOrganization( value ); 00226 break; 00227 case Note: 00228 a.setNote( value ); 00229 break; 00230 00231 case HomePhone: 00232 if ( !value.isEmpty() ) { 00233 KABC::PhoneNumber number( value, KABC::PhoneNumber::Home ); 00234 a.insertPhoneNumber( number ); 00235 } 00236 break; 00237 case BusinessPhone: 00238 if ( !value.isEmpty() ) { 00239 KABC::PhoneNumber number( value, KABC::PhoneNumber::Work ); 00240 a.insertPhoneNumber( number ); 00241 } 00242 break; 00243 case MobilePhone: 00244 if ( !value.isEmpty() ) { 00245 KABC::PhoneNumber number( value, KABC::PhoneNumber::Cell ); 00246 a.insertPhoneNumber( number ); 00247 } 00248 break; 00249 case HomeFax: 00250 if ( !value.isEmpty() ) { 00251 KABC::PhoneNumber number( value, KABC::PhoneNumber::Home | 00252 KABC::PhoneNumber::Fax ); 00253 a.insertPhoneNumber( number ); 00254 } 00255 break; 00256 case BusinessFax: 00257 if ( !value.isEmpty() ) { 00258 KABC::PhoneNumber number( value, KABC::PhoneNumber::Work | 00259 KABC::PhoneNumber::Fax ); 00260 a.insertPhoneNumber( number ); 00261 } 00262 break; 00263 case CarPhone: 00264 if ( !value.isEmpty() ) { 00265 KABC::PhoneNumber number( value, KABC::PhoneNumber::Car ); 00266 a.insertPhoneNumber( number ); 00267 } 00268 break; 00269 case Isdn: 00270 if ( !value.isEmpty() ) { 00271 KABC::PhoneNumber number( value, KABC::PhoneNumber::Isdn ); 00272 a.insertPhoneNumber( number ); 00273 } 00274 break; 00275 case Pager: 00276 if ( !value.isEmpty() ) { 00277 KABC::PhoneNumber number( value, KABC::PhoneNumber::Pager ); 00278 a.insertPhoneNumber( number ); 00279 } 00280 break; 00281 00282 case HomeAddressStreet: 00283 addrHome.setStreet( value ); 00284 break; 00285 case HomeAddressLocality: 00286 addrHome.setLocality( value ); 00287 break; 00288 case HomeAddressRegion: 00289 addrHome.setRegion( value ); 00290 break; 00291 case HomeAddressPostalCode: 00292 addrHome.setPostalCode( value ); 00293 break; 00294 case HomeAddressCountry: 00295 addrHome.setCountry( value ); 00296 break; 00297 case HomeAddressLabel: 00298 addrHome.setLabel( value ); 00299 break; 00300 00301 case BusinessAddressStreet: 00302 addrWork.setStreet( value ); 00303 break; 00304 case BusinessAddressLocality: 00305 addrWork.setLocality( value ); 00306 break; 00307 case BusinessAddressRegion: 00308 addrWork.setRegion( value ); 00309 break; 00310 case BusinessAddressPostalCode: 00311 addrWork.setPostalCode( value ); 00312 break; 00313 case BusinessAddressCountry: 00314 addrWork.setCountry( value ); 00315 break; 00316 case BusinessAddressLabel: 00317 addrWork.setLabel( value ); 00318 break; 00319 default: 00320 KABC::Field::List fields = mAddressBook->fields( KABC::Field::CustomCategory ); 00321 KABC::Field::List::Iterator it; 00322 00323 int counter = 0; 00324 for ( it = fields.begin(); it != fields.end(); ++it ) { 00325 if ( counter == (int)( posToType( item->currentItem() ) - mCustomCounter ) ) { 00326 (*it)->setValue( a, value ); 00327 continue; 00328 } 00329 ++counter; 00330 } 00331 break; 00332 } 00333 } 00334 00335 kapp->processEvents(); 00336 00337 if ( progressDialog.wasCancelled() ) 00338 return KABC::AddresseeList(); 00339 00340 progressDialog.progressBar()->advance( 1 ); 00341 00342 if ( !addrHome.isEmpty() ) 00343 a.insertAddress( addrHome ); 00344 if ( !addrWork.isEmpty() ) 00345 a.insertAddress( addrWork ); 00346 00347 if ( !emptyRow && !a.isEmpty() ) 00348 contacts.append( a ); 00349 } 00350 00351 return contacts; 00352 } 00353 00354 void CSVImportDialog::initGUI() 00355 { 00356 mPage = plainPage(); 00357 00358 QGridLayout *layout = new QGridLayout( mPage, 1, 1, marginHint(), 00359 spacingHint() ); 00360 QHBoxLayout *hbox = new QHBoxLayout(); 00361 hbox->setSpacing( spacingHint() ); 00362 00363 QLabel *label = new QLabel( i18n( "File to import:" ), mPage ); 00364 hbox->addWidget( label ); 00365 00366 mUrlRequester = new KURLRequester( mPage ); 00367 mUrlRequester->setFilter( "*.csv" ); 00368 hbox->addWidget( mUrlRequester ); 00369 00370 layout->addMultiCellLayout( hbox, 0, 0, 0, 4 ); 00371 00372 // Delimiter: comma, semicolon, tab, space, other 00373 mDelimiterBox = new QButtonGroup( i18n( "Delimiter" ), mPage ); 00374 mDelimiterBox->setColumnLayout( 0, Qt::Vertical ); 00375 mDelimiterBox->layout()->setSpacing( spacingHint() ); 00376 mDelimiterBox->layout()->setMargin( marginHint() ); 00377 QGridLayout *delimiterLayout = new QGridLayout( mDelimiterBox->layout() ); 00378 delimiterLayout->setAlignment( Qt::AlignTop ); 00379 layout->addMultiCellWidget( mDelimiterBox, 1, 3, 0, 0 ); 00380 00381 mRadioComma = new QRadioButton( i18n( "Comma" ), mDelimiterBox ); 00382 mRadioComma->setChecked( true ); 00383 delimiterLayout->addWidget( mRadioComma, 0, 0 ); 00384 00385 mRadioSemicolon = new QRadioButton( i18n( "Semicolon" ), mDelimiterBox ); 00386 delimiterLayout->addWidget( mRadioSemicolon, 0, 1 ); 00387 00388 mRadioTab = new QRadioButton( i18n( "Tabulator" ), mDelimiterBox ); 00389 delimiterLayout->addWidget( mRadioTab, 1, 0 ); 00390 00391 mRadioSpace = new QRadioButton( i18n( "Space" ), mDelimiterBox ); 00392 delimiterLayout->addWidget( mRadioSpace, 1, 1 ); 00393 00394 mRadioOther = new QRadioButton( i18n( "Other" ), mDelimiterBox ); 00395 delimiterLayout->addWidget( mRadioOther, 0, 2 ); 00396 00397 mDelimiterEdit = new QLineEdit( mDelimiterBox ); 00398 delimiterLayout->addWidget( mDelimiterEdit, 1, 2 ); 00399 00400 mComboLine = new QComboBox( false, mPage ); 00401 mComboLine->insertItem( i18n( "1" ) ); 00402 layout->addWidget( mComboLine, 2, 3 ); 00403 00404 mComboQuote = new QComboBox( false, mPage ); 00405 mComboQuote->insertItem( i18n( "\"" ), 0 ); 00406 mComboQuote->insertItem( i18n( "'" ), 1 ); 00407 mComboQuote->insertItem( i18n( "None" ), 2 ); 00408 layout->addWidget( mComboQuote, 2, 2 ); 00409 00410 mDatePatternEdit = new QLineEdit( mPage ); 00411 mDatePatternEdit->setText( "Y-M-D" ); // ISO 8601 format as default 00412 QToolTip::add( mDatePatternEdit, i18n( "<ul><li>y: year with 2 digits</li>" 00413 "<li>Y: year with 4 digits</li>" 00414 "<li>m: month with 1 or 2 digits</li>" 00415 "<li>M: month with 2 digits</li>" 00416 "<li>d: day with 1 or 2 digits</li>" 00417 "<li>D: day with 2 digits</li></ul>" ) ); 00418 layout->addWidget( mDatePatternEdit, 2, 4 ); 00419 00420 label = new QLabel( i18n( "Start at line:" ), mPage ); 00421 layout->addWidget( label, 1, 3 ); 00422 00423 label = new QLabel( i18n( "Textquote:" ), mPage ); 00424 layout->addWidget( label, 1, 2 ); 00425 00426 label = new QLabel( i18n( "Date format:" ), mPage ); 00427 layout->addWidget( label, 1, 4 ); 00428 00429 mIgnoreDuplicates = new QCheckBox( mPage ); 00430 mIgnoreDuplicates->setText( i18n( "Ignore duplicate delimiters" ) ); 00431 layout->addMultiCellWidget( mIgnoreDuplicates, 3, 3, 2, 4 ); 00432 00433 mTable = new QTable( 0, 0, mPage ); 00434 mTable->setSelectionMode( QTable::NoSelection ); 00435 mTable->horizontalHeader()->hide(); 00436 layout->addMultiCellWidget( mTable, 4, 4, 0, 4 ); 00437 00438 setButtonText( User1, i18n( "Apply Template" ) ); 00439 setButtonText( User2, i18n( "Save Template" ) ); 00440 00441 enableButtonOK( false ); 00442 actionButton( User1 )->setEnabled( false ); 00443 actionButton( User2 )->setEnabled( false ); 00444 00445 resize( 400, 300 ); 00446 } 00447 00448 void CSVImportDialog::fillTable() 00449 { 00450 int row, column; 00451 bool lastCharDelimiter = false; 00452 bool ignoreDups = mIgnoreDuplicates->isChecked(); 00453 enum { S_START, S_QUOTED_FIELD, S_MAYBE_END_OF_QUOTED_FIELD, S_END_OF_QUOTED_FIELD, 00454 S_MAYBE_NORMAL_FIELD, S_NORMAL_FIELD } state = S_START; 00455 00456 QChar x; 00457 QString field; 00458 00459 // store previous assignment 00460 mTypeStore.clear(); 00461 for ( column = 0; column < mTable->numCols(); ++column ) { 00462 QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, 00463 column ) ); 00464 if ( !item || mClearTypeStore ) 00465 mTypeStore.append( typeToPos( Undefined ) ); 00466 else if ( item ) 00467 mTypeStore.append( item->currentItem() ); 00468 } 00469 00470 clearTable(); 00471 00472 row = column = 1; 00473 mData = QString( mFileArray ); 00474 00475 QTextStream inputStream( mData, IO_ReadOnly ); 00476 inputStream.setEncoding( QTextStream::Locale ); 00477 00478 int maxColumn = 0; 00479 while ( !inputStream.atEnd() ) { 00480 inputStream >> x; // read one char 00481 00482 if ( x == '\r' ) inputStream >> x; // eat '\r', to handle DOS/LOSEDOWS files correctly 00483 00484 switch ( state ) { 00485 case S_START : 00486 if ( x == mTextQuote ) { 00487 state = S_QUOTED_FIELD; 00488 } else if ( x == mDelimiter ) { 00489 if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) 00490 ++column; 00491 lastCharDelimiter = true; 00492 } else if ( x == '\n' ) { 00493 ++row; 00494 column = 1; 00495 } else { 00496 field += x; 00497 state = S_MAYBE_NORMAL_FIELD; 00498 } 00499 break; 00500 case S_QUOTED_FIELD : 00501 if ( x == mTextQuote ) { 00502 state = S_MAYBE_END_OF_QUOTED_FIELD; 00503 } else if ( x == '\n' ) { 00504 setText( row - mStartLine + 1, column, field ); 00505 field = ""; 00506 if ( x == '\n' ) { 00507 ++row; 00508 column = 1; 00509 } else { 00510 if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) 00511 ++column; 00512 lastCharDelimiter = true; 00513 } 00514 state = S_START; 00515 } else { 00516 field += x; 00517 } 00518 break; 00519 case S_MAYBE_END_OF_QUOTED_FIELD : 00520 if ( x == mTextQuote ) { 00521 field += x; 00522 state = S_QUOTED_FIELD; 00523 } else if ( x == mDelimiter || x == '\n' ) { 00524 setText( row - mStartLine + 1, column, field ); 00525 field = ""; 00526 if ( x == '\n' ) { 00527 ++row; 00528 column = 1; 00529 } else { 00530 if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) 00531 ++column; 00532 lastCharDelimiter = true; 00533 } 00534 state = S_START; 00535 } else { 00536 state = S_END_OF_QUOTED_FIELD; 00537 } 00538 break; 00539 case S_END_OF_QUOTED_FIELD : 00540 if ( x == mDelimiter || x == '\n' ) { 00541 setText( row - mStartLine + 1, column, field ); 00542 field = ""; 00543 if ( x == '\n' ) { 00544 ++row; 00545 column = 1; 00546 } else { 00547 if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) 00548 ++column; 00549 lastCharDelimiter = true; 00550 } 00551 state = S_START; 00552 } else { 00553 state = S_END_OF_QUOTED_FIELD; 00554 } 00555 break; 00556 case S_MAYBE_NORMAL_FIELD : 00557 if ( x == mTextQuote ) { 00558 field = ""; 00559 state = S_QUOTED_FIELD; 00560 break; 00561 } 00562 case S_NORMAL_FIELD : 00563 if ( x == mDelimiter || x == '\n' ) { 00564 setText( row - mStartLine + 1, column, field ); 00565 field = ""; 00566 if ( x == '\n' ) { 00567 ++row; 00568 column = 1; 00569 } else { 00570 if ( ( ignoreDups == false ) || ( lastCharDelimiter == false ) ) 00571 ++column; 00572 lastCharDelimiter = true; 00573 } 00574 state = S_START; 00575 } else { 00576 field += x; 00577 } 00578 } 00579 if ( x != mDelimiter ) 00580 lastCharDelimiter = false; 00581 00582 if ( column > maxColumn ) 00583 maxColumn = column; 00584 } 00585 00586 // file with only one line without '\n' 00587 if ( field.length() > 0 ) { 00588 setText( row - mStartLine + 1, column, field ); 00589 ++row; 00590 field = ""; 00591 } 00592 00593 adjustRows( row - mStartLine ); 00594 mTable->setNumCols( maxColumn ); 00595 00596 for ( column = 0; column < mTable->numCols(); ++column ) { 00597 QComboTableItem *item = new QComboTableItem( mTable, mTypeMap.keys() ); 00598 mTable->setItem( 0, column, item ); 00599 if ( column < (int)mTypeStore.count() ) 00600 item->setCurrentItem( mTypeStore[ column ] ); 00601 else 00602 item->setCurrentItem( typeToPos( Undefined ) ); 00603 mTable->adjustColumn( column ); 00604 } 00605 } 00606 00607 void CSVImportDialog::clearTable() 00608 { 00609 for ( int row = 0; row < mTable->numRows(); ++row ) 00610 for ( int column = 0; column < mTable->numCols(); ++column ) 00611 mTable->clearCell( row, column ); 00612 } 00613 00614 void CSVImportDialog::fillComboBox() 00615 { 00616 mComboLine->clear(); 00617 for ( int row = 1; row < mTable->numRows() + 1; ++row ) 00618 mComboLine->insertItem( QString::number( row ), row - 1 ); 00619 } 00620 00621 void CSVImportDialog::setText( int row, int col, const QString& text ) 00622 { 00623 if ( row < 1 ) // skipped by the user 00624 return; 00625 00626 if ( mTable->numRows() < row ) { 00627 mTable->setNumRows( row + 5000 ); // We add 5000 at a time to limit recalculations 00628 mAdjustRows = true; 00629 } 00630 00631 if ( mTable->numCols() < col ) 00632 mTable->setNumCols( col + 50 ); // We add 50 at a time to limit recalculation 00633 00634 mTable->setText( row - 1, col - 1, text ); 00635 } 00636 00637 /* 00638 * Called after the first fillTable() when number of rows are unknown. 00639 */ 00640 void CSVImportDialog::adjustRows( int rows ) 00641 { 00642 if ( mAdjustRows ) { 00643 mTable->setNumRows( rows ); 00644 mAdjustRows = false; 00645 } 00646 } 00647 00648 void CSVImportDialog::returnPressed() 00649 { 00650 if ( mDelimiterBox->id( mDelimiterBox->selected() ) != 4 ) 00651 return; 00652 00653 mDelimiter = mDelimiterEdit->text(); 00654 fillTable(); 00655 } 00656 00657 void CSVImportDialog::textChanged ( const QString& ) 00658 { 00659 mRadioOther->setChecked ( true ); 00660 delimiterClicked( 4 ); // other 00661 } 00662 00663 void CSVImportDialog::delimiterClicked( int id ) 00664 { 00665 switch ( id ) { 00666 case 0: // comma 00667 mDelimiter = ","; 00668 break; 00669 case 4: // other 00670 mDelimiter = mDelimiterEdit->text(); 00671 break; 00672 case 2: // tab 00673 mDelimiter = "\t"; 00674 break; 00675 case 3: // space 00676 mDelimiter = " "; 00677 break; 00678 case 1: // semicolon 00679 mDelimiter = ";"; 00680 break; 00681 } 00682 00683 fillTable(); 00684 } 00685 00686 void CSVImportDialog::textquoteSelected( const QString& mark ) 00687 { 00688 if ( mComboQuote->currentItem() == 2 ) 00689 mTextQuote = 0; 00690 else 00691 mTextQuote = mark[ 0 ]; 00692 00693 fillTable(); 00694 } 00695 00696 void CSVImportDialog::lineSelected( const QString& line ) 00697 { 00698 mStartLine = line.toInt() - 1; 00699 fillTable(); 00700 } 00701 00702 void CSVImportDialog::slotOk() 00703 { 00704 bool assigned = false; 00705 00706 for ( int column = 0; column < mTable->numCols(); ++column ) { 00707 QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, 00708 column ) ); 00709 if ( item && posToType( item->currentItem() ) != Undefined ) 00710 assigned = true; 00711 } 00712 00713 if ( assigned ) 00714 KDialogBase::slotOk(); 00715 else 00716 KMessageBox::sorry( this, i18n( "You have to assign at least one column." ) ); 00717 } 00718 00719 void CSVImportDialog::applyTemplate() 00720 { 00721 QMap<uint,int> columnMap; 00722 QMap<QString, QString> fileMap; 00723 QStringList templates; 00724 00725 // load all template files 00726 QStringList list = KGlobal::dirs()->findAllResources( "data" , QString( kapp->name() ) + 00727 "/csv-templates/*.desktop", true, true ); 00728 00729 for ( QStringList::iterator it = list.begin(); it != list.end(); ++it ) 00730 { 00731 KSimpleConfig config( *it, true ); 00732 00733 if ( !config.hasGroup( "csv column map" ) ) 00734 continue; 00735 00736 config.setGroup( "Misc" ); 00737 templates.append( config.readEntry( "Name" ) ); 00738 fileMap.insert( config.readEntry( "Name" ), *it ); 00739 } 00740 00741 // let the user chose, what to take 00742 bool ok = false; 00743 QString tmp; 00744 tmp = KInputDialog::getItem( i18n( "Template Selection" ), 00745 i18n( "Please select a template, that matches the CSV file:" ), 00746 templates, 0, false, &ok, this ); 00747 00748 if ( !ok ) 00749 return; 00750 00751 KSimpleConfig config( fileMap[ tmp ], true ); 00752 config.setGroup( "General" ); 00753 mDatePatternEdit->setText( config.readEntry( "DatePattern", "Y-M-D" ) ); 00754 uint numColumns = config.readUnsignedNumEntry( "Columns" ); 00755 mDelimiterEdit->setText( config.readEntry( "DelimiterOther" ) ); 00756 mDelimiterBox->setButton( config.readNumEntry( "DelimiterType" ) ); 00757 delimiterClicked( config.readNumEntry( "DelimiterType" ) ); 00758 int quoteType = config.readNumEntry( "QuoteType" ); 00759 mComboQuote->setCurrentItem( quoteType ); 00760 textquoteSelected( mComboQuote->currentText() ); 00761 00762 // create the column map 00763 config.setGroup( "csv column map" ); 00764 for ( uint i = 0; i < numColumns; ++i ) { 00765 int col = config.readNumEntry( QString::number( i ) ); 00766 columnMap.insert( i, col ); 00767 } 00768 00769 // apply the column map 00770 for ( uint column = 0; column < columnMap.count(); ++column ) { 00771 int type = columnMap[ column ]; 00772 QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, 00773 column ) ); 00774 if ( item ) 00775 item->setCurrentItem( typeToPos( type ) ); 00776 } 00777 } 00778 00779 void CSVImportDialog::saveTemplate() 00780 { 00781 QString fileName = KFileDialog::getSaveFileName( 00782 locateLocal( "data", QString( kapp->name() ) + "/csv-templates/" ), 00783 "*.desktop", this ); 00784 00785 if ( fileName.isEmpty() ) 00786 return; 00787 00788 if ( !fileName.contains( ".desktop" ) ) 00789 fileName += ".desktop"; 00790 00791 QString name = KInputDialog::getText( i18n( "Template Name" ), i18n( "Please enter a name for the template:" ) ); 00792 00793 if ( name.isEmpty() ) 00794 return; 00795 00796 KConfig config( fileName ); 00797 config.setGroup( "General" ); 00798 config.writeEntry( "DatePattern", mDatePatternEdit->text() ); 00799 config.writeEntry( "Columns", mTable->numCols() ); 00800 config.writeEntry( "DelimiterType", mDelimiterBox->id( mDelimiterBox->selected() ) ); 00801 config.writeEntry( "DelimiterOther", mDelimiterEdit->text() ); 00802 config.writeEntry( "QuoteType", mComboQuote->currentItem() ); 00803 00804 config.setGroup( "Misc" ); 00805 config.writeEntry( "Name", name ); 00806 00807 config.setGroup( "csv column map" ); 00808 00809 for ( int column = 0; column < mTable->numCols(); ++column ) { 00810 QComboTableItem *item = static_cast<QComboTableItem*>( mTable->item( 0, 00811 column ) ); 00812 if ( item ) 00813 config.writeEntry( QString::number( column ), posToType( 00814 item->currentItem() ) ); 00815 else 00816 config.writeEntry( QString::number( column ), 0 ); 00817 } 00818 00819 config.sync(); 00820 } 00821 00822 QString CSVImportDialog::getText( int row, int col ) 00823 { 00824 return mTable->text( row, col ); 00825 } 00826 00827 uint CSVImportDialog::posToType( int pos ) const 00828 { 00829 uint counter = 0; 00830 QMap<QString, uint>::ConstIterator it; 00831 for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it, ++counter ) 00832 if ( counter == (uint)pos ) 00833 return it.data(); 00834 00835 return 0; 00836 } 00837 00838 int CSVImportDialog::typeToPos( uint type ) const 00839 { 00840 uint counter = 0; 00841 QMap<QString, uint>::ConstIterator it; 00842 for ( it = mTypeMap.begin(); it != mTypeMap.end(); ++it, ++counter ) 00843 if ( it.data() == type ) 00844 return counter; 00845 00846 return -1; 00847 } 00848 00849 void CSVImportDialog::ignoreDuplicatesChanged( int ) 00850 { 00851 fillTable(); 00852 } 00853 00854 void CSVImportDialog::setFile( const QString &fileName ) 00855 { 00856 if ( fileName.isEmpty() ) 00857 return; 00858 00859 QFile file( fileName ); 00860 if ( !file.open( IO_ReadOnly ) ) { 00861 KMessageBox::sorry( this, i18n( "Cannot open input file!" ) ); 00862 file.close(); 00863 return; 00864 } 00865 00866 mFileArray = file.readAll(); 00867 file.close(); 00868 00869 mClearTypeStore = true; 00870 clearTable(); 00871 mTable->setNumCols( 0 ); 00872 mTable->setNumRows( 0 ); 00873 fillTable(); 00874 mClearTypeStore = false; 00875 00876 fillComboBox(); 00877 } 00878 00879 void CSVImportDialog::urlChanged( const QString &file ) 00880 { 00881 bool state = !file.isEmpty(); 00882 00883 enableButtonOK( state ); 00884 actionButton( User1 )->setEnabled( state ); 00885 actionButton( User2 )->setEnabled( state ); 00886 } 00887 00888 #include <csvimportdialog.moc>
KDE Logo
This file is part of the documentation for kaddressbook Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:58:08 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003