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