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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 00020 As a special exception, permission is given to link this program 00021 with any edition of TQt, and distribute the resulting executable, 00022 without including the source code for TQt in the source distribution. 00023 */ 00024 00025 #include <time.h> 00026 00027 #include <tqlabel.h> 00028 #include <tqlistview.h> 00029 #include <tqfile.h> 00030 #include <tqtextstream.h> 00031 #include <tqmessagebox.h> 00032 00033 #include <tqtextedit.h> 00034 #include <tqgroupbox.h> 00035 #include <tqpushbutton.h> 00036 00037 #include <kdebug.h> 00038 #include <tdefiledialog.h> 00039 #include <tdemessagebox.h> 00040 #include <tdelocale.h> 00041 #include <tdeapplication.h> 00042 #include <kstatusbar.h> 00043 00044 #include <tdeabc/stdaddressbook.h> 00045 00046 #include "modem.h" 00047 #include "atcommand.h" 00048 #include "commandscheduler.h" 00049 00050 #include "mobilegui.h" 00051 #include "mobilegui.moc" 00052 #include "mobilemain.h" 00053 00054 00055 class SyncEntry 00056 { 00057 public: 00058 SyncEntry() 00059 { 00060 mOn = true; 00061 mToBeUpdated = false; 00062 mToBeInserted = false; 00063 } 00064 00065 bool mOn; 00066 bool mToBeUpdated; 00067 bool mToBeInserted; 00068 }; 00069 00070 00071 class SyncEntryKab : public SyncEntry 00072 { 00073 public: 00074 SyncEntryKab( bool on, const TQString &index, const TQString &name, 00075 const TQString &phone ) 00076 { 00077 mOn = on; 00078 00079 mIndex = index; 00080 mName = name; 00081 mPhone = phone; 00082 00083 mKABindex = -1; 00084 mPhoneNumberIndex = -1; 00085 } 00086 00087 TQString mIndex; 00088 TQString mName; 00089 TQString mPhone; 00090 00091 TDEABC::Addressee mAddressee; 00092 int mKABindex; 00093 int mPhoneNumberIndex; 00094 }; 00095 00096 00097 class SyncEntryMobile : public SyncEntry 00098 { 00099 public: 00100 SyncEntryMobile( bool on, const TQString &index, const TQString &phone, 00101 const TQString &name ) 00102 { 00103 mOn = on; 00104 mToBeDeleted = false; 00105 00106 mIndex = index; 00107 mName = name; 00108 mPhone = phone; 00109 } 00110 00111 TQString mIndex; 00112 TQString mName; 00113 TQString mPhone; 00114 00115 bool mToBeDeleted; 00116 }; 00117 00118 00119 class SyncEntryCommon : public SyncEntry 00120 { 00121 public: 00122 SyncEntryCommon( bool on, SyncEntryKab *kabEntry, 00123 SyncEntryMobile *mobileEntry ) 00124 { 00125 mOn = on; 00126 mKabEntry = kabEntry; 00127 mMobileEntry = mobileEntry; 00128 } 00129 00130 SyncEntryKab *mKabEntry; 00131 SyncEntryMobile *mMobileEntry; 00132 }; 00133 00134 00135 class AddressSyncer 00136 { 00137 public: 00138 AddressSyncer() 00139 { 00140 mKabEntries.setAutoDelete( true ); 00141 mMobileEntries.setAutoDelete( true ); 00142 mCommonEntries.setAutoDelete( true ); 00143 } 00144 00145 TQPtrList<SyncEntryKab> mKabEntries; 00146 TQPtrList<SyncEntryMobile> mMobileEntries; 00147 TQPtrList<SyncEntryCommon> mCommonEntries; 00148 }; 00149 00150 00151 class PhoneBookItem : public TQCheckListItem 00152 { 00153 public: 00154 PhoneBookItem( TQListView *v ) : 00155 TQCheckListItem( v, "", TQCheckListItem::CheckBox ) 00156 { 00157 mSyncEntry = 0; 00158 } 00159 00160 PhoneBookItem( TQListView *v, SyncEntry *syncEntry, const TQString &name, 00161 const TQString &phone, const TQString &index ) : 00162 TQCheckListItem( v, index, TQCheckListItem::CheckBox ) 00163 { 00164 mSyncEntry = syncEntry; 00165 00166 setText( 0, name ); 00167 setText( 1, phone ); 00168 setText( 2, index ); 00169 } 00170 00171 SyncEntry *syncEntry() { return mSyncEntry; } 00172 00173 private: 00174 SyncEntry *mSyncEntry; 00175 }; 00176 00177 00178 /* 00179 * Constructs a MobileGui which is a child of 'parent', with the 00180 * name 'name' and widget flags set to 'f' 00181 * 00182 * The dialog will by default be modeless, unless you set 'modal' to 00183 * TRUE to construct a modal dialog. 00184 */ 00185 MobileGui::MobileGui( CommandScheduler *scheduler, KandyPrefs *kprefs, 00186 TQWidget* parent, const char* name, WFlags fl ) : 00187 DCOPObject( "KandyIface" ), MobileGui_base( parent, name, fl ) 00188 { 00189 // Setup links to related classes 00190 mScheduler = scheduler; 00191 mSyncer = new AddressSyncer; 00192 mPrefs = kprefs; 00193 mparent = parent; 00194 00195 // Setup mobile phone specific data 00196 mMobManufacturer = ""; 00197 mMobModel = ""; 00198 mPBStartIndex = 0; 00199 mPBLength = 0; 00200 mPBNameLength = 0; 00201 mPBIndexOccupied.resize( 0, false ); 00202 mMobHasFD = false; 00203 mMobHasLD = false; 00204 mMobHasME = false; 00205 mMobHasMT = false; 00206 mMobHasTA = false; 00207 mMobHasOW = false; 00208 mMobHasMC = false; 00209 mMobHasRC = false; 00210 00211 // Setup status for asynchronous control flow 00212 mLastWriteId = ""; 00213 mComingFromToggleConnection = false; 00214 mComingFromReadPhonebook = false; 00215 mComingFromSyncPhonebooks = false; 00216 mComingFromExit = false; 00217 00218 // Setup initial state of phone books 00219 setKabState( UNLOADED ); 00220 setMobState( UNLOADED ); 00221 00222 // Setup signal handlers 00223 connect( mScheduler, TQT_SIGNAL( commandProcessed( ATCommand * ) ), 00224 TQT_SLOT( processResult( ATCommand * ) ) ); 00225 connect( mScheduler->modem(), TQT_SIGNAL( gotLine( const char * ) ), 00226 TQT_SLOT( termAddOutput( const char * ) ) ); 00227 } 00228 00229 00230 MobileGui::~MobileGui() 00231 { 00232 delete mSyncer; 00233 } 00234 00235 00236 void MobileGui::exit() 00237 { 00238 warnKabState( UNLOADED ); 00239 00240 mComingFromExit = true; 00241 if ( !warnMobState( UNLOADED ) ) { 00242 mComingFromExit = false; 00243 kapp->quit(); 00244 } 00245 } 00246 00247 00248 void MobileGui::readModelInformation() 00249 { 00250 // Read generic manufacturer and model information 00251 mScheduler->executeId( "+cgmi" ); 00252 mScheduler->executeId( "+cgmm" ); 00253 mScheduler->executeId( "+cgmr" ); 00254 mScheduler->executeId( "+cgsn" ); 00255 00256 // Read information about additional phonebook memories 00257 ATCommand *cmd = new ATCommand( "+cpbs=?" ); 00258 cmd->setAutoDelete( true ); 00259 mScheduler->execute( cmd ); 00260 00261 // Select SIM phonebook by default 00262 cmd = new ATCommand( "+cpbs=" ); 00263 cmd->setAutoDelete( true ); 00264 cmd->addParameter( new ATParameter( "SM" ) ); 00265 mScheduler->execute( cmd ); 00266 00267 // Read phonebook properties 00268 mScheduler->executeId( "+cpbr=?" ); 00269 mScheduler->executeId( "+cpbs?" ); 00270 00271 // Set clock 00272 if ( (*mPrefs).autoSetClock() ) 00273 setClock(); 00274 } 00275 00276 00277 void MobileGui::readPhonebook() 00278 { 00279 if ( mMobState == LOADED ) 00280 return; 00281 00282 mComingFromReadPhonebook = true; 00283 if ( !warnMobState( LOADED ) ) { 00284 mComingFromReadPhonebook = false; 00285 TQString tmp = ""; 00286 00287 ATCommand *cmd = new ATCommand( "+cpbr=" ); 00288 cmd->setAutoDelete( true ); 00289 cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) ); 00290 cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex + 00291 mPBLength - 1 ) ) ); 00292 00293 mScheduler->execute( cmd ); 00294 00295 emit statusMessage( i18n( "Reading mobile phonebook..." ) ); 00296 } 00297 } 00298 00299 00300 void MobileGui::writePhonebook() 00301 { 00302 bool ModemCommandScheduled = false; 00303 00304 00305 if ( mMobState != MODIFIED ) 00306 return; 00307 00308 PushButton12->setEnabled( false ); 00309 00310 00311 // 00312 // Remove all entries from data structures which are marked as 00313 // deleted but which are not found on the mobile phone 00314 // 00315 00316 for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { 00317 SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); 00318 00319 00320 if ( entry->mToBeDeleted ) 00321 if ( entry->mIndex.isEmpty() ) { 00322 // The current entry has to be deleted but doesn't come from 00323 // the mobile phone. Hence, it was inserted during phonebook 00324 // synchronisation or so. 00325 // => It is sufficient to remove it from mMobileEntries, no 00326 // ATCommand for deletion needs to be scheduled. 00327 mSyncer->mMobileEntries.remove( i ); 00328 i--; 00329 } else { 00330 // The current entry has to be deleted and stems from the 00331 // mobile phone. First thing to do is to free its associated 00332 // index. This way, its index can be reused for entries which 00333 // have be newly inserted to the mobile phone and we can save 00334 // an explicit ATCommand for deletion and save time & battery 00335 // energy. 00336 uint theIndex = entry->mIndex.toUInt(); 00337 mPBIndexOccupied[ theIndex - mPBStartIndex ] = false; 00338 } 00339 } 00340 00341 00342 // 00343 // Write all elements which need an update to the mobile phone 00344 // 00345 00346 for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { 00347 SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); 00348 TQString id; 00349 00350 00351 // Only process changed items of the mobile phonebook in 00352 // order to save time. 00353 if ( entry->mToBeUpdated || entry->mToBeInserted ) { 00354 TQString tmp = ""; 00355 00356 00357 if ( entry->mToBeUpdated ) { 00358 id = "+cpbw=" + entry->mIndex; 00359 } else { 00360 int index = firstFreeIndex(); 00361 00362 00363 mPBIndexOccupied[ index ] = true; 00364 id = "+cpbw=" + tmp.setNum( index + mPBStartIndex ); 00365 } 00366 mLastWriteId = id; 00367 entry->mToBeUpdated = false; 00368 entry->mToBeInserted = false; 00369 00370 ATCommand *cmd = new ATCommand( id ); 00371 cmd->setAutoDelete( true ); 00372 cmd->addParameter( new ATParameter( quote( entry->mPhone ) ) ); 00373 00374 if ( entry->mPhone.left( 1 ) == "+" ) 00375 cmd->addParameter( new ATParameter( "145" ) ); 00376 else 00377 cmd->addParameter( new ATParameter( "129" ) ); 00378 00379 cmd->addParameter( new ATParameter( 00380 quote( string2GSM( entry->mName ) ) ) ); 00381 00382 mScheduler->execute( cmd ); 00383 ModemCommandScheduled = true; 00384 } 00385 } 00386 00387 00388 // 00389 // As a final step, we need to check again all entries which should be 00390 // deleted. If entries exist stemming from the mobile phone and whose 00391 // index-position was not reused for updating or inserting other entries in 00392 // the previous loop, we need to issue an explicit ATCommand for its deletion. 00393 // 00394 00395 for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { 00396 SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); 00397 00398 00399 if ( entry->mToBeDeleted ) { 00400 uint theIndex = entry->mIndex.toUInt(); 00401 00402 00403 if ( !mPBIndexOccupied[ theIndex - mPBStartIndex ] ) { 00404 // Index of item to be deleted still is 0, so that index position 00405 // wasn't reused. We must delete it explicitly. 00406 TQString id = "+cpbw=" + entry->mIndex; 00407 00408 00409 mLastWriteId = id; 00410 ATCommand *cmd = new ATCommand( id ); 00411 cmd->setAutoDelete( true ); 00412 00413 mScheduler->execute( cmd ); 00414 ModemCommandScheduled = true; 00415 } 00416 00417 // Remove entry from internal data structures 00418 mSyncer->mMobileEntries.remove( i ); 00419 i--; 00420 } 00421 } 00422 00423 if ( ModemCommandScheduled ) 00424 emit statusMessage( i18n( "Writing mobile phonebook..." ) ); 00425 else 00426 writePhonebookPostProcessing(); 00427 } 00428 00429 00430 void MobileGui::writePhonebookPostProcessing() 00431 { 00432 mLastWriteId = ""; 00433 emit transienStatusMessage( i18n( "Wrote mobile phonebook." ) ); 00434 PushButton12->setEnabled( true ); 00435 setMobState( LOADED ); 00436 updateMobileBook(); 00437 00438 if ( mComingFromToggleConnection ) { 00439 mComingFromToggleConnection = false; 00440 disconnectGUI(); 00441 } else 00442 if ( mComingFromReadPhonebook ) { 00443 mComingFromReadPhonebook = false; 00444 TQString tmp = ""; 00445 00446 ATCommand *cmd = new ATCommand( "+cpbr=" ); 00447 cmd->setAutoDelete( true ); 00448 cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) ); 00449 cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex + 00450 mPBLength - 1 ) ) ); 00451 00452 mScheduler->execute( cmd ); 00453 00454 emit statusMessage( i18n( "Reading mobile phonebook..." ) ); 00455 } else 00456 if ( mComingFromExit ) { 00457 mComingFromExit = false; 00458 kapp->quit(); 00459 } 00460 } 00461 00462 00463 void MobileGui::setClock() 00464 { 00465 char *timeStr = new char[50]; 00466 TQString id = "+cclk="; 00467 ATCommand *cmd = new ATCommand( id ); 00468 00469 00470 cmd->setAutoDelete( true ); 00471 00472 time_t tloc; 00473 time( &tloc ); 00474 struct tm *theTime = localtime( &tloc ); 00475 strftime( timeStr, 50, "%y/%m/%d,%T+00", theTime ); 00476 00477 TQString Time = timeStr; 00478 cmd->addParameter( new ATParameter( quote( Time ) ) ); 00479 00480 mScheduler->execute( cmd ); 00481 00482 delete[] timeStr; 00483 } 00484 00485 00486 void MobileGui::readKabc() 00487 { 00488 if ( mKabState == LOADED ) 00489 return; 00490 00491 warnKabState( LOADED ); 00492 00493 emit statusMessage( i18n( "Reading TDE address book..." ) ); 00494 00495 mSyncer->mKabEntries.clear(); 00496 00497 TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self( true ); 00498 TDEABC::AddressBook::Iterator it; 00499 int kabIndex = 0; 00500 00501 for ( it = addressBook->begin(); it != addressBook->end(); 00502 it++, kabIndex++ ) { 00503 TQString index, name; 00504 TDEABC::PhoneNumber phoneNumber; 00505 TDEABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers(); 00506 TDEABC::PhoneNumber::List::Iterator it2; 00507 int phoneNumberIndex = 0; 00508 00509 00510 // Scan all numbers associated with a KAB entry 00511 for ( it2 = phoneNumbers.begin(); it2 != phoneNumbers.end(); 00512 it2++, phoneNumberIndex++ ) { 00513 bool excludeNumber = false; 00514 phoneNumber = (*it2); 00515 TQString phone = phoneNumber.number(); 00516 00517 00518 if ( (*mPrefs).excludeHome() && 00519 ( phoneNumber.type() & TDEABC::PhoneNumber::Home ) ) 00520 excludeNumber = true; 00521 if ( (*mPrefs).excludeWork() && 00522 ( phoneNumber.type() & TDEABC::PhoneNumber::Work ) ) 00523 excludeNumber = true; 00524 if ( (*mPrefs).excludeMessaging() && 00525 ( phoneNumber.type() & TDEABC::PhoneNumber::Msg ) ) 00526 excludeNumber = true; 00527 if ( (*mPrefs).excludeFax() && 00528 ( phoneNumber.type() & TDEABC::PhoneNumber::Fax ) ) 00529 excludeNumber = true; 00530 if ( (*mPrefs).excludeCell() && 00531 ( phoneNumber.type() & TDEABC::PhoneNumber::Cell ) ) 00532 excludeNumber = true; 00533 if ( (*mPrefs).excludeVideo() && 00534 ( phoneNumber.type() & TDEABC::PhoneNumber::Video ) ) 00535 excludeNumber = true; 00536 if ( (*mPrefs).excludeMailbox() && 00537 ( phoneNumber.type() & TDEABC::PhoneNumber::Bbs ) ) 00538 excludeNumber = true; 00539 if ( (*mPrefs).excludeModem() && 00540 ( phoneNumber.type() & TDEABC::PhoneNumber::Modem ) ) 00541 excludeNumber = true; 00542 if ( (*mPrefs).excludeCar() && 00543 ( phoneNumber.type() & TDEABC::PhoneNumber::Car ) ) 00544 excludeNumber = true; 00545 if ( (*mPrefs).excludeISDN() && 00546 ( phoneNumber.type() & TDEABC::PhoneNumber::Isdn ) ) 00547 excludeNumber = true; 00548 if ( (*mPrefs).excludePager() && 00549 ( phoneNumber.type() & TDEABC::PhoneNumber::Pager ) ) 00550 excludeNumber = true; 00551 00552 if ( excludeNumber == false ) { 00553 SyncEntryKab *kabEntry; 00554 00555 00556 index = ""; 00557 name = (*it).familyName(); 00558 00559 TDEABC::AddressBook::Iterator it3; 00560 TDEABC::Addressee::List tmp; 00561 bool firstCharIsUnique = true; 00562 for ( it3 = addressBook->begin(); it3 != addressBook->end(); ++it3 ) 00563 if ( ( (*it3).familyName() == name ) && ( it3 != it ) ) { 00564 tmp.append( (*it3) ); 00565 if ( (*it3).givenName()[0] == (*it).givenName()[0] ) 00566 firstCharIsUnique = false; 00567 } 00568 00569 // There are several KAB entries with the same family name. 00570 // So, we need to append the given name in order to 00571 // distinguish them. 00572 if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) { 00573 name += ", "; 00574 00575 if ( firstCharIsUnique ) 00576 name += (*it).givenName()[0] + "."; 00577 else 00578 name += (*it).givenName(); 00579 } 00580 00581 // Truncate name field if it's too long for mobile phone 00582 if ( name.length() > mPBNameLength ) 00583 name = name.remove( mPBNameLength, name.length() - mPBNameLength ); 00584 00585 // Append Suffix to name if specified in preferences 00586 if ( (*mPrefs).useHomeSuff() && 00587 ( phoneNumber.type() & TDEABC::PhoneNumber::Home ) ) 00588 formatPBName( &name, (*mPrefs).homeSuff() ); 00589 else 00590 if ( (*mPrefs).useWorkSuff() && 00591 ( phoneNumber.type() & TDEABC::PhoneNumber::Work ) ) 00592 formatPBName( &name, (*mPrefs).workSuff() ); 00593 else 00594 if ( (*mPrefs).useMessagingSuff() && 00595 ( phoneNumber.type() & TDEABC::PhoneNumber::Msg ) ) 00596 formatPBName( &name, (*mPrefs).messagingSuff() ); 00597 else 00598 if ( (*mPrefs).useFaxSuff() && 00599 ( phoneNumber.type() & TDEABC::PhoneNumber::Fax ) ) 00600 formatPBName( &name, (*mPrefs).faxSuff() ); 00601 else 00602 if ( (*mPrefs).useCellSuff() && 00603 ( phoneNumber.type() & TDEABC::PhoneNumber::Cell ) ) 00604 formatPBName( &name, (*mPrefs).cellSuff() ); 00605 else 00606 if ( (*mPrefs).useVideoSuff() && 00607 ( phoneNumber.type() & TDEABC::PhoneNumber::Video ) ) 00608 formatPBName( &name, (*mPrefs).videoSuff() ); 00609 else 00610 if ( (*mPrefs).useMailboxSuff() && 00611 ( phoneNumber.type() & TDEABC::PhoneNumber::Bbs ) ) 00612 formatPBName( &name, (*mPrefs).mailboxSuff() ); 00613 else 00614 if ( (*mPrefs).useModemSuff() && 00615 ( phoneNumber.type() & TDEABC::PhoneNumber::Modem ) ) 00616 formatPBName( &name, (*mPrefs).modemSuff() ); 00617 else 00618 if ( (*mPrefs).useCarSuff() && 00619 ( phoneNumber.type() & TDEABC::PhoneNumber::Car ) ) 00620 formatPBName( &name, (*mPrefs).carSuff() ); 00621 else 00622 if ( (*mPrefs).useISDNSuff() && 00623 ( phoneNumber.type() & TDEABC::PhoneNumber::Isdn ) ) 00624 formatPBName( &name, (*mPrefs).iSDNSuff() ); 00625 else 00626 if ( (*mPrefs).usePagerSuff() && 00627 ( phoneNumber.type() & TDEABC::PhoneNumber::Pager ) ) 00628 formatPBName( &name, (*mPrefs).pagerSuff() ); 00629 00630 kabEntry = new SyncEntryKab( true, index, name, phone ); 00631 kabEntry->mKABindex = kabIndex; 00632 kabEntry->mPhoneNumberIndex = phoneNumberIndex; 00633 00634 kabEntry->mAddressee = (*it); 00635 mSyncer->mKabEntries.append( kabEntry ); 00636 } 00637 } 00638 } 00639 00640 // Display KAB entries 00641 updateKabBook(); 00642 00643 emit transienStatusMessage( i18n( "Read TDE address book." ) ); 00644 00645 setKabState( LOADED ); 00646 } 00647 00648 00649 TQString MobileGui::decodeSuffix( const TQString &suffix ) 00650 { 00651 TQString theSuffix = suffix; 00652 00653 00654 // Check whether suffix is quoted. If so, it should be interpreted 00655 // as Hex-Number of a special GSM character. 00656 if ( ( theSuffix.left( 1 ) == "\"" ) && ( theSuffix.right( 1 ) == "\"" ) ) { 00657 TQString tmp = ""; 00658 char suffixNumber = (char) dequote( suffix ).toUInt( 0, 16 ); 00659 tmp += suffixNumber; 00660 00661 theSuffix = GSM2String( tmp ); 00662 } 00663 00664 return theSuffix; 00665 } 00666 00667 00668 void MobileGui::formatPBName( TQString *name, TQString suffix ) 00669 { 00670 TQString theSuffix = decodeSuffix( suffix ); 00671 00672 00673 if ( name->length() + theSuffix.length() > mPBNameLength ) { 00674 // Truncate name field if it's too long for mobile phone 00675 unsigned int toolong = name->length() + theSuffix.length() - mPBNameLength; 00676 (*name) = name->remove( name->length() - toolong, toolong ); 00677 } else 00678 if ( name->length() + theSuffix.length() < mPBNameLength ) 00679 // Add white spaces so that suffix is right justified 00680 while ( name->length() + theSuffix.length() != mPBNameLength ) 00681 (*name) += ' '; 00682 00683 (*name) += theSuffix; 00684 } 00685 00686 00687 TQString MobileGui::stripWhiteSpaces( const TQString &theString ) 00688 { 00689 int pos = 0; 00690 int len = theString.length(); 00691 00692 00693 for ( unsigned int i = 0; i < theString.length(); i++ ) 00694 if ( theString[ i ].latin1() == ' ' ) { 00695 pos++; 00696 len--; 00697 } else 00698 break; 00699 00700 if ( len == 0 ) 00701 return ""; 00702 00703 for ( int i = theString.length() - 1; i >= 0; i-- ) 00704 if ( theString[ i ].latin1() == ' ' ) 00705 len--; 00706 else 00707 break; 00708 00709 return theString.mid( pos, len ); 00710 } 00711 00712 00713 void MobileGui::writeKabc() 00714 { 00715 if ( mKabState != MODIFIED ) 00716 return; 00717 00718 TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self( true ); 00719 TDEABC::Ticket *ticket = addressBook->requestSaveTicket(); 00720 00721 if ( !ticket ) { 00722 kdDebug() << "Error! No ticket to save." << endl; 00723 return; 00724 } 00725 00726 00727 for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) { 00728 SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i ); 00729 TQString phoneNumber = kabEntry->mPhone; 00730 00731 00732 if ( kabEntry->mToBeUpdated ) { 00733 // Find the entry in the KAB which has to be updated 00734 TDEABC::AddressBook::Iterator it = addressBook->begin(); 00735 for ( int KABindex = 0; KABindex != kabEntry->mKABindex; 00736 it++, KABindex++ ) ; 00737 00738 // Find the correct phonenumber of the phonebook entry 00739 TDEABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers(); 00740 TDEABC::PhoneNumber::List::Iterator it2 = phoneNumbers.begin(); 00741 for ( int phoneNumberIndex = 0; 00742 phoneNumberIndex != kabEntry->mPhoneNumberIndex; 00743 it2++, phoneNumberIndex++ ) ; 00744 00745 (*it2).setNumber( phoneNumber ); 00746 (*it).insertPhoneNumber( (*it2) ); 00747 } else 00748 00749 if ( kabEntry->mToBeInserted ) { 00750 int phoneType = 0; 00751 bool goon = true; 00752 TDEABC::AddressBook::Iterator it; 00753 bool equivalentEntryFound = false; 00754 TQString name = kabEntry->mName; 00755 00756 00757 // 00758 // Identify Type of Phonenumber using possibly appended suffixes. 00759 // If a suffix is found, remove it from the name. 00760 // 00761 if ( goon && (*mPrefs).useHomeSuff() ) { 00762 TQString theSuffix = decodeSuffix( (*mPrefs).homeSuff() ); 00763 if ( name.right( theSuffix.length() ) == theSuffix ) { 00764 phoneType = TDEABC::PhoneNumber::Home; 00765 name = stripWhiteSpaces( 00766 name.left( name.length() - theSuffix.length() ) ); 00767 goon = false; 00768 } 00769 } 00770 if ( goon && (*mPrefs).useWorkSuff() ) { 00771 TQString theSuffix = decodeSuffix( (*mPrefs).workSuff() ); 00772 if ( name.right( theSuffix.length() ) == theSuffix ) { 00773 phoneType = TDEABC::PhoneNumber::Work; 00774 name = stripWhiteSpaces( 00775 name.left( name.length() - theSuffix.length() ) ); 00776 goon = false; 00777 } 00778 } 00779 if ( goon && (*mPrefs).useMessagingSuff() ) { 00780 TQString theSuffix = decodeSuffix( (*mPrefs).messagingSuff() ); 00781 if ( name.right( theSuffix.length() ) == theSuffix ) { 00782 phoneType = TDEABC::PhoneNumber::Msg; 00783 name = stripWhiteSpaces( 00784 name.left( name.length() - theSuffix.length() ) ); 00785 goon = false; 00786 } 00787 } 00788 if ( goon && (*mPrefs).useFaxSuff() ) { 00789 TQString theSuffix = decodeSuffix( (*mPrefs).faxSuff() ); 00790 if ( name.right( theSuffix.length() ) == theSuffix ) { 00791 phoneType = TDEABC::PhoneNumber::Fax; 00792 name = stripWhiteSpaces( 00793 name.left( name.length() - theSuffix.length() ) ); 00794 goon = false; 00795 } 00796 } 00797 if ( goon && (*mPrefs).useCellSuff() ) { 00798 TQString theSuffix = decodeSuffix( (*mPrefs).cellSuff() ); 00799 if ( name.right( theSuffix.length() ) == theSuffix ) { 00800 phoneType = TDEABC::PhoneNumber::Cell; 00801 name = stripWhiteSpaces( 00802 name.left( name.length() - theSuffix.length() ) ); 00803 goon = false; 00804 } 00805 } 00806 if ( goon && (*mPrefs).useVideoSuff() ) { 00807 TQString theSuffix = decodeSuffix( (*mPrefs).videoSuff() ); 00808 if ( name.right( theSuffix.length() ) == theSuffix ) { 00809 phoneType = TDEABC::PhoneNumber::Video; 00810 name = stripWhiteSpaces( 00811 name.left( name.length() - theSuffix.length() ) ); 00812 goon = false; 00813 } 00814 } 00815 if ( goon && (*mPrefs).useMailboxSuff() ) { 00816 TQString theSuffix = decodeSuffix( (*mPrefs).mailboxSuff() ); 00817 if ( name.right( theSuffix.length() ) == theSuffix ) { 00818 phoneType = TDEABC::PhoneNumber::Bbs; 00819 name = stripWhiteSpaces( 00820 name.left( name.length() - theSuffix.length() ) ); 00821 goon = false; 00822 } 00823 } 00824 if ( goon && (*mPrefs).useModemSuff() ) { 00825 TQString theSuffix = decodeSuffix( (*mPrefs).modemSuff() ); 00826 if ( name.right( theSuffix.length() ) == theSuffix ) { 00827 phoneType = TDEABC::PhoneNumber::Modem; 00828 name = stripWhiteSpaces( 00829 name.left( name.length() - theSuffix.length() ) ); 00830 goon = false; 00831 } 00832 } 00833 if ( goon && (*mPrefs).useCarSuff() ) { 00834 TQString theSuffix = decodeSuffix( (*mPrefs).carSuff() ); 00835 if ( name.right( theSuffix.length() ) == theSuffix ) { 00836 phoneType = TDEABC::PhoneNumber::Car; 00837 name = stripWhiteSpaces( 00838 name.left( name.length() - theSuffix.length() ) ); 00839 goon = false; 00840 } 00841 } 00842 if ( goon && (*mPrefs).useISDNSuff() ) { 00843 TQString theSuffix = decodeSuffix( (*mPrefs).iSDNSuff() ); 00844 if ( name.right( theSuffix.length() ) == theSuffix ) { 00845 phoneType = TDEABC::PhoneNumber::Isdn; 00846 name = stripWhiteSpaces( 00847 name.left( name.length() - theSuffix.length() ) ); 00848 goon = false; 00849 } 00850 } 00851 if ( goon && (*mPrefs).usePagerSuff() ) { 00852 TQString theSuffix = decodeSuffix( (*mPrefs).pagerSuff() ); 00853 if ( name.right( theSuffix.length() ) == theSuffix ) { 00854 phoneType = TDEABC::PhoneNumber::Pager; 00855 name = stripWhiteSpaces( 00856 name.left( name.length() - theSuffix.length() ) ); 00857 goon = false; 00858 } 00859 } 00860 00861 00862 // 00863 // Search for a KAB entry whose name, if formatted in exactly the 00864 // same way as was done in readKabc, is equal to the actual name. 00865 // 00866 00867 for ( it = addressBook->begin(); it != addressBook->end(); it++ ) { 00868 TQString kabName = (*it).familyName(); 00869 TDEABC::AddressBook::Iterator it3; 00870 TDEABC::Addressee::List tmp; 00871 bool firstCharIsUnique = true; 00872 unsigned int minLength; 00873 00874 00875 for ( it3 = addressBook->begin(); it3 != addressBook->end(); it3++ ) 00876 if ( ( (*it3).familyName() == kabName ) && ( it3 != it ) ) { 00877 tmp.append( (*it3) ); 00878 if ( (*it3).givenName()[0] == (*it).givenName()[0] ) 00879 firstCharIsUnique = false; 00880 } 00881 00882 // There are several KAB entries with the same family name. 00883 // So, we need to append the given name in order to 00884 // distinguish them. 00885 if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) { 00886 kabName += ", "; 00887 00888 if ( firstCharIsUnique ) 00889 kabName += (*it).givenName()[0] + "."; 00890 else 00891 kabName += (*it).givenName(); 00892 } 00893 00894 // Truncate name field if it's too long for mobile phone 00895 if ( kabName.length() > mPBNameLength ) 00896 kabName = kabName.remove( mPBNameLength, 00897 kabName.length() - mPBNameLength ); 00898 00899 minLength = kabName.length(); 00900 if ( name.length() < minLength ) 00901 minLength = name.length(); 00902 00903 if ( name.left( minLength ) == kabName.left( minLength ) ) { 00904 (*it).insertPhoneNumber( TDEABC::PhoneNumber( phoneNumber, 00905 phoneType ) ); 00906 00907 equivalentEntryFound = true; 00908 break; 00909 } 00910 } 00911 00912 // 00913 // If no equivalent entry was found in KAB, we need to generate 00914 // a complete new entry. 00915 // 00916 00917 if ( !equivalentEntryFound ) { 00918 TDEABC::Addressee entry; 00919 TQStringList *fields = new TQStringList; 00920 00921 00922 *fields = TQStringList::split( ',', name ); 00923 00924 if ( fields->count() > 1 ) { 00925 // Name string contains comma separated entry so that we 00926 // need to build family and given names out of them. 00927 TQString givenName = ""; 00928 00929 00930 entry.setFamilyName( stripWhiteSpaces( (*fields)[ 0 ] ) ); 00931 00932 for ( unsigned int i = 1; i < fields->count(); i++ ) 00933 givenName += stripWhiteSpaces( (*fields)[ i ] ) + " "; 00934 entry.setGivenName( stripWhiteSpaces( givenName ) ); 00935 } else 00936 // Name string contains only one string without comma. 00937 entry.setFamilyName( stripWhiteSpaces( name ) ); 00938 00939 entry.insertPhoneNumber( TDEABC::PhoneNumber( phoneNumber, phoneType ) ); 00940 00941 addressBook->insertAddressee( entry ); 00942 } 00943 } 00944 00945 kabEntry->mToBeUpdated = false; 00946 kabEntry->mToBeInserted = false; 00947 } 00948 00949 addressBook->save( ticket ); 00950 00951 emit transienStatusMessage( i18n( "Wrote TDE address book." ) ); 00952 00953 setKabState( LOADED ); 00954 } 00955 00956 00957 void MobileGui::refreshStatus() 00958 { 00959 mScheduler->executeId( "+cbc" ); 00960 mScheduler->executeId( "+csq" ); 00961 } 00962 00963 00964 void MobileGui::processResult( ATCommand *command ) 00965 { 00966 if ( command->id() == "+cbc" ) 00967 mBatteryChargeLabel->setText( command->resultField( 1 ) + " %" ); 00968 else 00969 if ( command->id() == "+csq" ) 00970 mSignalQualityLabel->setText( command->resultField( 0 ) ); 00971 else 00972 if ( command->id() == "+cgmi" ) { 00973 mMobManufacturer = command->resultField( 0 ); 00974 mManufacturerLabel->setText( mMobManufacturer ); 00975 } else 00976 if ( command->id() == "+cgmm" ) { 00977 mMobModel = command->resultField( 0 ); 00978 mModelLabel->setText( mMobModel ); 00979 } else 00980 if ( command->id() == "+cgmr" ) 00981 mGSMVersionLabel->setText( command->resultField( 0 ) ); 00982 else 00983 if ( command->id() == "+cgsn" ) 00984 mSerialNumberLabel->setText( command->resultField( 0 ) ); 00985 else 00986 if ( command->id() == "+cpbr=?" ) 00987 { 00988 TQStringList tmpList = TQStringList::split( "-", command->resultField( 0 ) ); 00989 TQString tmpString = tmpList.first().right( tmpList.first().length() - 1 ); 00990 mPBStartIndex = tmpString.toUInt(); 00991 mPBNameLength = command->resultField( 2 ).toUInt(); 00992 } else 00993 if ( command->id() == "+cpbs?" ) { 00994 mPBLength = command->resultField( 2 ).toUInt(); 00995 00996 // Allocate and initialize memory for the buckets of indices 00997 mPBIndexOccupied.resize( mPBLength, false ); 00998 for ( unsigned int i = 0; i < mPBLength; i++ ) 00999 mPBIndexOccupied[ i ] = false; 01000 } else 01001 if ( command->id() == "+cpbr=" ) { 01002 fillPhonebook( command ); 01003 01004 if ( mComingFromSyncPhonebooks ) { 01005 mComingFromSyncPhonebooks = false; 01006 mergePhonebooks(); 01007 } 01008 } else 01009 if ( command->id() == mLastWriteId ) 01010 writePhonebookPostProcessing(); 01011 else 01012 if ( command->id() == "+cpbs=?" ) { 01013 TQPtrList<TQStringList> *list = command->resultFields(); 01014 TQStringList *fields = list->first(); 01015 01016 01017 while( fields ) { 01018 for ( unsigned int i = 0; i < fields->count(); i++ ) { 01019 TQString memory = dequote( (*fields)[ i ] ); 01020 01021 01022 if ( memory == "FD" ) 01023 mMobHasFD = true; 01024 else 01025 if ( memory == "LD" ) 01026 mMobHasLD = true; 01027 else 01028 if ( memory == "ME" ) 01029 mMobHasME = true; 01030 else 01031 if ( memory == "MT" ) 01032 mMobHasMT = true; 01033 else 01034 if ( memory == "TA" ) 01035 mMobHasTA = true; 01036 else 01037 if ( ( memory == "OW" ) || 01038 ( ( memory == "ON" ) && ( mMobManufacturer == "SIEMENS" ) ) ) 01039 mMobHasOW = true; 01040 else 01041 if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "MC" ) ) 01042 mMobHasMC = true; 01043 else 01044 if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "RC" ) ) 01045 mMobHasRC = true; 01046 } 01047 01048 fields = list->next(); 01049 } 01050 } 01051 } 01052 01053 01054 TQString MobileGui::noSpaces( const TQString &theString ) 01055 { 01056 TQString result = ""; 01057 01058 01059 for ( unsigned int i = 0; i < theString.length(); i++ ) 01060 if ( theString[ i ].latin1() != ' ' ) 01061 result += theString[ i ]; 01062 01063 return result; 01064 } 01065 01066 01067 int MobileGui::firstFreeIndex() 01068 { 01069 unsigned int i; 01070 01071 01072 if ( mPBIndexOccupied.capacity() == 0 ) 01073 return 0; 01074 01075 for ( i = 1; i < mPBLength; i++ ) 01076 if ( !mPBIndexOccupied[ i ] ) 01077 break; 01078 01079 if ( i < mPBLength ) 01080 return i; 01081 01082 return 0; 01083 } 01084 01085 01086 TQString MobileGui::string2GSM( const TQString &theString ) 01087 { 01088 TQString result = ""; 01089 01090 01091 for ( unsigned int i = 0; i < theString.length(); i++ ) 01092 switch ( theString[ i ].latin1() ) { 01093 case 'Ä': result += '['; break; 01094 case 'ä': result += '{'; break; 01095 case 'Ö': result += 92; break; 01096 case 'ö': result += '|'; break; 01097 case 'Ü': result += '^'; break; 01098 case 'ü': result += '~'; break; 01099 case 'ß': result += 30; break; 01100 case 'è': result += 4; break; 01101 case 'é': result += 5; break; 01102 01103 default: result += theString[ i ]; 01104 } 01105 01106 return result; 01107 } 01108 01109 01110 TQString MobileGui::GSM2String( const TQString &theString ) 01111 { 01112 TQString result = ""; 01113 01114 01115 for ( unsigned int i = 0; i < theString.length(); i++ ) 01116 switch ( theString[ i ].latin1() ) { 01117 case '[': result += 'Ä'; break; 01118 case '{': result += 'ä'; break; 01119 case 92: result += 'Ö'; break; 01120 case '|': result += 'ö'; break; 01121 case '^': result += 'Ü'; break; 01122 case '~': result += 'ü'; break; 01123 case 30: result += 'ß'; break; 01124 case 4: result += 'è'; break; 01125 case 5: result += 'é'; break; 01126 01127 default: result += theString[ i ]; 01128 } 01129 01130 return result; 01131 } 01132 01133 01134 void MobileGui::fillPhonebook( ATCommand *cmd ) 01135 { 01136 mSyncer->mMobileEntries.clear(); 01137 01138 TQPtrList<TQStringList> *list = cmd->resultFields(); 01139 TQStringList *fields = list->first(); 01140 01141 while( fields ) { 01142 if ( fields->count() != 4 ) 01143 kdDebug() << "Error! Unexpected number of address fields." << endl; 01144 else { 01145 TQString index = (*fields)[0]; 01146 TQString phone = (*fields)[1]; 01147 TQString type = (*fields)[2]; 01148 TQString name = GSM2String( (*fields)[3] ); 01149 01150 SyncEntryMobile *phoneEntry = new SyncEntryMobile( true, dequote( index ), 01151 dequote( phone ), 01152 dequote( name ) ); 01153 mPBIndexOccupied[ index.toUInt() - mPBStartIndex ] = true; 01154 mSyncer->mMobileEntries.append( phoneEntry ); 01155 } 01156 fields = list->next(); 01157 } 01158 01159 // Display mobile entries 01160 updateMobileBook(); 01161 01162 emit transienStatusMessage(i18n("Read mobile phonebook.")); 01163 emit phonebookRead(); 01164 01165 setMobState( LOADED ); 01166 } 01167 01168 01169 TQString MobileGui::quote( const TQString &str ) 01170 { 01171 if ( ( str.left(1) == "\"" ) && ( str.right(1) == "\"" ) ) 01172 return str; 01173 01174 return "\"" + str + "\""; 01175 } 01176 01177 01178 TQString MobileGui::dequote( const TQString &str ) 01179 { 01180 int pos = 0; 01181 int len = str.length(); 01182 01183 01184 if ( str.left(1) == "\"" ) { 01185 pos = 1; 01186 len --; 01187 } 01188 01189 if ( str.right(1) == "\"" ) 01190 len--; 01191 01192 return str.mid( pos, len ); 01193 } 01194 01195 01196 void MobileGui::savePhonebook() 01197 { 01198 if ( mMobState == UNLOADED ) 01199 return; 01200 01201 TQString fileName = KFileDialog::getSaveFileName( "phonebook.csv" ); 01202 TQFile outFile( fileName ); 01203 01204 if ( outFile.open( IO_WriteOnly ) ) { 01205 TQTextStream t( &outFile ); // use a text stream 01206 01207 for( uint i = 0; i < mSyncer->mMobileEntries.count(); i++) { 01208 SyncEntryMobile *e = mSyncer->mMobileEntries.at( i ); 01209 01210 01211 if ( !e->mToBeDeleted ) 01212 t << e->mIndex << "," << e->mPhone << "," << e->mName << endl; 01213 } 01214 01215 outFile.close(); 01216 } 01217 } 01218 01219 01220 void MobileGui::deleteMobPhonebook() 01221 { 01222 01223 // 01224 // Process all elements selected in the GUI 01225 // 01226 01227 PhoneBookItem *item = (PhoneBookItem *) mMobileBook->firstChild(); 01228 while ( item ) { 01229 if ( item->isOn() ) { 01230 SyncEntryMobile *mobileItem = (SyncEntryMobile *) item->syncEntry(); 01231 01232 01233 // Deselect current item 01234 item->setOn( false ); 01235 mobileItem->mOn = false; 01236 01237 // Mark current item as deleted 01238 mobileItem->mToBeDeleted = true; 01239 } 01240 01241 item = (PhoneBookItem *) item->nextSibling(); 01242 } 01243 01244 // Update GUI 01245 updateMobileBook(); 01246 setMobState( MODIFIED ); 01247 } 01248 01249 01250 void MobileGui::mergePhonebooks() 01251 { 01252 uint i; 01253 01254 01255 // 01256 // Transfer current Selection State from GUI to mSyncer 01257 // 01258 01259 PhoneBookItem *item = (PhoneBookItem *) mKabBook->firstChild(); 01260 while ( item ) { 01261 item->syncEntry()->mOn = item->isOn(); 01262 item = (PhoneBookItem *) item->nextSibling(); 01263 } 01264 01265 item = (PhoneBookItem *) mMobileBook->firstChild(); 01266 while ( item ) { 01267 item->syncEntry()->mOn = item->isOn(); 01268 item = (PhoneBookItem *) item->nextSibling(); 01269 } 01270 01271 mSyncer->mCommonEntries.clear(); 01272 01273 01274 // 01275 // Put TDE Address Book list into Common List 01276 // 01277 01278 for ( i = 0; i < mSyncer->mKabEntries.count(); i++ ) 01279 if ( mSyncer->mKabEntries.at( i )->mOn ) { 01280 mSyncer->mCommonEntries.append( 01281 new SyncEntryCommon( true, mSyncer->mKabEntries.at( i ), 0 ) ); 01282 mSyncer->mKabEntries.at( i )->mOn = false; 01283 } 01284 01285 01286 // 01287 // Put Mobile Address Book list into Common List; Merge equivalent entries 01288 // 01289 01290 for ( i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { 01291 SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at( i ); 01292 bool equivalentEntryFound = false; 01293 uint j; 01294 01295 01296 if( !mobileEntry->mToBeDeleted ) 01297 for ( j = 0; j < mSyncer->mCommonEntries.count(); j++ ) { 01298 SyncEntryCommon *theCommonEntry = mSyncer->mCommonEntries.at( j ); 01299 01300 01301 if ( theCommonEntry->mKabEntry && 01302 ( theCommonEntry->mKabEntry->mName == mobileEntry->mName ) ) { 01303 theCommonEntry->mMobileEntry = mobileEntry; 01304 equivalentEntryFound = true; 01305 01306 if ( noSpaces( theCommonEntry->mKabEntry->mPhone ) == 01307 mobileEntry->mPhone ) { 01308 mobileEntry->mOn = false; 01309 break; 01310 } else { 01311 // Conflict: 2 Entries have same name but different numbers. 01312 // Prompt user. 01313 TQString text = "<qt><b>" + i18n( "Kab Entry:" ) + "</b><br>"; 01314 text += " " + theCommonEntry->mKabEntry->mName + " " + 01315 theCommonEntry->mKabEntry->mPhone + "<br>"; 01316 text += "<b>" + i18n( "Mobile Entry:" ) + "</b><br>"; 01317 text += " " + mobileEntry->mName + " " + mobileEntry->mPhone; 01318 text += "</qt>"; 01319 01320 TQMessageBox *msg = 01321 new TQMessageBox( i18n( "Conflicting Entries" ), text, 01322 TQMessageBox::Warning, 1, 2, 0, this ); 01323 msg->setButtonText( 1, i18n( "Use Kab Entry" ) ); 01324 msg->setButtonText( 2, i18n( "Use Mobile Entry" ) ); 01325 01326 switch ( msg->exec() ) { 01327 case 1: 01328 // Use TDE Address Book Entry 01329 mobileEntry->mPhone = theCommonEntry->mKabEntry->mPhone; 01330 mobileEntry->mName = theCommonEntry->mKabEntry->mName; 01331 mobileEntry->mOn = true; 01332 mobileEntry->mToBeUpdated = true; 01333 01334 setMobState( MODIFIED ); 01335 break; 01336 01337 case 2: 01338 // Use Mobile Address Book Entry 01339 theCommonEntry->mKabEntry->mPhone = mobileEntry->mPhone; 01340 theCommonEntry->mKabEntry->mName = mobileEntry->mName; 01341 theCommonEntry->mKabEntry->mOn = true; 01342 theCommonEntry->mKabEntry->mToBeUpdated = true; 01343 01344 mobileEntry->mOn = false; 01345 01346 setKabState( MODIFIED ); 01347 break; 01348 } 01349 } 01350 } 01351 } 01352 01353 if ( !equivalentEntryFound && mobileEntry->mOn ) { 01354 // No equivalent entry exists; generate a new one. 01355 mSyncer->mCommonEntries.append( 01356 new SyncEntryCommon( true, 0, mobileEntry ) ); 01357 mobileEntry->mOn = false; 01358 } 01359 } 01360 01361 01362 // 01363 // Create new KAB and Mobile Entries 01364 // 01365 01366 for ( i = 0; i < mSyncer->mCommonEntries.count(); i++ ) { 01367 SyncEntryCommon *entry = mSyncer->mCommonEntries.at( i ); 01368 SyncEntryKab *kabEntry = entry->mKabEntry; 01369 SyncEntryMobile *mobileEntry = entry->mMobileEntry; 01370 01371 01372 if ( kabEntry && !mobileEntry ) { 01373 // Create Mobile Entry 01374 entry->mMobileEntry = new SyncEntryMobile( true, "", kabEntry->mPhone, 01375 kabEntry->mName ); 01376 entry->mMobileEntry->mToBeInserted = true; 01377 mSyncer->mMobileEntries.append( entry->mMobileEntry ); 01378 01379 setMobState( MODIFIED ); 01380 } else 01381 if ( mobileEntry && !kabEntry ) { 01382 // Create KAB Entry 01383 entry->mKabEntry = new SyncEntryKab( true, mobileEntry->mIndex, 01384 mobileEntry->mName, 01385 mobileEntry->mPhone ); 01386 entry->mKabEntry->mToBeInserted = true; 01387 mSyncer->mKabEntries.append( entry->mKabEntry ); 01388 01389 setKabState( MODIFIED ); 01390 } 01391 } 01392 01393 01394 // 01395 // Update GUI 01396 // 01397 01398 updateKabBook(); 01399 updateMobileBook(); 01400 01401 emit transienStatusMessage( i18n( "Synced phonebooks." ) ); 01402 PushButton8_3->setEnabled( true ); 01403 } 01404 01405 01406 void MobileGui::syncPhonebooks() 01407 { 01408 PushButton8_3->setEnabled( false ); 01409 01410 if ( mKabState == UNLOADED ) 01411 readKabc(); 01412 if ( mMobState == UNLOADED ) { 01413 mComingFromSyncPhonebooks = true; 01414 readPhonebook(); 01415 } else 01416 mergePhonebooks(); 01417 } 01418 01419 01420 void MobileGui::updateKabBook() 01421 { 01422 mKabBook->clear(); 01423 01424 for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) { 01425 SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i ); 01426 PhoneBookItem *item = new PhoneBookItem( mKabBook, kabEntry, 01427 kabEntry->mName, kabEntry->mPhone, 01428 kabEntry->mIndex ); 01429 item->setOn( kabEntry->mOn ); 01430 } 01431 } 01432 01433 01434 void MobileGui::updateMobileBook() 01435 { 01436 mMobileBook->clear(); 01437 01438 for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { 01439 SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); 01440 01441 if ( !entry->mToBeDeleted ) { 01442 PhoneBookItem *item = new PhoneBookItem( mMobileBook, entry, entry->mName, 01443 entry->mPhone, entry->mIndex ); 01444 item->setOn( entry->mOn ); 01445 } 01446 } 01447 } 01448 01449 01450 void MobileGui::toggleConnection() 01451 { 01452 if ( mConnectButton->text() == i18n( "Connect" ) ) { 01453 emit connectModem(); 01454 01455 readModelInformation(); 01456 refreshStatus(); 01457 01458 mConnectButton->setText( tr2i18n( "Disconnect" ) ); 01459 PushButton1->setEnabled( true ); 01460 PushButton5_3->setEnabled( true ); 01461 01462 mABTab->setEnabled( true ); 01463 setKabState( UNLOADED ); 01464 setMobState( UNLOADED ); 01465 01466 ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Connected "), 1 ); 01467 } else { 01468 warnKabState( UNLOADED ); 01469 01470 mComingFromToggleConnection = true; 01471 if ( !warnMobState( UNLOADED ) ) { 01472 mComingFromToggleConnection = false; 01473 disconnectGUI(); 01474 } 01475 } 01476 } 01477 01478 01479 void MobileGui::disconnectGUI() 01480 { 01481 emit disconnectModem(); 01482 01483 mManufacturerLabel->setText( "x" ); 01484 mModelLabel->setText( "x" ); 01485 mGSMVersionLabel->setText( "x" ); 01486 mSerialNumberLabel->setText( "x" ); 01487 01488 mBatteryChargeLabel->setText( "xx %" ); 01489 mSignalQualityLabel->setText( "x" ); 01490 01491 mConnectButton->setText( tr2i18n( "Connect" ) ); 01492 PushButton1->setEnabled( false ); 01493 PushButton5_3->setEnabled( false ); 01494 01495 mKabBook->clear(); 01496 mMobileBook->clear(); 01497 setKabState( UNLOADED ); 01498 setMobState( UNLOADED ); 01499 01500 mABTab->setEnabled( false ); 01501 01502 mMobHasFD = false; 01503 mMobHasLD = false; 01504 mMobHasME = false; 01505 mMobHasMT = false; 01506 mMobHasTA = false; 01507 mMobHasOW = false; 01508 mMobHasMC = false; 01509 mMobHasRC = false; 01510 01511 mPBIndexOccupied.resize( 0, false ); 01512 01513 ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Disconnected "), 01514 1 ); 01515 } 01516 01517 01518 void MobileGui::termAddOutput( const char *line ) 01519 { 01520 mTermIO->append( line ); 01521 mTermIO->setCursorPosition( mTermIO->paragraphs() - 1, 0 ); 01522 } 01523 01524 01525 void MobileGui::setKabState( ABState newState ) 01526 { 01527 switch ( mKabState ) { 01528 case UNLOADED: 01529 groupBox3->setTitle( tr2i18n( "TDE Address Book" ) ); 01530 mReadKabButton->setEnabled( true ); 01531 PushButton8->setEnabled( false ); 01532 break; 01533 01534 case LOADED: 01535 if ( newState == MODIFIED ) { 01536 groupBox3->setTitle( tr2i18n( "TDE Address Book (modified)" ) ); 01537 mReadKabButton->setEnabled( true ); 01538 PushButton8->setEnabled( true ); 01539 } else 01540 if ( newState == UNLOADED ) { 01541 groupBox3->setTitle( tr2i18n( "TDE Address Book" ) ); 01542 mReadKabButton->setEnabled( true ); 01543 PushButton8->setEnabled( false ); 01544 } 01545 break; 01546 01547 case MODIFIED: 01548 if ( newState != MODIFIED ) { 01549 groupBox3->setTitle( tr2i18n( "TDE Address Book" ) ); 01550 mReadKabButton->setEnabled( true ); 01551 PushButton8->setEnabled( false ); 01552 } 01553 break; 01554 } 01555 01556 mKabState = newState; 01557 } 01558 01559 01560 void MobileGui::warnKabState( ABState newState ) 01561 { 01562 if ( ( mKabState == MODIFIED ) && ( newState != MODIFIED ) ) { 01563 TQString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>"; 01564 text += i18n( "The TDE address book contains unsaved changes." ) + 01565 "<br></qt>"; 01566 01567 TQMessageBox *msg = new TQMessageBox( i18n( "Unsaved Changes" ), text, 01568 TQMessageBox::Critical, 1, 2, 0, this ); 01569 msg->setButtonText( 1, i18n( "Save" ) ); 01570 msg->setButtonText( 2, i18n( "Discard" ) ); 01571 01572 switch ( msg->exec() ) { 01573 case 1: 01574 // Save Changes first 01575 writeKabc(); 01576 break; 01577 01578 case 2: 01579 break; 01580 } 01581 } 01582 } 01583 01584 01585 void MobileGui::setMobState( ABState newState ) 01586 { 01587 switch ( mMobState ) { 01588 case UNLOADED: 01589 if ( newState == UNLOADED ) { 01590 groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); 01591 PushButton3->setEnabled( true ); 01592 PushButton12->setEnabled( false ); 01593 PushButton4_2->setEnabled( false ); 01594 MobDeleteButton->setEnabled( false ); 01595 } else 01596 if ( newState == LOADED ) { 01597 groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); 01598 PushButton3->setEnabled( true ); 01599 PushButton12->setEnabled( false ); 01600 PushButton4_2->setEnabled( true ); 01601 MobDeleteButton->setEnabled( true ); 01602 } 01603 break; 01604 01605 case LOADED: 01606 if ( newState == MODIFIED ) { 01607 groupBox4->setTitle( tr2i18n( "Mobile Phone Book (modified)" ) ); 01608 PushButton3->setEnabled( true ); 01609 PushButton12->setEnabled( true ); 01610 PushButton4_2->setEnabled( true ); 01611 MobDeleteButton->setEnabled( true ); 01612 } else 01613 if ( newState == UNLOADED ) { 01614 groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); 01615 PushButton3->setEnabled( true ); 01616 PushButton12->setEnabled( false ); 01617 PushButton4_2->setEnabled( false ); 01618 MobDeleteButton->setEnabled( false ); 01619 } 01620 break; 01621 01622 case MODIFIED: 01623 if ( newState == UNLOADED ) { 01624 groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); 01625 PushButton3->setEnabled( true ); 01626 PushButton12->setEnabled( false ); 01627 PushButton4_2->setEnabled( false ); 01628 MobDeleteButton->setEnabled( false ); 01629 } else 01630 if ( newState == LOADED ) { 01631 groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); 01632 PushButton3->setEnabled( true ); 01633 PushButton12->setEnabled( false ); 01634 PushButton4_2->setEnabled( true ); 01635 MobDeleteButton->setEnabled( true ); 01636 } 01637 break; 01638 } 01639 01640 mMobState = newState; 01641 } 01642 01643 01644 bool MobileGui::warnMobState( ABState newState ) 01645 { 01646 if ( ( mMobState == MODIFIED ) && ( newState != MODIFIED ) ) 01647 { 01648 TQString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>"; 01649 text += i18n( "The mobile phone book contains unsaved changes." ) + 01650 "<br></qt>"; 01651 01652 TQMessageBox *msg = new TQMessageBox( i18n( "Unsaved Changes" ), text, 01653 TQMessageBox::Critical, 1, 2, 0, this ); 01654 msg->setButtonText( 1, i18n( "Save" ) ); 01655 msg->setButtonText( 2, i18n( "Discard" ) ); 01656 01657 switch ( msg->exec() ) { 01658 case 1: 01659 // Save Changes first 01660 writePhonebook(); 01661 return true; 01662 break; 01663 01664 case 2: 01665 return false; 01666 break; 01667 } 01668 } 01669 01670 return false; 01671 }