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