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