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.64 2003/10/13 13:58:19 kainhofe 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 #include <qregexp.h>
00055 
00056 #include <kapplication.h>
00057 #include <kmessagebox.h>
00058 #include <kdebug.h>
00059 #include <kfiledialog.h>
00060 
00061 #include "kpilotConfig.h"
00062 #include "listItems.h"
00063 #include "addressEditor.h"
00064 #include "pilotLocalDatabase.h"
00065 
00066 #include "addressWidget.moc"
00067 
00068 // This is the size of several (automatic) buffers,
00069 // used to retrieve data from the database.
00070 // I have no idea if 0xffff is some magic number or not.
00071 //
00072 //
00073 #define BUFFERSIZE  (0xffff)
00074 
00075 AddressWidget::AddressWidget(QWidget * parent,
00076     const QString & path) :
00077     PilotComponent(parent, "component_address", path),
00078     fAddrInfo(0),
00079     fPendingAddresses(0)
00080 {
00081     FUNCTIONSETUP;
00082 
00083     setupWidget();
00084     fAddressList.setAutoDelete(true);
00085 
00086     /* NOTREACHED */
00087     (void) addresswidget_id;
00088 }
00089 
00090 AddressWidget::~AddressWidget()
00091 {
00092     FUNCTIONSETUP;
00093 }
00094 
00095 int AddressWidget::getAllAddresses(PilotDatabase * addressDB)
00096 {
00097     FUNCTIONSETUP;
00098 
00099     int currentRecord = 0;
00100     PilotRecord *pilotRec;
00101     PilotAddress *address;
00102     bool showSecrets = KPilotConfig::getConfig().getShowSecrets();
00103 
00104 
00105 #ifdef DEBUG
00106     DEBUGKPILOT << fname << ": Reading AddressDB..." << endl;
00107 #endif
00108 
00109     while ((pilotRec = addressDB->readRecordByIndex(currentRecord)) != 0L)
00110     {
00111         if (!(pilotRec->isDeleted()) &&
00112             (!(pilotRec->isSecret()) || showSecrets))
00113         {
00114             address = new PilotAddress(fAddressAppInfo, pilotRec);
00115             if (address == 0L)
00116             {
00117                 kdWarning() << k_funcinfo
00118                     << ": Couldn't allocate record "
00119                     << currentRecord++
00120                     << endl;
00121                 break;
00122             }
00123             fAddressList.append(address);
00124         }
00125         delete pilotRec;
00126 
00127         currentRecord++;
00128     }
00129 
00130 #ifdef DEBUG
00131     DEBUGKPILOT << fname
00132         << ": Total " << currentRecord << " records" << endl;
00133 #endif
00134 
00135     return currentRecord;
00136 }
00137 
00138 void AddressWidget::showComponent()
00139 {
00140     FUNCTIONSETUP;
00141     if ( fPendingAddresses>0 ) return;
00142 
00143 #ifdef DEBUG
00144     DEBUGKPILOT << fname
00145         << ": Reading from directory " << dbPath() << endl;
00146 #endif
00147 
00148     PilotDatabase *addressDB =
00149         new PilotLocalDatabase(dbPath(), CSL1("AddressDB"));
00150     unsigned char buffer[BUFFERSIZE];
00151     int appLen;
00152 
00153     fAddressList.clear();
00154 
00155     if (addressDB->isDBOpen())
00156     {
00157         appLen = addressDB->readAppBlock(buffer, BUFFERSIZE);
00158         unpack_AddressAppInfo(&fAddressAppInfo, buffer, appLen);
00159 
00160         populateCategories(fCatList, &fAddressAppInfo.category);
00161         getAllAddresses(addressDB);
00162 
00163     }
00164     else
00165     {
00166         populateCategories(fCatList, 0L);
00167         kdWarning() << k_funcinfo
00168             << ": Could not open local AddressDB" << endl;
00169     }
00170 
00171     KPILOT_DELETE( addressDB );
00172 
00173     updateWidget();
00174 }
00175 
00176 void AddressWidget::hideComponent()
00177 {
00178     FUNCTIONSETUP;
00179     if (fPendingAddresses==0 )
00180     {
00181         fAddressList.clear();
00182         fListBox->clear();
00183     
00184         updateWidget();
00185     }
00186 }
00187 
00188 /* virtual */ bool AddressWidget::preHotSync(QString &s)
00189 {
00190     FUNCTIONSETUP;
00191 
00192     if ( fPendingAddresses )
00193     {
00194 #ifdef DEBUG
00195         DEBUGKPILOT << fname
00196             << ": fPendingAddress="
00197             << fPendingAddresses
00198             << endl;
00199 #endif
00200 
00201 #if KDE_VERSION<220
00202         s = i18n("There are still %1 address editing windows open.")
00203             .arg(QString::number(fPendingAddresses));
00204 #else
00205         s = i18n("There is still an address editing window open.",
00206             "There are still %n address editing windows open.",
00207             fPendingAddresses);
00208 #endif
00209         return false;
00210     }
00211 
00212     return true;
00213 }
00214 
00215 void AddressWidget::postHotSync()
00216 {
00217     FUNCTIONSETUP;
00218 
00219     if ( shown ) 
00220     {
00221         fAddressList.clear();
00222         showComponent();
00223     }
00224 }
00225 
00226 
00227 void AddressWidget::setupWidget()
00228 {
00229     FUNCTIONSETUP;
00230 
00231     QLabel *label;
00232     QGridLayout *grid = new QGridLayout(this, 6, 4, SPACING);
00233 
00234     fCatList = new QComboBox(this);
00235     grid->addWidget(fCatList, 0, 1);
00236     connect(fCatList, SIGNAL(activated(int)),
00237         this, SLOT(slotSetCategory(int)));
00238     QWhatsThis::add(fCatList,
00239         i18n("<qt>Select the category of addresses to display here.</qt>"));
00240 
00241     label = new QLabel(i18n("Category:"), this);
00242     label->setBuddy(fCatList);
00243     grid->addWidget(label, 0, 0);
00244 
00245     fListBox = new QListBox(this);
00246     grid->addMultiCellWidget(fListBox, 1, 1, 0, 1);
00247     connect(fListBox, SIGNAL(highlighted(int)),
00248         this, SLOT(slotShowAddress(int)));
00249     connect(fListBox, SIGNAL(selected(int)),
00250         this, SLOT(slotEditRecord()));
00251     QWhatsThis::add(fListBox,
00252         i18n("<qt>This list displays all the addresses "
00253             "in the selected category. Click on "
00254             "one to display it to the right.</qt>"));
00255 
00256     label = new QLabel(i18n("Address info:"), this);
00257     grid->addWidget(label, 0, 2);
00258 
00259     // address info text view
00260     fAddrInfo = new QTextView(this);
00261     grid->addMultiCellWidget(fAddrInfo, 1, 4, 2, 2);
00262 
00263     QPushButton *button;
00264 
00265     fEditButton = new QPushButton(i18n("Edit Record..."), this);
00266     grid->addWidget(fEditButton, 2, 0);
00267     connect(fEditButton, SIGNAL(clicked()), this, SLOT(slotEditRecord()));
00268     QWhatsThis::add(fEditButton,
00269         i18n("<qt>You can edit an address when it is selected.</qt>"));
00270 
00271     button = new QPushButton(i18n("New Record..."), this);
00272     grid->addWidget(button, 2, 1);
00273     connect(button, SIGNAL(clicked()), this, SLOT(slotCreateNewRecord()));
00274     QWhatsThis::add(button, i18n("<qt>Add a new address to the address book.</qt>"));
00275 
00276     fDeleteButton = new QPushButton(i18n("Delete Record"), this);
00277     grid->addWidget(fDeleteButton, 3, 0);
00278     connect(fDeleteButton, SIGNAL(clicked()),
00279         this, SLOT(slotDeleteRecord()));
00280     QWhatsThis::add(fDeleteButton,
00281         i18n("<qt>Delete the selected address from the address book.</qt>"));
00282 }
00283 
00284 void AddressWidget::updateWidget()
00285 {
00286     FUNCTIONSETUP;
00287 
00288     int addressDisplayMode =
00289         KPilotConfig::getConfig().setAddressGroup().
00290         getAddressDisplayMode();
00291 
00292     int listIndex = 0;
00293 
00294 #ifdef DEBUG
00295     DEBUGKPILOT << fname
00296         << ": Display Mode=" << addressDisplayMode << endl;
00297 #endif
00298 
00299     int currentCatID = findSelectedCategory(fCatList,
00300         &(fAddressAppInfo.category));
00301 
00302     fListBox->clear();
00303     fAddressList.first();
00304 
00305 #ifdef DEBUG
00306     DEBUGKPILOT << fname << ": Adding records..." << endl;
00307 #endif
00308 
00309     while (fAddressList.current())
00310     {
00311         if ((currentCatID == -1) ||
00312             (fAddressList.current()->getCat() == currentCatID))
00313         {
00314             QString title = createTitle(fAddressList.current(),
00315                 addressDisplayMode);
00316 
00317             if (!title.isEmpty())
00318             {
00319                 title.remove(QRegExp("\n.*"));
00320                 PilotListItem *p = new PilotListItem(title,
00321                     listIndex,
00322                     fAddressList.current());
00323 
00324                 fListBox->insertItem(p);
00325             }
00326         }
00327         listIndex++;
00328         fAddressList.next();
00329     }
00330 
00331 #ifdef DEBUG
00332     DEBUGKPILOT << fname << ": " << listIndex << " records" << endl;
00333 #endif
00334 
00335     slotUpdateButtons();
00336 }
00337 
00338 
00339 
00340 QString AddressWidget::createTitle(PilotAddress * address, int displayMode)
00341 {
00342     // FUNCTIONSETUP;
00343 
00344     QString title;
00345 
00346     switch (displayMode)
00347     {
00348     case 1:
00349         if (!address->getField(entryCompany).isEmpty())
00350         {
00351             title.append(address->getField(entryCompany));
00352         }
00353         if (!address->getField(entryLastname).isEmpty())
00354         {
00355             if (!title.isEmpty())
00356             {
00357                 title.append( CSL1(", "));
00358             }
00359 
00360             title.append(address->getField(entryLastname));
00361         }
00362         break;
00363     case 0:
00364     default:
00365         if (!address->getField(entryLastname).isEmpty())
00366         {
00367             title.append(address->getField(entryLastname));
00368         }
00369 
00370         if (!address->getField(entryFirstname).isEmpty())
00371         {
00372             if (!title.isEmpty())
00373             {
00374                 title.append( CSL1(", "));
00375             }
00376             title.append(address->getField(entryFirstname));
00377         }
00378         break;
00379     }
00380 
00381     if (title.isEmpty())    // One last try
00382     {
00383         if (!fAddressList.current()->getField(entryCompany).isEmpty())
00384         {
00385             title.append(fAddressList.current()->
00386                 getField(entryCompany));
00387         }
00388         if (title.isEmpty())
00389         {
00390             title = i18n("[unknown]");
00391         }
00392     }
00393 
00394     return title;
00395 }
00396 
00397 
00398 /* slot */ void AddressWidget::slotUpdateButtons()
00399 {
00400     FUNCTIONSETUP;
00401 
00402     bool enabled = (fListBox->currentItem() != -1);
00403 
00404     fEditButton->setEnabled(enabled);
00405     fDeleteButton->setEnabled(enabled);
00406 }
00407 
00408 void AddressWidget::slotSetCategory(int)
00409 {
00410     FUNCTIONSETUP;
00411 
00412     updateWidget();
00413 }
00414 
00415 void AddressWidget::slotEditRecord()
00416 {
00417     FUNCTIONSETUP;
00418     if ( !shown ) return;
00419 
00420     int item = fListBox->currentItem();
00421 
00422     if (item == -1)
00423         return;
00424 
00425     PilotListItem *p = (PilotListItem *) fListBox->item(item);
00426     PilotAddress *selectedRecord = (PilotAddress *) p->rec();
00427 
00428     if (selectedRecord->id() == 0)
00429     {
00430         KMessageBox::error(0L,
00431             i18n("Cannot edit new records until "
00432                 "HotSynced with Pilot."),
00433             i18n("HotSync Required"));
00434         return;
00435     }
00436 
00437     AddressEditor *editor = new AddressEditor(selectedRecord,
00438         &fAddressAppInfo, this);
00439 
00440     connect(editor, SIGNAL(recordChangeComplete(PilotAddress *)),
00441         this, SLOT(slotUpdateRecord(PilotAddress *)));
00442     connect(editor, SIGNAL(cancelClicked()),
00443         this, SLOT(slotEditCancelled()));
00444     editor->show();
00445 
00446     fPendingAddresses++;
00447 }
00448 
00449 void AddressWidget::slotCreateNewRecord()
00450 {
00451     FUNCTIONSETUP;
00452     if ( !shown ) return;
00453 
00454     // Response to bug 18072: Don't even try to
00455     // add records to an empty or unopened database,
00456     // since we don't have the DBInfo stuff to deal with it.
00457     //
00458     //
00459     PilotDatabase *myDB = new PilotLocalDatabase(dbPath(), CSL1("AddressDB"));
00460 
00461     if (!myDB || !myDB->isDBOpen())
00462     {
00463 #ifdef DEBUG
00464         DEBUGKPILOT << fname
00465             << ": Tried to open "
00466             << dbPath()
00467             << "/AddressDB"
00468             << " and got pointer @"
00469             << (int) myDB
00470             << " with status "
00471             << ( myDB ? myDB->isDBOpen() : false )
00472             << endl;
00473 #endif
00474 
00475         KMessageBox::sorry(this,
00476             i18n("You can't add addresses to the address book "
00477                 "until you have done a HotSync at least once "
00478                 "to retrieve the database layout from your Pilot."),
00479             i18n("Can't Add New Address"));
00480 
00481         if (myDB)
00482             KPILOT_DELETE( myDB );
00483 
00484         return;
00485     }
00486 
00487     AddressEditor *editor = new AddressEditor(0L,
00488         &fAddressAppInfo, this);
00489 
00490     connect(editor, SIGNAL(recordChangeComplete(PilotAddress *)),
00491         this, SLOT(slotAddRecord(PilotAddress *)));
00492     connect(editor, SIGNAL(cancelClicked()),
00493         this, SLOT(slotEditCancelled()));
00494     editor->show();
00495 
00496     fPendingAddresses++;
00497 }
00498 
00499 void AddressWidget::slotAddRecord(PilotAddress * address)
00500 {
00501     FUNCTIONSETUP;
00502     if ( !shown && fPendingAddresses==0 ) return;
00503 
00504     int currentCatID = findSelectedCategory(fCatList,
00505         &(fAddressAppInfo.category), true);
00506 
00507 
00508     address->setCat(currentCatID);
00509     fAddressList.append(address);
00510     writeAddress(address);
00511     // TODO: Just add the new record to the lists
00512     updateWidget();
00513 
00514     // k holds the item number of the address just added.
00515     //
00516     //
00517     int k = fListBox->count() - 1;
00518 
00519     fListBox->setCurrentItem(k);    // Show the newest one
00520     fListBox->setBottomItem(k);
00521 
00522     fPendingAddresses--;
00523     if ( !shown && fPendingAddresses==0 ) hideComponent();
00524 }
00525 
00526 void AddressWidget::slotUpdateRecord(PilotAddress * address)
00527 {
00528     FUNCTIONSETUP;
00529     if ( !shown && fPendingAddresses==0 ) return;
00530 
00531     writeAddress(address);
00532     int currentRecord = fListBox->currentItem();
00533 
00534     // TODO: Just change the record
00535     updateWidget();
00536     fListBox->setCurrentItem(currentRecord);
00537 
00538     emit(recordChanged(address));
00539 
00540     fPendingAddresses--;
00541     if ( !shown && fPendingAddresses==0 ) hideComponent();
00542 }
00543 
00544 void AddressWidget::slotEditCancelled()
00545 {
00546     FUNCTIONSETUP;
00547 
00548     fPendingAddresses--;
00549     if ( !shown && fPendingAddresses==0 ) hideComponent();
00550 }
00551 
00552 void AddressWidget::slotDeleteRecord()
00553 {
00554     FUNCTIONSETUP;
00555     if ( !shown ) return;
00556 
00557     int item = fListBox->currentItem();
00558 
00559     if (item == -1)
00560         return;
00561 
00562     PilotListItem *p = (PilotListItem *) fListBox->item(item);
00563     PilotAddress *selectedRecord = (PilotAddress *) p->rec();
00564 
00565     if (selectedRecord->id() == 0)
00566     {
00567         KMessageBox::error(this,
00568             i18n("New records cannot be deleted until "
00569                 "HotSynced with pilot."),
00570             i18n("HotSync Required"));
00571         return;
00572     }
00573 
00574     if (KMessageBox::questionYesNo(this,
00575             i18n("Delete currently selected record?"),
00576             i18n("Delete Record?")) == KMessageBox::No)
00577         return;
00578 
00579     selectedRecord->makeDeleted();
00580     writeAddress(selectedRecord);
00581     emit(recordChanged(selectedRecord));
00582     showComponent();
00583 }
00584 
00585 
00586 
00587 void AddressWidget::slotShowAddress(int which)
00588 {
00589     FUNCTIONSETUP;
00590     if (!shown) return;
00591 
00592     PilotListItem *p = (PilotListItem *) fListBox->item(which);
00593     PilotAddress *addr = (PilotAddress *) p->rec();
00594 
00595 #ifdef DEBUG
00596     DEBUGKPILOT << fname
00597         << ": Showing "
00598         << addr->getField(entryLastname)
00599         << " "
00600         << addr->getField(entryFirstname)
00601         << endl;
00602 #endif
00603 
00604     QString text(CSL1("<qt>"));
00605     text += addr->getTextRepresentation(true);
00606     text += CSL1("</qt>\n");
00607     fAddrInfo->setText(text);
00608 
00609     slotUpdateButtons();
00610 }
00611 
00612 
00613 
00614 void AddressWidget::writeAddress(PilotAddress * which,
00615     PilotDatabase * addressDB)
00616 {
00617     FUNCTIONSETUP;
00618 
00619     // Open a database (myDB) only if needed,
00620     // i.e. only if the passed-in addressDB
00621     // isn't valid.
00622     //
00623     //
00624     PilotDatabase *myDB = addressDB;
00625     bool usemyDB = false;
00626 
00627     if (myDB == 0L || !myDB->isDBOpen())
00628     {
00629         myDB = new PilotLocalDatabase(dbPath(), CSL1("AddressDB"));
00630         usemyDB = true;
00631     }
00632 
00633     // Still no valid address database...
00634     //
00635     //
00636     if (!myDB->isDBOpen())
00637     {
00638 #ifdef DEBUG
00639         DEBUGKPILOT << fname << ": Address database is not open" <<
00640             endl;
00641 #endif
00642         return;
00643     }
00644 
00645 
00646     // Do the actual work.
00647     PilotRecord *pilotRec = which->pack();
00648 
00649     myDB->writeRecord(pilotRec);
00650     markDBDirty("AddressDB");
00651     delete pilotRec;
00652 
00653     // Clean up in the case that we allocated our own DB.
00654     //
00655     //
00656     if (usemyDB)
00657     {
00658         KPILOT_DELETE( myDB );
00659     }
00660 }
00661 
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:46 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003