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 #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
00162
00163
00164
00165
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() << "MobileGui::writePhonebook" << endl;
00208
00209 for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00210 SyncEntryMobile *entry = mSyncer->mMobileEntries.at(i);
00211
00212
00213
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() << " " << cmd->cmd() << endl;
00224 kdDebug() << " 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() << "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
00249
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
00262 kabEntry = new SyncEntryKab(true,index,name,type,phone,phonetype);
00263 } else {
00264
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
00279 updateKabBook();
00280
00281 emit transientStatusMessage(i18n("Read KDE address book."));
00282 }
00283
00284 void MobileGui::writeKabc()
00285 {
00286 kdDebug() << "MobileGui::writeKabc()" << endl;
00287
00288 KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
00289
00290 KABC::Ticket *ticket = addressBook->requestSaveTicket();
00291
00292 if ( !ticket ) {
00293 kdDebug() << "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
00312
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() << "MobileGui::fillPhonebook()" << endl;
00374
00375
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() << "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
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) ) {
00434 QTextStream t( &outFile );
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() << "MobileGui::mergePhonebooks()" << endl;
00449
00450
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
00465
00466
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
00474
00475
00476 for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00477 SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at(i);
00478
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
00486 mSyncer->mCommonEntries.at(j)->mMobileEntry = mobileEntry;
00487 break;
00488 }
00489 }
00490 }
00491 if (j == mSyncer->mCommonEntries.count()) {
00492 if (mobileEntry->mOn) {
00493
00494 mSyncer->mCommonEntries.append(new SyncEntryCommon(true,0,mobileEntry));
00495 }
00496 }
00497 }
00498
00499
00500
00501
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
00512 } else {
00513
00514
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:
00527 mobileEntry->mPhone = kabEntry->mPhone;
00528 mobileEntry->mName = kabEntry->mName;
00529 mobileUpdated = true;
00530 break;
00531 case 2:
00532 kabEntry->mPhone = mobileEntry->mPhone;
00533 kabEntry->mName = mobileEntry->mName;
00534 kabUpdated = true;
00535 break;
00536 }
00537 }
00538 }
00539 }
00540
00541
00542
00543
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() << "Creating mobile entry for " << kabEntry->mPhone << endl;
00551
00552
00553
00554 entry->mMobileEntry = new SyncEntryMobile(true,"",kabEntry->mPhone,kabEntry->mType,
00555 kabEntry->mName);
00556 mSyncer->mMobileEntries.append(entry->mMobileEntry);
00557
00558
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
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
00591
00592
00593 if (kabUpdated) updateKabBook();
00594 if (mobileUpdated) updateMobileBook();
00595
00596 kdDebug() << "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 }