kandy Library API Documentation

mobilegui.cpp

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