00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 static const char *addresswidget_id =
00032 "$Id: addressWidget.cc 450284 2005-08-17 20:49:09Z adridg $";
00033
00034
00035
00036 #ifndef _KPILOT_OPTIONS_H
00037 #include "options.h"
00038 #endif
00039
00040 #include <iostream>
00041 #include <cstring>
00042 #include <cstdlib>
00043
00044 #include <qptrlist.h>
00045 #include <qlistbox.h>
00046 #include <qfile.h>
00047 #include <qpushbutton.h>
00048 #include <qtextstream.h>
00049 #include <qlayout.h>
00050 #include <qlabel.h>
00051 #include <qmultilineedit.h>
00052 #include <qcombobox.h>
00053 #include <qwhatsthis.h>
00054 #include <qtextview.h>
00055 #include <qtextcodec.h>
00056 #include <qregexp.h>
00057
00058 #include <kapplication.h>
00059 #include <kmessagebox.h>
00060 #include <kdebug.h>
00061 #include <kfiledialog.h>
00062
00063 #include "kpilotConfig.h"
00064 #include "listItems.h"
00065 #include "addressEditor.h"
00066 #include "pilotLocalDatabase.h"
00067
00068 #include "addressWidget.moc"
00069
00070
00071 AddressWidget::AddressWidget(QWidget * parent,
00072 const QString & path) :
00073 PilotComponent(parent, "component_address", path),
00074 fAddrInfo(0L),
00075 fAddressAppInfo(0L),
00076 fPendingAddresses(0)
00077 {
00078 FUNCTIONSETUP;
00079
00080 setupWidget();
00081 fAddressList.setAutoDelete(true);
00082
00083
00084 (void) addresswidget_id;
00085 }
00086
00087 AddressWidget::~AddressWidget()
00088 {
00089 FUNCTIONSETUP;
00090 }
00091
00092 int AddressWidget::getAllAddresses(PilotDatabase * addressDB)
00093 {
00094 FUNCTIONSETUP;
00095
00096 int currentRecord = 0;
00097 PilotRecord *pilotRec;
00098 PilotAddress *address;
00099
00100
00101 #ifdef DEBUG
00102 DEBUGKPILOT << fname << ": Reading AddressDB..." << endl;
00103 #endif
00104
00105 while ((pilotRec = addressDB->readRecordByIndex(currentRecord)) != 0L)
00106 {
00107 if (!(pilotRec->isDeleted()) &&
00108 (!(pilotRec->isSecret()) || KPilotSettings::showSecrets()))
00109 {
00110 address = new PilotAddress(fAddressAppInfo, pilotRec);
00111 if (address == 0L)
00112 {
00113 kdWarning() << k_funcinfo
00114 << ": Couldn't allocate record "
00115 << currentRecord++
00116 << endl;
00117 break;
00118 }
00119 fAddressList.append(address);
00120 }
00121 delete pilotRec;
00122
00123 currentRecord++;
00124 }
00125
00126 #ifdef DEBUG
00127 DEBUGKPILOT << fname
00128 << ": Total " << currentRecord << " records" << endl;
00129 #endif
00130
00131 return currentRecord;
00132 }
00133
00134 void AddressWidget::showComponent()
00135 {
00136 FUNCTIONSETUP;
00137 if ( fPendingAddresses>0 ) return;
00138
00139 #ifdef DEBUG
00140 DEBUGKPILOT << fname
00141 << ": Reading from directory " << dbPath() << endl;
00142 #endif
00143
00144 PilotDatabase *addressDB =
00145 new PilotLocalDatabase(dbPath(), CSL1("AddressDB"));
00146
00147 fAddressList.clear();
00148
00149 if (addressDB->isDBOpen())
00150 {
00151 KPILOT_DELETE(fAddressAppInfo);
00152 fAddressAppInfo = new PilotAddressInfo(addressDB);
00153 populateCategories(fCatList, fAddressAppInfo->categoryInfo());
00154 getAllAddresses(addressDB);
00155
00156 }
00157 else
00158 {
00159 populateCategories(fCatList, 0L);
00160 kdWarning() << k_funcinfo
00161 << ": Could not open local AddressDB" << endl;
00162 }
00163
00164 KPILOT_DELETE( addressDB );
00165
00166 updateWidget();
00167 }
00168
00169 void AddressWidget::hideComponent()
00170 {
00171 FUNCTIONSETUP;
00172 if (fPendingAddresses==0 )
00173 {
00174 fAddressList.clear();
00175 fListBox->clear();
00176
00177 updateWidget();
00178 }
00179 }
00180
00181 bool AddressWidget::preHotSync(QString &s)
00182 {
00183 FUNCTIONSETUP;
00184
00185 if ( fPendingAddresses )
00186 {
00187 #ifdef DEBUG
00188 DEBUGKPILOT << fname
00189 << ": fPendingAddress="
00190 << fPendingAddresses
00191 << endl;
00192 #endif
00193
00194 #if KDE_VERSION<220
00195 s = i18n("There are still %1 address editing windows open.")
00196 .arg(QString::number(fPendingAddresses));
00197 #else
00198 s = i18n("There is still an address editing window open.",
00199 "There are still %n address editing windows open.",
00200 fPendingAddresses);
00201 #endif
00202 return false;
00203 }
00204
00205 return true;
00206 }
00207
00208 void AddressWidget::postHotSync()
00209 {
00210 FUNCTIONSETUP;
00211
00212 if ( shown )
00213 {
00214 fAddressList.clear();
00215 showComponent();
00216 }
00217 }
00218
00219
00220 void AddressWidget::setupWidget()
00221 {
00222 FUNCTIONSETUP;
00223
00224 QLabel *label;
00225 QGridLayout *grid = new QGridLayout(this, 6, 4, SPACING);
00226
00227 fCatList = new QComboBox(this);
00228 grid->addWidget(fCatList, 0, 1);
00229 connect(fCatList, SIGNAL(activated(int)),
00230 this, SLOT(slotSetCategory(int)));
00231 QWhatsThis::add(fCatList,
00232 i18n("<qt>Select the category of addresses to display here.</qt>"));
00233
00234 label = new QLabel(i18n("Category:"), this);
00235 label->setBuddy(fCatList);
00236 grid->addWidget(label, 0, 0);
00237
00238 fListBox = new QListBox(this);
00239 grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
00240 connect(fListBox, SIGNAL(highlighted(int)),
00241 this, SLOT(slotShowAddress(int)));
00242 connect(fListBox, SIGNAL(selected(int)),
00243 this, SLOT(slotEditRecord()));
00244 QWhatsThis::add(fListBox,
00245 i18n("<qt>This list displays all the addresses "
00246 "in the selected category. Click on "
00247 "one to display it to the right.</qt>"));
00248
00249 label = new QLabel(i18n("Address info:"), this);
00250 grid->addWidget(label, 0, 2);
00251
00252
00253 fAddrInfo = new QTextView(this);
00254 grid->addMultiCellWidget(fAddrInfo, 1, 4, 2, 2);
00255
00256 QPushButton *button;
00257 QString wt;
00258
00259 fEditButton = new QPushButton(i18n("Edit Record..."), this);
00260 grid->addWidget(fEditButton, 2, 0);
00261 connect(fEditButton, SIGNAL(clicked()), this, SLOT(slotEditRecord()));
00262 wt = KPilotSettings::internalEditors() ?
00263 i18n("<qt>You can edit an address when it is selected.</qt>") :
00264 i18n("<qt><i>Editing is disabled by the 'internal editors' setting.</i></qt>");
00265 QWhatsThis::add(fEditButton,wt);
00266
00267 button = new QPushButton(i18n("New Record..."), this);
00268 grid->addWidget(button, 2, 1);
00269 connect(button, SIGNAL(clicked()), this, SLOT(slotCreateNewRecord()));
00270 wt = KPilotSettings::internalEditors() ?
00271 i18n("<qt>Add a new address to the address book.</qt>") :
00272 i18n("<qt><i>Adding is disabled by the 'internal editors' setting.</i></qt>") ;
00273 QWhatsThis::add(button, wt);
00274 button->setEnabled(KPilotSettings::internalEditors());
00275
00276
00277 fDeleteButton = new QPushButton(i18n("Delete Record"), this);
00278 grid->addWidget(fDeleteButton, 3, 0);
00279 connect(fDeleteButton, SIGNAL(clicked()),
00280 this, SLOT(slotDeleteRecord()));
00281 wt = KPilotSettings::internalEditors() ?
00282 i18n("<qt>Delete the selected address from the address book.</qt>") :
00283 i18n("<qt><i>Deleting is disabled by the 'internal editors' setting.</i></qt>") ;
00284
00285 button = new QPushButton(TODO_I18N("Export..."), this);
00286 grid->addWidget(button, 3,1);
00287 connect(button, SIGNAL(clicked()), this, SLOT(slotExport()));
00288 QWhatsThis::add(button,
00289 TODO_I18N("<qt>Export all addresses in the selected category to CSV format.</qt>") );
00290
00291 QWhatsThis::add(fDeleteButton,wt);
00292 }
00293
00294 void AddressWidget::updateWidget()
00295 {
00296 FUNCTIONSETUP;
00297
00298 if( !fAddressAppInfo )
00299 return;
00300 int addressDisplayMode = KPilotSettings::addressDisplayMode();
00301
00302 int listIndex = 0;
00303
00304 #ifdef DEBUG
00305 DEBUGKPILOT << fname
00306 << ": Display Mode=" << addressDisplayMode << endl;
00307 #endif
00308
00309 int currentCatID = findSelectedCategory(fCatList,
00310 fAddressAppInfo->categoryInfo());
00311
00312 fListBox->clear();
00313 fAddressList.first();
00314
00315 #ifdef DEBUG
00316 DEBUGKPILOT << fname << ": Adding records..." << endl;
00317 #endif
00318
00319 while (fAddressList.current())
00320 {
00321 if ((currentCatID == -1) ||
00322 (fAddressList.current()->category() == currentCatID))
00323 {
00324 QString title = createTitle(fAddressList.current(),
00325 addressDisplayMode);
00326
00327 if (!title.isEmpty())
00328 {
00329 title.remove(QRegExp(CSL1("\n.*")));
00330 PilotListItem *p = new PilotListItem(title,
00331 listIndex,
00332 fAddressList.current());
00333
00334 fListBox->insertItem(p);
00335 }
00336 }
00337 listIndex++;
00338 fAddressList.next();
00339 }
00340
00341 fListBox->sort();
00342 #ifdef DEBUG
00343 DEBUGKPILOT << fname << ": " << listIndex << " records" << endl;
00344 #endif
00345
00346 slotUpdateButtons();
00347 }
00348
00349
00350
00351 QString AddressWidget::createTitle(PilotAddress * address, int displayMode)
00352 {
00353
00354
00355 QString title;
00356
00357 switch (displayMode)
00358 {
00359 case 1:
00360 if (!address->getField(entryCompany).isEmpty())
00361 {
00362 title.append(address->getField(entryCompany));
00363 }
00364 if (!address->getField(entryLastname).isEmpty())
00365 {
00366 if (!title.isEmpty())
00367 {
00368 title.append( CSL1(", "));
00369 }
00370
00371 title.append(address->getField(entryLastname));
00372 }
00373 break;
00374 case 0:
00375 default:
00376 if (!address->getField(entryLastname).isEmpty())
00377 {
00378 title.append(address->getField(entryLastname));
00379 }
00380
00381 if (!address->getField(entryFirstname).isEmpty())
00382 {
00383 if (!title.isEmpty())
00384 {
00385 title.append( CSL1(", "));
00386 }
00387 title.append(address->getField(entryFirstname));
00388 }
00389 break;
00390 }
00391
00392 if (title.isEmpty())
00393 {
00394 if (!fAddressList.current()->getField(entryCompany).isEmpty())
00395 {
00396 title.append(fAddressList.current()->
00397 getField(entryCompany));
00398 }
00399 if (title.isEmpty())
00400 {
00401 title = i18n("[unknown]");
00402 }
00403 }
00404
00405 return title;
00406 }
00407
00408
00409 void AddressWidget::slotUpdateButtons()
00410 {
00411 FUNCTIONSETUP;
00412
00413 bool enabled = (fListBox->currentItem() != -1);
00414
00415 enabled &= KPilotSettings::internalEditors();
00416 fEditButton->setEnabled(enabled);
00417 fDeleteButton->setEnabled(enabled);
00418 }
00419
00420 void AddressWidget::slotSetCategory(int)
00421 {
00422 FUNCTIONSETUP;
00423
00424 updateWidget();
00425 }
00426
00427 void AddressWidget::slotEditRecord()
00428 {
00429 FUNCTIONSETUP;
00430 if ( !shown ) return;
00431
00432 int item = fListBox->currentItem();
00433
00434 if (item == -1)
00435 return;
00436
00437 PilotListItem *p = (PilotListItem *) fListBox->item(item);
00438 PilotAddress *selectedRecord = (PilotAddress *) p->rec();
00439
00440 if (selectedRecord->id() == 0)
00441 {
00442 KMessageBox::error(0L,
00443 i18n("Cannot edit new records until "
00444 "HotSynced with Pilot."),
00445 i18n("HotSync Required"));
00446 return;
00447 }
00448
00449 AddressEditor *editor = new AddressEditor(selectedRecord,
00450 fAddressAppInfo->info(), this);
00451
00452 connect(editor, SIGNAL(recordChangeComplete(PilotAddress *)),
00453 this, SLOT(slotUpdateRecord(PilotAddress *)));
00454 connect(editor, SIGNAL(cancelClicked()),
00455 this, SLOT(slotEditCancelled()));
00456 editor->show();
00457
00458 fPendingAddresses++;
00459 }
00460
00461 void AddressWidget::slotCreateNewRecord()
00462 {
00463 FUNCTIONSETUP;
00464 if ( !shown ) return;
00465
00466
00467
00468
00469
00470
00471 PilotDatabase *myDB = new PilotLocalDatabase(dbPath(), CSL1("AddressDB"));
00472
00473 if (!myDB || !myDB->isDBOpen())
00474 {
00475 #ifdef DEBUG
00476 DEBUGKPILOT << fname
00477 << ": Tried to open "
00478 << dbPath()
00479 << "/AddressDB"
00480 << " and got pointer @"
00481 << (long) myDB
00482 << " with status "
00483 << ( myDB ? myDB->isDBOpen() : false )
00484 << endl;
00485 #endif
00486
00487 KMessageBox::sorry(this,
00488 i18n("You cannot add addresses to the address book "
00489 "until you have done a HotSync at least once "
00490 "to retrieve the database layout from your Pilot."),
00491 i18n("Cannot Add New Address"));
00492
00493 if (myDB)
00494 KPILOT_DELETE( myDB );
00495
00496 return;
00497 }
00498
00499 AddressEditor *editor = new AddressEditor(0L,
00500 fAddressAppInfo->info(), this);
00501
00502 connect(editor, SIGNAL(recordChangeComplete(PilotAddress *)),
00503 this, SLOT(slotAddRecord(PilotAddress *)));
00504 connect(editor, SIGNAL(cancelClicked()),
00505 this, SLOT(slotEditCancelled()));
00506 editor->show();
00507
00508 fPendingAddresses++;
00509 }
00510
00511 void AddressWidget::slotAddRecord(PilotAddress * address)
00512 {
00513 FUNCTIONSETUP;
00514 if ( !shown && fPendingAddresses==0 ) return;
00515
00516 int currentCatID = findSelectedCategory(fCatList,
00517 fAddressAppInfo->categoryInfo(), true);
00518
00519
00520 address->PilotAppCategory::setCategory(currentCatID);
00521 fAddressList.append(address);
00522 writeAddress(address);
00523
00524 updateWidget();
00525
00526
00527
00528
00529 int k = fListBox->count() - 1;
00530
00531 fListBox->setCurrentItem(k);
00532 fListBox->setBottomItem(k);
00533
00534 fPendingAddresses--;
00535 if ( !shown && fPendingAddresses==0 ) hideComponent();
00536 }
00537
00538 void AddressWidget::slotUpdateRecord(PilotAddress * address)
00539 {
00540 FUNCTIONSETUP;
00541 if ( !shown && fPendingAddresses==0 ) return;
00542
00543 writeAddress(address);
00544 int currentRecord = fListBox->currentItem();
00545
00546
00547 updateWidget();
00548 fListBox->setCurrentItem(currentRecord);
00549
00550 emit(recordChanged(address));
00551
00552 fPendingAddresses--;
00553 if ( !shown && fPendingAddresses==0 ) hideComponent();
00554 }
00555
00556 void AddressWidget::slotEditCancelled()
00557 {
00558 FUNCTIONSETUP;
00559
00560 fPendingAddresses--;
00561 if ( !shown && fPendingAddresses==0 ) hideComponent();
00562 }
00563
00564 void AddressWidget::slotDeleteRecord()
00565 {
00566 FUNCTIONSETUP;
00567 if ( !shown ) return;
00568
00569 int item = fListBox->currentItem();
00570
00571 if (item == -1)
00572 return;
00573
00574 PilotListItem *p = (PilotListItem *) fListBox->item(item);
00575 PilotAddress *selectedRecord = (PilotAddress *) p->rec();
00576
00577 if (selectedRecord->id() == 0)
00578 {
00579 KMessageBox::error(this,
00580 i18n("New records cannot be deleted until "
00581 "HotSynced with pilot."),
00582 i18n("HotSync Required"));
00583 return;
00584 }
00585
00586 if (KMessageBox::questionYesNo(this,
00587 i18n("Delete currently selected record?"),
00588 i18n("Delete Record?"), KStdGuiItem::del(), KStdGuiItem::cancel()) == KMessageBox::No)
00589 return;
00590
00591 selectedRecord->setDeleted( true );
00592 writeAddress(selectedRecord);
00593 emit(recordChanged(selectedRecord));
00594 showComponent();
00595 }
00596
00597
00598
00599 void AddressWidget::slotShowAddress(int which)
00600 {
00601 FUNCTIONSETUP;
00602 if (!shown) return;
00603
00604 PilotListItem *p = (PilotListItem *) fListBox->item(which);
00605 PilotAddress *addr = (PilotAddress *) p->rec();
00606
00607 #ifdef DEBUG
00608 DEBUGKPILOT << fname
00609 << ": Showing "
00610 << addr->getField(entryLastname)
00611 << " "
00612 << addr->getField(entryFirstname)
00613 << endl;
00614 #endif
00615
00616 QString text(CSL1("<qt>"));
00617 text += addr->getTextRepresentation(true);
00618 text += CSL1("</qt>\n");
00619 fAddrInfo->setText(text);
00620
00621 slotUpdateButtons();
00622 }
00623
00624
00625
00626 void AddressWidget::writeAddress(PilotAddress * which,
00627 PilotDatabase * addressDB)
00628 {
00629 FUNCTIONSETUP;
00630
00631
00632
00633
00634
00635
00636 PilotDatabase *myDB = addressDB;
00637 bool usemyDB = false;
00638
00639 if (myDB == 0L || !myDB->isDBOpen())
00640 {
00641 myDB = new PilotLocalDatabase(dbPath(), CSL1("AddressDB"));
00642 usemyDB = true;
00643 }
00644
00645
00646
00647
00648 if (!myDB->isDBOpen())
00649 {
00650 #ifdef DEBUG
00651 DEBUGKPILOT << fname << ": Address database is not open" <<
00652 endl;
00653 #endif
00654 return;
00655 }
00656
00657
00658
00659 PilotRecord *pilotRec = which->pack();
00660
00661 myDB->writeRecord(pilotRec);
00662 markDBDirty(CSL1("AddressDB"));
00663 delete pilotRec;
00664
00665
00666
00667
00668 if (usemyDB)
00669 {
00670 KPILOT_DELETE( myDB );
00671 }
00672 }
00673
00674 #define plu_quiet 1
00675 #include "pilot-addresses.c"
00676
00677 void AddressWidget::slotExport()
00678 {
00679 FUNCTIONSETUP;
00680 if( !fAddressAppInfo ) return;
00681 int currentCatID = findSelectedCategory(fCatList,
00682 fAddressAppInfo->categoryInfo());
00683
00684 QString prompt = (currentCatID==-1) ?
00685 i18n("Export All Addresses") :
00686 i18n("Export Address Category %1").arg(fAddressAppInfo->category(currentCatID)) ;
00687
00688
00689 QString saveFile = KFileDialog::getSaveFileName(
00690 QString::null,
00691 CSL1("*.csv|Comma Separated Values"),
00692 this,
00693 prompt
00694 );
00695 if (saveFile.isEmpty())
00696 {
00697 #ifdef DEBUG
00698 DEBUGKPILOT << fname << ": No save file selected." << endl;
00699 #endif
00700 return;
00701 }
00702 if (QFile::exists(saveFile) &&
00703 KMessageBox::warningContinueCancel(this,
00704 i18n("The file <i>%1</i> exists. Overwrite?").arg(saveFile),
00705 i18n("Overwrite File?"),
00706 i18n("Overwrite"))!=KMessageBox::Continue)
00707 {
00708 #ifdef DEBUG
00709 DEBUGKPILOT << fname << ": Overwrite file canceled." << endl;
00710 #endif
00711 return;
00712 }
00713
00714 FILE *f = fopen(QFile::encodeName(saveFile),"w");
00715 if (!f)
00716 {
00717 KMessageBox::sorry(this,
00718 i18n("The file <i>%1</i> could not be opened for writing.").arg(saveFile));
00719 return;
00720 }
00721 fAddressList.first();
00722
00723 #ifdef DEBUG
00724 DEBUGKPILOT << fname << ": Adding records..." << endl;
00725 #endif
00726
00727 while (fAddressList.current())
00728 {
00729 const PilotAddress *a = fAddressList.current();
00730 if ((currentCatID == -1) ||
00731 (a->category() == currentCatID))
00732 {
00733 write_record_CSV(f, fAddressAppInfo->info(), a->address(),
00734 a->attributes(), a->category(), 0);
00735 }
00736 fAddressList.next();
00737 }
00738
00739 fclose(f);
00740 }
00741