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