00001
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
00140
00141
00142
00143
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
00191
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
00227
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
00240 kabEntry = new SyncEntryKab(true,index,name,type,phone,phonetype);
00241 } else {
00242
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
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
00290
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
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
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) ) {
00412 QTextStream t( &outFile );
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
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
00443
00444
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
00452
00453
00454 for(uint i=0;i<mSyncer->mMobileEntries.count();++i) {
00455 SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at(i);
00456
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
00464 mSyncer->mCommonEntries.at(j)->mMobileEntry = mobileEntry;
00465 break;
00466 }
00467 }
00468 }
00469 if (j == mSyncer->mCommonEntries.count()) {
00470 if (mobileEntry->mOn) {
00471
00472 mSyncer->mCommonEntries.append(new SyncEntryCommon(true,0,mobileEntry));
00473 }
00474 }
00475 }
00476
00477
00478
00479
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
00490 } else {
00491
00492
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:
00504 mobileEntry->mPhone = kabEntry->mPhone;
00505 mobileEntry->mName = kabEntry->mName;
00506 mobileUpdated = true;
00507 break;
00508 case 2:
00509 kabEntry->mPhone = mobileEntry->mPhone;
00510 kabEntry->mName = mobileEntry->mName;
00511 kabUpdated = true;
00512 break;
00513 }
00514 }
00515 }
00516 }
00517
00518
00519
00520
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
00529
00530
00531 entry->mMobileEntry = new SyncEntryMobile(true,"",kabEntry->mPhone,kabEntry->mType,
00532 kabEntry->mName);
00533 mSyncer->mMobileEntries.append(entry->mMobileEntry);
00534
00535
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
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
00568
00569
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 }