kandy Library API Documentation

mobilegui.cpp

00001 // $Id: mobilegui.cpp,v 1.8 2002/08/29 09:51:19 lukas Exp $
00002 
00003 #include <qlabel.h>
00004 #include <qlistview.h>
00005 #include <qfile.h>
00006 #include <qtextstream.h>
00007 #include <qmessagebox.h>
00008 
00009 #include <kdebug.h>
00010 #include <kfiledialog.h>
00011 #include <kmessagebox.h>
00012 #include <klocale.h>
00013 #include <kapplication.h>
00014 
00015 #include <kabc/stdaddressbook.h>
00016 
00017 #include "atcommand.h"
00018 #include "commandscheduler.h"
00019 
00020 #include "mobilegui.h"
00021 #include "mobilegui.moc"
00022 
00023 class SyncEntry {
00024   public:
00025     SyncEntry() { mOn = true; }
00026   
00027     bool mOn;
00028 };
00029 
00030 class SyncEntryKab : public SyncEntry {
00031   public:
00032     SyncEntryKab(bool on,const QString &index,const QString &name,
00033                  const QString &type,const QString &phone,const QString &phonetype)
00034     {
00035       mOn = on;
00036       mIndex = index;
00037       mName = name;
00038       mType = type;
00039       mPhone = phone;
00040       mPhonetype = phonetype;
00041     }
00042   
00043     QString mIndex;
00044     QString mName;
00045     QString mType;
00046     QString mPhone;
00047     QString mPhonetype;
00048 
00049     KABC::Addressee mAddressee;
00050 };
00051 
00052 class SyncEntryMobile : public SyncEntry {
00053   public:
00054     SyncEntryMobile(bool on,const QString &index,const QString &phone,
00055                     const QString &type,const QString &name)
00056     {
00057       mOn = on;
00058       mIndex = index;
00059       mName = name;
00060       mType = type;
00061       mPhone = phone;
00062     }
00063     
00064     QString mIndex;
00065     QString mName;
00066     QString mType;
00067     QString mPhone;
00068 };
00069 
00070 class SyncEntryCommon : public SyncEntry {
00071   public:
00072     SyncEntryCommon(bool on,SyncEntryKab *kabEntry,SyncEntryMobile *mobileEntry)
00073     {
00074       mOn = on;
00075       mKabEntry = kabEntry;
00076       mMobileEntry = mobileEntry;
00077     }
00078     
00079     SyncEntryKab *mKabEntry;
00080     SyncEntryMobile *mMobileEntry;
00081 };
00082 
00083 class AddressSyncer {
00084   public:
00085     AddressSyncer()
00086     {
00087       mKabEntries.setAutoDelete(true);
00088       mMobileEntries.setAutoDelete(true);
00089       mCommonEntries.setAutoDelete(true);
00090     }
00091   
00092     QPtrList<SyncEntryKab> mKabEntries;
00093     QPtrList<SyncEntryMobile> mMobileEntries;
00094     QPtrList<SyncEntryCommon> mCommonEntries; 
00095 };
00096 
00097 
00098 class PhoneBookItem : public QCheckListItem {
00099   public:
00100     PhoneBookItem(QListView *v) : QCheckListItem(v,"",QCheckListItem::CheckBox)
00101     {
00102       mSyncEntry = 0;
00103     }
00104     PhoneBookItem(QListView *v,SyncEntry *syncEntry,const QString &index,
00105                   const QString &phone,
00106                   const QString &type, const QString &name) :
00107       QCheckListItem(v,index,QCheckListItem::CheckBox)
00108     {
00109       mSyncEntry = syncEntry;
00110       
00111       setText(1,phone);
00112       setText(2,type);
00113       setText(3,name);
00114     }
00115 
00116     void setItem(const QString &index,const QString &phone,
00117                  const QString &type, const QString &name)
00118     {
00119       setText(0,index);
00120       setText(1,phone);
00121       setText(2,type);
00122       setText(3,name);
00123     }
00124 
00125     void setIndex(int i) { setText(0,QString::number(i)); }
00126     QString index() { return text(0); }
00127     QString phone() { return text(1); }
00128     QString type() { return text(2); }
00129     QString name() { return text(3); }
00130 
00131     SyncEntry *syncEntry() { return mSyncEntry; }
00132 
00133   private:
00134     SyncEntry *mSyncEntry;
00135 };
00136 
00137 
00138 /* 
00139  *  Constructs a MobileGui which is a child of 'parent', with the 
00140  *  name 'name' and widget flags set to 'f' 
00141  *
00142  *  The dialog will by default be modeless, unless you set 'modal' to
00143  *  TRUE to construct a modal dialog.
00144  */
00145 MobileGui::MobileGui(CommandScheduler *scheduler,QWidget* parent,
00146                      const char* name,WFlags fl)
00147     : MobileGui_base(parent,name,fl),
00148       DCOPObject("KandyIface")
00149 {
00150   mSyncing = false;
00151   mScheduler = scheduler;
00152   mSyncer = new AddressSyncer;
00153 
00154   connect(mScheduler,SIGNAL(commandProcessed(ATCommand *)),
00155           SLOT(processResult(ATCommand *)));
00156 }
00157 
00158 MobileGui::~MobileGui()
00159 {
00160   delete mSyncer;
00161 }
00162 
00163 void MobileGui::exit()
00164 {
00165   kapp->quit();
00166 }
00167 
00168 void MobileGui::readModelInformation()
00169 {
00170   mScheduler->executeId("+cgmi");
00171   mScheduler->executeId("+cgmm");
00172   mScheduler->executeId("+cgmr");
00173   mScheduler->executeId("+cgsn");
00174 }
00175 
00176 void MobileGui::readPhonebook()
00177 {
00178   mScheduler->executeId("+cpbr=1,150");
00179   
00180   emit statusMessage(i18n("Reading mobile phonebook..."));
00181 }
00182 
00183 void MobileGui::writePhonebook()
00184 {
00185   kdDebug() << "MobileGui::writePhonebook" << endl;
00186 
00187   for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00188     SyncEntryMobile *entry = mSyncer->mMobileEntries.at(i);
00189 
00190 //    kdDebug() << "Writing " << entry->mIndex << " " << entry->mName
00191 //              << " " << entry->mPhone << endl;
00192 
00193     QString id = "+cpbw=" + entry->mIndex;
00194     mLastWriteId = id;
00195     ATCommand *cmd = new ATCommand(id);
00196     cmd->setAutoDelete(true);
00197     cmd->addParameter(new ATParameter(quote(entry->mPhone)));
00198     cmd->addParameter(new ATParameter(entry->mType));
00199     cmd->addParameter(new ATParameter(quote(entry->mName)));
00200 
00201     kdDebug() << "  " << cmd->cmd() << endl;
00202     kdDebug() << "  id: " << cmd->id() << endl;
00203     
00204     mScheduler->execute(cmd);
00205   }
00206 
00207   emit statusMessage(i18n("Writing mobile phonebook..."));  
00208 }
00209 
00210 void MobileGui::readKabc()
00211 {
00212   kdDebug() << "MobileGui::readKabc()" << endl;
00213 
00214   mSyncer->mKabEntries.clear();
00215 
00216   KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
00217 
00218   KABC::AddressBook::Iterator it;
00219   for( it = addressBook->begin(); it != addressBook->end(); ++it ) {
00220     
00221     QString index = (*it).custom("KANDY","Index");
00222     QString type = (*it).custom("KANDY","Type");
00223     QString name = (*it).custom("KANDY","Name");
00224     QString phonetype = (*it).custom("KANDY","Phonetype");
00225     
00226     // Get phonenumber according to phonetype. If no number of this type was
00227     // found use the first phone number as default
00228     KABC::PhoneNumber phoneNumber;
00229     if ( phonetype.isEmpty() ) {
00230       KABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers();
00231       phoneNumber = phoneNumbers.first();
00232     } else {
00233       phoneNumber = (*it).phoneNumber( phonetype.toInt() );
00234     }
00235     QString phone = phoneNumber.number();
00236 
00237     SyncEntryKab *kabEntry;
00238     if (!index.isEmpty()) {
00239       // This entry was already stored on the phone at some time.
00240       kabEntry = new SyncEntryKab(true,index,name,type,phone,phonetype);
00241     } else {
00242       // This entry has never been on the phone.
00243       index = "";
00244       name = (*it).realName();
00245       if (phone.left(1) == "+") type = "145";
00246       else type = "129";
00247       
00248       kabEntry = new SyncEntryKab(false,index,name,type,phone,phonetype);
00249     }
00250 
00251     kabEntry->mAddressee = (*it);
00252 
00253     mSyncer->mKabEntries.append(kabEntry);
00254   }
00255 
00256   // Display kab entries
00257   updateKabBook();
00258   
00259   emit transientStatusMessage(i18n("Read KDE address book."));
00260 }
00261 
00262 void MobileGui::writeKabc()
00263 {
00264   kdDebug() << "MobileGui::writeKabc()" << endl;
00265 
00266   KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
00267 
00268   KABC::Ticket *ticket = addressBook->requestSaveTicket();
00269 
00270   if ( !ticket ) {
00271     kdDebug() << "Error! No ticket to save." << endl;
00272     return;
00273   }
00274 
00275   for(uint i=0;i<mSyncer->mKabEntries.count();++i) {
00276     SyncEntryKab *kabEntry = mSyncer->mKabEntries.at(i);
00277 
00278     KABC::Addressee entry = kabEntry->mAddressee;
00279     
00280     QString name = kabEntry->mName;
00281     QString phonenumber = kabEntry->mPhone;
00282     QString index = kabEntry->mIndex;
00283     QString type = kabEntry->mType;
00284 
00285     entry.insertCustom( "KANDY", "Index", index );
00286     
00287     entry.setFormattedName( name );
00288 
00289     // Try to identify type of phonenumber and write it to the corresponding
00290     // telephone entry    
00291     int phoneType = 0;
00292     if (phonenumber.left(3) == "017" || phonenumber.left(6) == "+49017") {
00293       phoneType = KABC::PhoneNumber::Cell;
00294     }
00295     entry.insertPhoneNumber( KABC::PhoneNumber( phonenumber, phoneType ) );
00296     entry.insertCustom( "KANDY", "Phonetype", QString::number( phoneType ) );
00297     
00298     entry.insertCustom( "KANDY", "Name", name );
00299     entry.insertCustom( "KANDY", "Type", type );
00300 
00301     addressBook->insertAddressee( entry );
00302   }
00303   
00304   addressBook->save( ticket );
00305   
00306   emit transientStatusMessage(i18n("Wrote KDE address book"));
00307 }
00308 
00309 void MobileGui::refreshStatus()
00310 {
00311   mScheduler->executeId("+cbc");
00312   mScheduler->executeId("+csq");
00313 }
00314 
00315 void MobileGui::processResult(ATCommand *command)
00316 {
00317   if (command->id() == "+cbc") {
00318     mBatteryChargeLabel->setText(command->resultField(1) + " %");
00319   } else if (command->id() == "+csq") {
00320     mSignalQualityLabel->setText(command->resultField(0));
00321   } else if (command->id() == "+cgmi") {
00322     mManufacturerLabel->setText(command->resultField(0));
00323   } else if (command->id() == "+cgmm") {
00324     mModelLabel->setText(command->resultField(0));
00325   } else if (command->id() == "+cgmr") {
00326     mGSMVersionLabel->setText(command->resultField(0));
00327   } else if (command->id() == "+cgsn") {
00328     mSerialNumberLabel->setText(command->resultField(0));
00329   } else if (command->id() == "+cpbr=1,150") {
00330     fillPhonebook(command);
00331   } else if (command->id() == mLastWriteId) {
00332     mLastWriteId = "";
00333     emit transientStatusMessage(i18n("Wrote mobile phonebook."));
00334   }
00335   if (command->id() == mSyncReadId) {
00336     mSyncReadId = "";
00337     mergePhonebooks();
00338     writeKabc();
00339     writePhonebook();
00340     mSyncWriteId = mLastWriteId;
00341   }
00342   if (command->id() == mSyncWriteId) {
00343     mSyncWriteId = "";
00344     emit transientStatusMessage(i18n("Synced phonebooks."));
00345     mSyncing = false;
00346   }
00347 }
00348 
00349 void MobileGui::fillPhonebook(ATCommand *cmd)
00350 {
00351   kdDebug() << "MobileGui::fillPhonebook()" << endl;
00352 
00353 //  kdDebug() << "--- " << cmd->resultString() << endl;
00354 
00355   mSyncer->mMobileEntries.clear();
00356     
00357   QPtrList<QStringList> *list = cmd->resultFields();
00358   
00359   QStringList *fields = list->first();
00360   while(fields) {
00361     if (fields->count() != 4) {
00362       kdDebug() << "Error! Unexpected number of address fields." << endl;
00363     } else {
00364       QString index = (*fields)[0];
00365       QString phone = (*fields)[1];
00366       QString type = (*fields)[2];
00367       QString name = (*fields)[3];
00368       SyncEntryMobile *phoneEntry = new SyncEntryMobile(true,dequote(index),
00369           dequote(phone),dequote(type),dequote(name));
00370       mSyncer->mMobileEntries.append(phoneEntry);
00371     }
00372     fields = list->next();
00373   }
00374 
00375   // Display mobile entries
00376   updateMobileBook();
00377 
00378   emit transientStatusMessage(i18n("Read mobile phonebook."));
00379   
00380   emit phonebookRead();
00381 }
00382 
00383 QString MobileGui::quote(const QString &str)
00384 {
00385   if (str.left(1) == "\"" && str.right(1) == "\"") return str;
00386   
00387   return "\"" + str + "\"";
00388 }
00389 
00390 QString MobileGui::dequote(const QString &str)
00391 {
00392   int pos = 0;
00393   int len = str.length();
00394 
00395   if (str.left(1) == "\"") {
00396     ++pos;
00397     --len;
00398   } 
00399   if (str.right(1) == "\"") {
00400     --len;
00401   }
00402   
00403   return str.mid(pos,len);
00404 }
00405 
00406 void MobileGui::savePhonebook()
00407 {
00408   QString fileName = KFileDialog::getSaveFileName("phonebook.csv");
00409 
00410   QFile outFile(fileName);
00411   if ( outFile.open(IO_WriteOnly) ) {    // file opened successfully
00412     QTextStream t( &outFile );        // use a text stream
00413 
00414     for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00415       SyncEntryMobile *e = mSyncer->mMobileEntries.at(i);
00416       t << e->mIndex << "," << e->mPhone << "," << e->mType << ","
00417         << e->mName << endl;
00418     }
00419 
00420     outFile.close();
00421   }
00422 }
00423 
00424 void MobileGui::mergePhonebooks()
00425 {
00426   kdDebug() << "MobileGui::mergePhonebooks()" << endl;
00427 
00428   // Update selection state from GUI.
00429   PhoneBookItem *item = (PhoneBookItem *)mKabBook->firstChild();
00430   while(item) {
00431     item->syncEntry()->mOn = item->isOn();
00432     item = (PhoneBookItem *)item->nextSibling();
00433   }
00434   item = (PhoneBookItem *)mMobileBook->firstChild();
00435   while(item) {
00436     item->syncEntry()->mOn = item->isOn();
00437     item = (PhoneBookItem *)item->nextSibling();
00438   }
00439 
00440   mSyncer->mCommonEntries.clear();
00441 
00442 //  kdDebug() << " Insert kab list" << endl;
00443 
00444   // Put Kab list into common list
00445   for(uint i=0;i<mSyncer->mKabEntries.count();++i) {
00446     if (mSyncer->mKabEntries.at(i)->mOn) {
00447       mSyncer->mCommonEntries.append(new SyncEntryCommon(true,mSyncer->mKabEntries.at(i),0));
00448     }
00449   }
00450 
00451 //  kdDebug() << " Insert mobile list" << endl;
00452 
00453   // Put mobile list into common list. Merge equivalent entries.
00454   for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00455     SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at(i);
00456 //    kdDebug() << "--- Inserting " << mobileEntry->mName << endl;
00457   
00458     uint j=0;
00459     for(;j<mSyncer->mCommonEntries.count();++j) {
00460       if (mSyncer->mCommonEntries.at(j)->mKabEntry) {
00461         if (mSyncer->mCommonEntries.at(j)->mKabEntry->mIndex ==
00462             mobileEntry->mIndex) {
00463           // Equivalent entry is already there. Merge entries.
00464           mSyncer->mCommonEntries.at(j)->mMobileEntry = mobileEntry;
00465           break;
00466         }
00467       }
00468     }
00469     if (j == mSyncer->mCommonEntries.count()) {
00470       if (mobileEntry->mOn) {
00471         // Entry wasn't found
00472         mSyncer->mCommonEntries.append(new SyncEntryCommon(true,0,mobileEntry));
00473       }
00474     }
00475   }
00476   
00477 //  kdDebug() << " Resolve conflicts" << endl;
00478 
00479   // Resolve conflicts
00480   bool kabUpdated = false;
00481   bool mobileUpdated = false;
00482   for(uint i=0;i<mSyncer->mCommonEntries.count();++i) {
00483     SyncEntryCommon *entry = mSyncer->mCommonEntries.at(i);
00484     SyncEntryKab *kabEntry = entry->mKabEntry;
00485     SyncEntryMobile *mobileEntry = entry->mMobileEntry;
00486     if (kabEntry && mobileEntry) {
00487       if (mobileEntry->mPhone == kabEntry->mPhone &&
00488           mobileEntry->mName == kabEntry->mName) {
00489         // Entries are identical. Do nothing.
00490       } else {
00491         // Merge mobileEntrys
00492         // This alters the mobile and kab lists. Perhaps we should reflect this in the GUI.
00493         QString text = "<b>" + i18n("Kab Entry:") + "</b><br>";
00494         text += "  " + kabEntry->mName + " " + kabEntry->mPhone + "<br>";
00495         text += "<b>" + i18n("Mobile Entry:") + "</b><br>";
00496         text += "  " + mobileEntry->mName + " " + mobileEntry->mPhone;
00497       
00498         QMessageBox *msg = new QMessageBox(i18n("Conflicting Entries"),text,
00499                                          QMessageBox::Warning,1,2,0,this);
00500         msg->setButtonText(1,i18n("Use Kab entry"));
00501         msg->setButtonText(2,i18n("Use Mobile entry"));
00502         switch (msg->exec()) {
00503           case 1: // use kab entry
00504             mobileEntry->mPhone = kabEntry->mPhone;
00505             mobileEntry->mName = kabEntry->mName;
00506             mobileUpdated = true;
00507             break;
00508           case 2: // use mobile entry
00509             kabEntry->mPhone = mobileEntry->mPhone;
00510             kabEntry->mName = mobileEntry->mName;
00511             kabUpdated = true;
00512             break;
00513         }
00514       }
00515     }
00516   }
00517 
00518 //  kdDebug() << " Create new entries" << endl;
00519 
00520   // Create new entries
00521   for(uint i=0;i<mSyncer->mCommonEntries.count();++i) {
00522     SyncEntryCommon *entry = mSyncer->mCommonEntries.at(i);
00523     SyncEntryKab *kabEntry = entry->mKabEntry;
00524     SyncEntryMobile *mobileEntry = entry->mMobileEntry;
00525 
00526     if (kabEntry && !mobileEntry) {
00527       kdDebug() << "Creating mobile entry for " << kabEntry->mPhone << endl;
00528       // Create mobile entry
00529       // The type should be generated here.
00530       // The values should be checked for validity.
00531       entry->mMobileEntry = new SyncEntryMobile(true,"",kabEntry->mPhone,kabEntry->mType,
00532                                                 kabEntry->mName);
00533       mSyncer->mMobileEntries.append(entry->mMobileEntry);
00534 
00535       // Create new index
00536       QString index;
00537       for(uint j=1;j<150;++j) {
00538         uint k = 0;
00539         for(;k<mSyncer->mMobileEntries.count();++k) {
00540           if (mSyncer->mMobileEntries.at(k)->mIndex == QString::number(j)) {
00541             break;
00542           }
00543         }
00544         if (k == mSyncer->mMobileEntries.count()) {
00545           index = QString::number(j);
00546           break;
00547         }
00548       }
00549       entry->mMobileEntry->mIndex = index;
00550       
00551       kabEntry->mIndex = index;
00552 
00553       kabUpdated = true;
00554       mobileUpdated = true;
00555     } else if (mobileEntry && !kabEntry) {
00556       // Create kab entry
00557       QString phonetype = "0";
00558       entry->mKabEntry = new SyncEntryKab(true,mobileEntry->mIndex,mobileEntry->mName,
00559                                           mobileEntry->mType,mobileEntry->mPhone,
00560                                           phonetype);
00561       mSyncer->mKabEntries.append(entry->mKabEntry);
00562 
00563       kabUpdated = true;
00564     }
00565   }
00566 
00567 //  kdDebug() << "Update gui" << endl;
00568 
00569   // Update kab and mobile entries
00570   if (kabUpdated) updateKabBook();
00571   if (mobileUpdated) updateMobileBook();
00572 
00573   kdDebug() << "MobileGui::mergePhonebooks() done." << endl;
00574 }
00575 
00576 void MobileGui::syncPhonebooks()
00577 {
00578   if (mSyncing) return;
00579 
00580   mSyncing = true;
00581   readKabc();
00582   readPhonebook();
00583   mSyncReadId = "+cpbr=1,150";
00584 }
00585 
00586 void MobileGui::updateKabBook()
00587 {
00588   mKabBook->clear();
00589   for(uint i=0;i<mSyncer->mKabEntries.count();++i) {
00590     SyncEntryKab *kabEntry = mSyncer->mKabEntries.at(i);
00591     PhoneBookItem *item = new PhoneBookItem(mKabBook,kabEntry,kabEntry->mIndex,
00592         kabEntry->mPhone,kabEntry->mType,kabEntry->mName);
00593     item->setOn(kabEntry->mOn);
00594   }
00595 }
00596 
00597 void MobileGui::updateMobileBook()
00598 {
00599   mMobileBook->clear();
00600   for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00601     SyncEntryMobile *entry = mSyncer->mMobileEntries.at(i);
00602     PhoneBookItem *item = new PhoneBookItem(mMobileBook,entry,entry->mIndex,
00603         entry->mPhone,entry->mType,entry->mName);
00604     item->setOn(entry->mOn);
00605   }
00606 }
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:06 2003 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001