kpilot Library API Documentation

addressWidget.cc

00001 /* addressWidget.cc                     KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 **
00005 ** This file defines the addressWidget, that part of KPilot that
00006 ** displays address records from the Pilot.
00007 */
00008 
00009 /*
00010 ** This program is free software; you can redistribute it and/or modify
00011 ** it under the terms of the GNU General Public License as published by
00012 ** the Free Software Foundation; either version 2 of the License, or
00013 ** (at your option) any later version.
00014 **
00015 ** This program is distributed in the hope that it will be useful,
00016 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018 ** GNU General Public License for more details.
00019 **
00020 ** You should have received a copy of the GNU General Public License
00021 ** along with this program in a file called COPYING; if not, write to
00022 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
00023 ** MA 02111-1307, USA.
00024 */
00025 
00026 /*
00027 ** Bug reports and questions can be sent to kde-pim@kde.org
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 // This is the size of several (automatic) buffers,
00068 // used to retrieve data from the database.
00069 // I have no idea if 0xffff is some magic number or not.
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         /* NOTREACHED */
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 /* virtual */ 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         // address info text view
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         // FUNCTIONSETUP;
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())    // One last try
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 /* slot */ 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         // Response to bug 18072: Don't even try to
00435         // add records to an empty or unopened database,
00436         // since we don't have the DBInfo stuff to deal with it.
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         // TODO: Just add the new record to the lists
00491         updateWidget();
00492 
00493         // k holds the item number of the address just added.
00494         //
00495         //
00496         int k = fListBox->count() - 1;
00497 
00498         fListBox->setCurrentItem(k);    // Show the newest one
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         // TODO: Just change the record
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          * enum values from pi-address.h
00580          *
00581          * entryLastname, entryFirstname,
00582          * entryCompany, entryPhone1, entryPhone2, entryPhone3,
00583          * entryPhone4, entryPhone5, entryAddress, entryCity, entryState,
00584          * entryZip, entryCountry, entryTitle, entryCustom1, entryCustom2,
00585          * entryCustom3, entryCustom4, entryNote
00586          */
00587 
00588         QString text;
00589 
00590         text += CSL1("<qt>");
00591 
00592         QString par = CSL1("<p>");
00593         QString ps = CSL1("</p>");
00594         
00595         // title + name
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         // company
00613         if (!addr->getField(entryCompany).isEmpty())
00614         {
00615                 text += par;
00616                 text += addr->getField(entryCompany);
00617                 text += ps;
00618         }
00619 
00620         // phone numbers (+ labels)
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         // address, city, state, country
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         // custom fields
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         // note
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         // Open a database (myDB) only if needed,
00701         // i.e. only if the passed-in addressDB
00702         // isn't valid.
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         // Still no valid address database...
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         // Do the actual work.
00728         PilotRecord *pilotRec = which->pack();
00729 
00730         myDB->writeRecord(pilotRec);
00731         delete pilotRec;
00732 
00733         // Clean up in the case that we allocated our own DB.
00734         //
00735         //
00736         if (usemyDB)
00737         {
00738                 delete myDB;
00739         }
00740 }
00741 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sat Oct 18 02:47:14 2003 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001