kandy

mobilegui.cpp
1 /*
2  This file is part of Kandy.
3 
4  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20  As a special exception, permission is given to link this program
21  with any edition of TQt, and distribute the resulting executable,
22  without including the source code for TQt in the source distribution.
23 */
24 
25 #include <time.h>
26 
27 #include <tqlabel.h>
28 #include <tqlistview.h>
29 #include <tqfile.h>
30 #include <tqtextstream.h>
31 #include <tqmessagebox.h>
32 
33 #include <tqtextedit.h>
34 #include <tqgroupbox.h>
35 #include <tqpushbutton.h>
36 
37 #include <kdebug.h>
38 #include <tdefiledialog.h>
39 #include <tdemessagebox.h>
40 #include <tdelocale.h>
41 #include <tdeapplication.h>
42 #include <kstatusbar.h>
43 
44 #include <tdeabc/stdaddressbook.h>
45 
46 #include "modem.h"
47 #include "atcommand.h"
48 #include "commandscheduler.h"
49 
50 #include "mobilegui.h"
51 #include "mobilegui.moc"
52 #include "mobilemain.h"
53 
54 
55 class SyncEntry
56 {
57  public:
58  SyncEntry()
59  {
60  mOn = true;
61  mToBeUpdated = false;
62  mToBeInserted = false;
63  }
64 
65  bool mOn;
66  bool mToBeUpdated;
67  bool mToBeInserted;
68 };
69 
70 
71 class SyncEntryKab : public SyncEntry
72 {
73  public:
74  SyncEntryKab( bool on, const TQString &index, const TQString &name,
75  const TQString &phone )
76  {
77  mOn = on;
78 
79  mIndex = index;
80  mName = name;
81  mPhone = phone;
82 
83  mKABindex = -1;
84  mPhoneNumberIndex = -1;
85  }
86 
87  TQString mIndex;
88  TQString mName;
89  TQString mPhone;
90 
91  TDEABC::Addressee mAddressee;
92  int mKABindex;
93  int mPhoneNumberIndex;
94 };
95 
96 
97 class SyncEntryMobile : public SyncEntry
98 {
99  public:
100  SyncEntryMobile( bool on, const TQString &index, const TQString &phone,
101  const TQString &name )
102  {
103  mOn = on;
104  mToBeDeleted = false;
105 
106  mIndex = index;
107  mName = name;
108  mPhone = phone;
109  }
110 
111  TQString mIndex;
112  TQString mName;
113  TQString mPhone;
114 
115  bool mToBeDeleted;
116 };
117 
118 
119 class SyncEntryCommon : public SyncEntry
120 {
121  public:
122  SyncEntryCommon( bool on, SyncEntryKab *kabEntry,
123  SyncEntryMobile *mobileEntry )
124  {
125  mOn = on;
126  mKabEntry = kabEntry;
127  mMobileEntry = mobileEntry;
128  }
129 
130  SyncEntryKab *mKabEntry;
131  SyncEntryMobile *mMobileEntry;
132 };
133 
134 
135 class AddressSyncer
136 {
137  public:
138  AddressSyncer()
139  {
140  mKabEntries.setAutoDelete( true );
141  mMobileEntries.setAutoDelete( true );
142  mCommonEntries.setAutoDelete( true );
143  }
144 
145  TQPtrList<SyncEntryKab> mKabEntries;
146  TQPtrList<SyncEntryMobile> mMobileEntries;
147  TQPtrList<SyncEntryCommon> mCommonEntries;
148 };
149 
150 
151 class PhoneBookItem : public TQCheckListItem
152 {
153  public:
154  PhoneBookItem( TQListView *v ) :
155  TQCheckListItem( v, "", TQCheckListItem::CheckBox )
156  {
157  mSyncEntry = 0;
158  }
159 
160  PhoneBookItem( TQListView *v, SyncEntry *syncEntry, const TQString &name,
161  const TQString &phone, const TQString &index ) :
162  TQCheckListItem( v, index, TQCheckListItem::CheckBox )
163  {
164  mSyncEntry = syncEntry;
165 
166  setText( 0, name );
167  setText( 1, phone );
168  setText( 2, index );
169  }
170 
171  SyncEntry *syncEntry() { return mSyncEntry; }
172 
173  private:
174  SyncEntry *mSyncEntry;
175 };
176 
177 
178 /*
179  * Constructs a MobileGui which is a child of 'parent', with the
180  * name 'name' and widget flags set to 'f'
181  *
182  * The dialog will by default be modeless, unless you set 'modal' to
183  * TRUE to construct a modal dialog.
184  */
185 MobileGui::MobileGui( CommandScheduler *scheduler, KandyPrefs *kprefs,
186  TQWidget* parent, const char* name, WFlags fl ) :
187  DCOPObject( "KandyIface" ), MobileGui_base( parent, name, fl )
188 {
189  // Setup links to related classes
190  mScheduler = scheduler;
191  mSyncer = new AddressSyncer;
192  mPrefs = kprefs;
193  mparent = parent;
194 
195  // Setup mobile phone specific data
196  mMobManufacturer = "";
197  mMobModel = "";
198  mPBStartIndex = 0;
199  mPBLength = 0;
200  mPBNameLength = 0;
201  mPBIndexOccupied.resize( 0, false );
202  mMobHasFD = false;
203  mMobHasLD = false;
204  mMobHasME = false;
205  mMobHasMT = false;
206  mMobHasTA = false;
207  mMobHasOW = false;
208  mMobHasMC = false;
209  mMobHasRC = false;
210 
211  // Setup status for asynchronous control flow
212  mLastWriteId = "";
213  mComingFromToggleConnection = false;
214  mComingFromReadPhonebook = false;
215  mComingFromSyncPhonebooks = false;
216  mComingFromExit = false;
217 
218  // Setup initial state of phone books
219  setKabState( UNLOADED );
220  setMobState( UNLOADED );
221 
222  // Setup signal handlers
223  connect( mScheduler, TQ_SIGNAL( commandProcessed( ATCommand * ) ),
224  TQ_SLOT( processResult( ATCommand * ) ) );
225  connect( mScheduler->modem(), TQ_SIGNAL( gotLine( const char * ) ),
226  TQ_SLOT( termAddOutput( const char * ) ) );
227 }
228 
229 
230 MobileGui::~MobileGui()
231 {
232  delete mSyncer;
233 }
234 
235 
236 void MobileGui::exit()
237 {
238  warnKabState( UNLOADED );
239 
240  mComingFromExit = true;
241  if ( !warnMobState( UNLOADED ) ) {
242  mComingFromExit = false;
243  kapp->quit();
244  }
245 }
246 
247 
248 void MobileGui::readModelInformation()
249 {
250  // Read generic manufacturer and model information
251  mScheduler->executeId( "+cgmi" );
252  mScheduler->executeId( "+cgmm" );
253  mScheduler->executeId( "+cgmr" );
254  mScheduler->executeId( "+cgsn" );
255 
256  // Read information about additional phonebook memories
257  ATCommand *cmd = new ATCommand( "+cpbs=?" );
258  cmd->setAutoDelete( true );
259  mScheduler->execute( cmd );
260 
261  // Select SIM phonebook by default
262  cmd = new ATCommand( "+cpbs=" );
263  cmd->setAutoDelete( true );
264  cmd->addParameter( new ATParameter( "SM" ) );
265  mScheduler->execute( cmd );
266 
267  // Read phonebook properties
268  mScheduler->executeId( "+cpbr=?" );
269  mScheduler->executeId( "+cpbs?" );
270 
271  // Set clock
272  if ( (*mPrefs).autoSetClock() )
273  setClock();
274 }
275 
276 
277 void MobileGui::readPhonebook()
278 {
279  if ( mMobState == LOADED )
280  return;
281 
282  mComingFromReadPhonebook = true;
283  if ( !warnMobState( LOADED ) ) {
284  mComingFromReadPhonebook = false;
285  TQString tmp = "";
286 
287  ATCommand *cmd = new ATCommand( "+cpbr=" );
288  cmd->setAutoDelete( true );
289  cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) );
290  cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex +
291  mPBLength - 1 ) ) );
292 
293  mScheduler->execute( cmd );
294 
295  emit statusMessage( i18n( "Reading mobile phonebook..." ) );
296  }
297 }
298 
299 
300 void MobileGui::writePhonebook()
301 {
302  bool ModemCommandScheduled = false;
303 
304 
305  if ( mMobState != MODIFIED )
306  return;
307 
308  PushButton12->setEnabled( false );
309 
310 
311  //
312  // Remove all entries from data structures which are marked as
313  // deleted but which are not found on the mobile phone
314  //
315 
316  for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
317  SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
318 
319 
320  if ( entry->mToBeDeleted )
321  if ( entry->mIndex.isEmpty() ) {
322  // The current entry has to be deleted but doesn't come from
323  // the mobile phone. Hence, it was inserted during phonebook
324  // synchronisation or so.
325  // => It is sufficient to remove it from mMobileEntries, no
326  // ATCommand for deletion needs to be scheduled.
327  mSyncer->mMobileEntries.remove( i );
328  i--;
329  } else {
330  // The current entry has to be deleted and stems from the
331  // mobile phone. First thing to do is to free its associated
332  // index. This way, its index can be reused for entries which
333  // have be newly inserted to the mobile phone and we can save
334  // an explicit ATCommand for deletion and save time & battery
335  // energy.
336  uint theIndex = entry->mIndex.toUInt();
337  mPBIndexOccupied[ theIndex - mPBStartIndex ] = false;
338  }
339  }
340 
341 
342  //
343  // Write all elements which need an update to the mobile phone
344  //
345 
346  for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
347  SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
348  TQString id;
349 
350 
351  // Only process changed items of the mobile phonebook in
352  // order to save time.
353  if ( entry->mToBeUpdated || entry->mToBeInserted ) {
354  TQString tmp = "";
355 
356 
357  if ( entry->mToBeUpdated ) {
358  id = "+cpbw=" + entry->mIndex;
359  } else {
360  int index = firstFreeIndex();
361 
362 
363  mPBIndexOccupied[ index ] = true;
364  id = "+cpbw=" + tmp.setNum( index + mPBStartIndex );
365  }
366  mLastWriteId = id;
367  entry->mToBeUpdated = false;
368  entry->mToBeInserted = false;
369 
370  ATCommand *cmd = new ATCommand( id );
371  cmd->setAutoDelete( true );
372  cmd->addParameter( new ATParameter( quote( entry->mPhone ) ) );
373 
374  if ( entry->mPhone.left( 1 ) == "+" )
375  cmd->addParameter( new ATParameter( "145" ) );
376  else
377  cmd->addParameter( new ATParameter( "129" ) );
378 
379  cmd->addParameter( new ATParameter(
380  quote( string2GSM( entry->mName ) ) ) );
381 
382  mScheduler->execute( cmd );
383  ModemCommandScheduled = true;
384  }
385  }
386 
387 
388  //
389  // As a final step, we need to check again all entries which should be
390  // deleted. If entries exist stemming from the mobile phone and whose
391  // index-position was not reused for updating or inserting other entries in
392  // the previous loop, we need to issue an explicit ATCommand for its deletion.
393  //
394 
395  for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
396  SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
397 
398 
399  if ( entry->mToBeDeleted ) {
400  uint theIndex = entry->mIndex.toUInt();
401 
402 
403  if ( !mPBIndexOccupied[ theIndex - mPBStartIndex ] ) {
404  // Index of item to be deleted still is 0, so that index position
405  // wasn't reused. We must delete it explicitly.
406  TQString id = "+cpbw=" + entry->mIndex;
407 
408 
409  mLastWriteId = id;
410  ATCommand *cmd = new ATCommand( id );
411  cmd->setAutoDelete( true );
412 
413  mScheduler->execute( cmd );
414  ModemCommandScheduled = true;
415  }
416 
417  // Remove entry from internal data structures
418  mSyncer->mMobileEntries.remove( i );
419  i--;
420  }
421  }
422 
423  if ( ModemCommandScheduled )
424  emit statusMessage( i18n( "Writing mobile phonebook..." ) );
425  else
426  writePhonebookPostProcessing();
427 }
428 
429 
430 void MobileGui::writePhonebookPostProcessing()
431 {
432  mLastWriteId = "";
433  emit transienStatusMessage( i18n( "Wrote mobile phonebook." ) );
434  PushButton12->setEnabled( true );
435  setMobState( LOADED );
436  updateMobileBook();
437 
438  if ( mComingFromToggleConnection ) {
439  mComingFromToggleConnection = false;
440  disconnectGUI();
441  } else
442  if ( mComingFromReadPhonebook ) {
443  mComingFromReadPhonebook = false;
444  TQString tmp = "";
445 
446  ATCommand *cmd = new ATCommand( "+cpbr=" );
447  cmd->setAutoDelete( true );
448  cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) );
449  cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex +
450  mPBLength - 1 ) ) );
451 
452  mScheduler->execute( cmd );
453 
454  emit statusMessage( i18n( "Reading mobile phonebook..." ) );
455  } else
456  if ( mComingFromExit ) {
457  mComingFromExit = false;
458  kapp->quit();
459  }
460 }
461 
462 
463 void MobileGui::setClock()
464 {
465  char *timeStr = new char[50];
466  TQString id = "+cclk=";
467  ATCommand *cmd = new ATCommand( id );
468 
469 
470  cmd->setAutoDelete( true );
471 
472  time_t tloc;
473  time( &tloc );
474  struct tm *theTime = localtime( &tloc );
475  strftime( timeStr, 50, "%y/%m/%d,%T+00", theTime );
476 
477  TQString Time = timeStr;
478  cmd->addParameter( new ATParameter( quote( Time ) ) );
479 
480  mScheduler->execute( cmd );
481 
482  delete[] timeStr;
483 }
484 
485 
486 void MobileGui::readKabc()
487 {
488  if ( mKabState == LOADED )
489  return;
490 
491  warnKabState( LOADED );
492 
493  emit statusMessage( i18n( "Reading TDE address book..." ) );
494 
495  mSyncer->mKabEntries.clear();
496 
497  TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self( true );
498  TDEABC::AddressBook::Iterator it;
499  int kabIndex = 0;
500 
501  for ( it = addressBook->begin(); it != addressBook->end();
502  it++, kabIndex++ ) {
503  TQString index, name;
504  TDEABC::PhoneNumber phoneNumber;
505  TDEABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers();
506  TDEABC::PhoneNumber::List::Iterator it2;
507  int phoneNumberIndex = 0;
508 
509 
510  // Scan all numbers associated with a KAB entry
511  for ( it2 = phoneNumbers.begin(); it2 != phoneNumbers.end();
512  it2++, phoneNumberIndex++ ) {
513  bool excludeNumber = false;
514  phoneNumber = (*it2);
515  TQString phone = phoneNumber.number();
516 
517 
518  if ( (*mPrefs).excludeHome() &&
519  ( phoneNumber.type() & TDEABC::PhoneNumber::Home ) )
520  excludeNumber = true;
521  if ( (*mPrefs).excludeWork() &&
522  ( phoneNumber.type() & TDEABC::PhoneNumber::Work ) )
523  excludeNumber = true;
524  if ( (*mPrefs).excludeMessaging() &&
525  ( phoneNumber.type() & TDEABC::PhoneNumber::Msg ) )
526  excludeNumber = true;
527  if ( (*mPrefs).excludeFax() &&
528  ( phoneNumber.type() & TDEABC::PhoneNumber::Fax ) )
529  excludeNumber = true;
530  if ( (*mPrefs).excludeCell() &&
531  ( phoneNumber.type() & TDEABC::PhoneNumber::Cell ) )
532  excludeNumber = true;
533  if ( (*mPrefs).excludeVideo() &&
534  ( phoneNumber.type() & TDEABC::PhoneNumber::Video ) )
535  excludeNumber = true;
536  if ( (*mPrefs).excludeMailbox() &&
537  ( phoneNumber.type() & TDEABC::PhoneNumber::Bbs ) )
538  excludeNumber = true;
539  if ( (*mPrefs).excludeModem() &&
540  ( phoneNumber.type() & TDEABC::PhoneNumber::Modem ) )
541  excludeNumber = true;
542  if ( (*mPrefs).excludeCar() &&
543  ( phoneNumber.type() & TDEABC::PhoneNumber::Car ) )
544  excludeNumber = true;
545  if ( (*mPrefs).excludeISDN() &&
546  ( phoneNumber.type() & TDEABC::PhoneNumber::Isdn ) )
547  excludeNumber = true;
548  if ( (*mPrefs).excludePager() &&
549  ( phoneNumber.type() & TDEABC::PhoneNumber::Pager ) )
550  excludeNumber = true;
551 
552  if ( excludeNumber == false ) {
553  SyncEntryKab *kabEntry;
554 
555 
556  index = "";
557  name = (*it).familyName();
558 
559  TDEABC::AddressBook::Iterator it3;
560  TDEABC::Addressee::List tmp;
561  bool firstCharIsUnique = true;
562  for ( it3 = addressBook->begin(); it3 != addressBook->end(); ++it3 )
563  if ( ( (*it3).familyName() == name ) && ( it3 != it ) ) {
564  tmp.append( (*it3) );
565  if ( (*it3).givenName()[0] == (*it).givenName()[0] )
566  firstCharIsUnique = false;
567  }
568 
569  // There are several KAB entries with the same family name.
570  // So, we need to append the given name in order to
571  // distinguish them.
572  if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) {
573  name += ", ";
574 
575  if ( firstCharIsUnique )
576  name += (*it).givenName()[0] + ".";
577  else
578  name += (*it).givenName();
579  }
580 
581  // Truncate name field if it's too long for mobile phone
582  if ( name.length() > mPBNameLength )
583  name = name.remove( mPBNameLength, name.length() - mPBNameLength );
584 
585  // Append Suffix to name if specified in preferences
586  if ( (*mPrefs).useHomeSuff() &&
587  ( phoneNumber.type() & TDEABC::PhoneNumber::Home ) )
588  formatPBName( &name, (*mPrefs).homeSuff() );
589  else
590  if ( (*mPrefs).useWorkSuff() &&
591  ( phoneNumber.type() & TDEABC::PhoneNumber::Work ) )
592  formatPBName( &name, (*mPrefs).workSuff() );
593  else
594  if ( (*mPrefs).useMessagingSuff() &&
595  ( phoneNumber.type() & TDEABC::PhoneNumber::Msg ) )
596  formatPBName( &name, (*mPrefs).messagingSuff() );
597  else
598  if ( (*mPrefs).useFaxSuff() &&
599  ( phoneNumber.type() & TDEABC::PhoneNumber::Fax ) )
600  formatPBName( &name, (*mPrefs).faxSuff() );
601  else
602  if ( (*mPrefs).useCellSuff() &&
603  ( phoneNumber.type() & TDEABC::PhoneNumber::Cell ) )
604  formatPBName( &name, (*mPrefs).cellSuff() );
605  else
606  if ( (*mPrefs).useVideoSuff() &&
607  ( phoneNumber.type() & TDEABC::PhoneNumber::Video ) )
608  formatPBName( &name, (*mPrefs).videoSuff() );
609  else
610  if ( (*mPrefs).useMailboxSuff() &&
611  ( phoneNumber.type() & TDEABC::PhoneNumber::Bbs ) )
612  formatPBName( &name, (*mPrefs).mailboxSuff() );
613  else
614  if ( (*mPrefs).useModemSuff() &&
615  ( phoneNumber.type() & TDEABC::PhoneNumber::Modem ) )
616  formatPBName( &name, (*mPrefs).modemSuff() );
617  else
618  if ( (*mPrefs).useCarSuff() &&
619  ( phoneNumber.type() & TDEABC::PhoneNumber::Car ) )
620  formatPBName( &name, (*mPrefs).carSuff() );
621  else
622  if ( (*mPrefs).useISDNSuff() &&
623  ( phoneNumber.type() & TDEABC::PhoneNumber::Isdn ) )
624  formatPBName( &name, (*mPrefs).iSDNSuff() );
625  else
626  if ( (*mPrefs).usePagerSuff() &&
627  ( phoneNumber.type() & TDEABC::PhoneNumber::Pager ) )
628  formatPBName( &name, (*mPrefs).pagerSuff() );
629 
630  kabEntry = new SyncEntryKab( true, index, name, phone );
631  kabEntry->mKABindex = kabIndex;
632  kabEntry->mPhoneNumberIndex = phoneNumberIndex;
633 
634  kabEntry->mAddressee = (*it);
635  mSyncer->mKabEntries.append( kabEntry );
636  }
637  }
638  }
639 
640  // Display KAB entries
641  updateKabBook();
642 
643  emit transienStatusMessage( i18n( "Read TDE address book." ) );
644 
645  setKabState( LOADED );
646 }
647 
648 
649 TQString MobileGui::decodeSuffix( const TQString &suffix )
650 {
651  TQString theSuffix = suffix;
652 
653 
654  // Check whether suffix is quoted. If so, it should be interpreted
655  // as Hex-Number of a special GSM character.
656  if ( ( theSuffix.left( 1 ) == "\"" ) && ( theSuffix.right( 1 ) == "\"" ) ) {
657  TQString tmp = "";
658  char suffixNumber = (char) dequote( suffix ).toUInt( 0, 16 );
659  tmp += suffixNumber;
660 
661  theSuffix = GSM2String( tmp );
662  }
663 
664  return theSuffix;
665 }
666 
667 
668 void MobileGui::formatPBName( TQString *name, TQString suffix )
669 {
670  TQString theSuffix = decodeSuffix( suffix );
671 
672 
673  if ( name->length() + theSuffix.length() > mPBNameLength ) {
674  // Truncate name field if it's too long for mobile phone
675  unsigned int toolong = name->length() + theSuffix.length() - mPBNameLength;
676  (*name) = name->remove( name->length() - toolong, toolong );
677  } else
678  if ( name->length() + theSuffix.length() < mPBNameLength )
679  // Add white spaces so that suffix is right justified
680  while ( name->length() + theSuffix.length() != mPBNameLength )
681  (*name) += ' ';
682 
683  (*name) += theSuffix;
684 }
685 
686 
687 TQString MobileGui::stripWhiteSpaces( const TQString &theString )
688 {
689  int pos = 0;
690  int len = theString.length();
691 
692 
693  for ( unsigned int i = 0; i < theString.length(); i++ )
694  if ( theString[ i ].latin1() == ' ' ) {
695  pos++;
696  len--;
697  } else
698  break;
699 
700  if ( len == 0 )
701  return "";
702 
703  for ( int i = theString.length() - 1; i >= 0; i-- )
704  if ( theString[ i ].latin1() == ' ' )
705  len--;
706  else
707  break;
708 
709  return theString.mid( pos, len );
710 }
711 
712 
713 void MobileGui::writeKabc()
714 {
715  if ( mKabState != MODIFIED )
716  return;
717 
718  TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self( true );
719  TDEABC::Ticket *ticket = addressBook->requestSaveTicket();
720 
721  if ( !ticket ) {
722  kdDebug() << "Error! No ticket to save." << endl;
723  return;
724  }
725 
726 
727  for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) {
728  SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i );
729  TQString phoneNumber = kabEntry->mPhone;
730 
731 
732  if ( kabEntry->mToBeUpdated ) {
733  // Find the entry in the KAB which has to be updated
734  TDEABC::AddressBook::Iterator it = addressBook->begin();
735  for ( int KABindex = 0; KABindex != kabEntry->mKABindex;
736  it++, KABindex++ ) ;
737 
738  // Find the correct phonenumber of the phonebook entry
739  TDEABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers();
740  TDEABC::PhoneNumber::List::Iterator it2 = phoneNumbers.begin();
741  for ( int phoneNumberIndex = 0;
742  phoneNumberIndex != kabEntry->mPhoneNumberIndex;
743  it2++, phoneNumberIndex++ ) ;
744 
745  (*it2).setNumber( phoneNumber );
746  (*it).insertPhoneNumber( (*it2) );
747  } else
748 
749  if ( kabEntry->mToBeInserted ) {
750  int phoneType = 0;
751  bool goon = true;
752  TDEABC::AddressBook::Iterator it;
753  bool equivalentEntryFound = false;
754  TQString name = kabEntry->mName;
755 
756 
757  //
758  // Identify Type of Phonenumber using possibly appended suffixes.
759  // If a suffix is found, remove it from the name.
760  //
761  if ( goon && (*mPrefs).useHomeSuff() ) {
762  TQString theSuffix = decodeSuffix( (*mPrefs).homeSuff() );
763  if ( name.right( theSuffix.length() ) == theSuffix ) {
764  phoneType = TDEABC::PhoneNumber::Home;
765  name = stripWhiteSpaces(
766  name.left( name.length() - theSuffix.length() ) );
767  goon = false;
768  }
769  }
770  if ( goon && (*mPrefs).useWorkSuff() ) {
771  TQString theSuffix = decodeSuffix( (*mPrefs).workSuff() );
772  if ( name.right( theSuffix.length() ) == theSuffix ) {
773  phoneType = TDEABC::PhoneNumber::Work;
774  name = stripWhiteSpaces(
775  name.left( name.length() - theSuffix.length() ) );
776  goon = false;
777  }
778  }
779  if ( goon && (*mPrefs).useMessagingSuff() ) {
780  TQString theSuffix = decodeSuffix( (*mPrefs).messagingSuff() );
781  if ( name.right( theSuffix.length() ) == theSuffix ) {
782  phoneType = TDEABC::PhoneNumber::Msg;
783  name = stripWhiteSpaces(
784  name.left( name.length() - theSuffix.length() ) );
785  goon = false;
786  }
787  }
788  if ( goon && (*mPrefs).useFaxSuff() ) {
789  TQString theSuffix = decodeSuffix( (*mPrefs).faxSuff() );
790  if ( name.right( theSuffix.length() ) == theSuffix ) {
791  phoneType = TDEABC::PhoneNumber::Fax;
792  name = stripWhiteSpaces(
793  name.left( name.length() - theSuffix.length() ) );
794  goon = false;
795  }
796  }
797  if ( goon && (*mPrefs).useCellSuff() ) {
798  TQString theSuffix = decodeSuffix( (*mPrefs).cellSuff() );
799  if ( name.right( theSuffix.length() ) == theSuffix ) {
800  phoneType = TDEABC::PhoneNumber::Cell;
801  name = stripWhiteSpaces(
802  name.left( name.length() - theSuffix.length() ) );
803  goon = false;
804  }
805  }
806  if ( goon && (*mPrefs).useVideoSuff() ) {
807  TQString theSuffix = decodeSuffix( (*mPrefs).videoSuff() );
808  if ( name.right( theSuffix.length() ) == theSuffix ) {
809  phoneType = TDEABC::PhoneNumber::Video;
810  name = stripWhiteSpaces(
811  name.left( name.length() - theSuffix.length() ) );
812  goon = false;
813  }
814  }
815  if ( goon && (*mPrefs).useMailboxSuff() ) {
816  TQString theSuffix = decodeSuffix( (*mPrefs).mailboxSuff() );
817  if ( name.right( theSuffix.length() ) == theSuffix ) {
818  phoneType = TDEABC::PhoneNumber::Bbs;
819  name = stripWhiteSpaces(
820  name.left( name.length() - theSuffix.length() ) );
821  goon = false;
822  }
823  }
824  if ( goon && (*mPrefs).useModemSuff() ) {
825  TQString theSuffix = decodeSuffix( (*mPrefs).modemSuff() );
826  if ( name.right( theSuffix.length() ) == theSuffix ) {
827  phoneType = TDEABC::PhoneNumber::Modem;
828  name = stripWhiteSpaces(
829  name.left( name.length() - theSuffix.length() ) );
830  goon = false;
831  }
832  }
833  if ( goon && (*mPrefs).useCarSuff() ) {
834  TQString theSuffix = decodeSuffix( (*mPrefs).carSuff() );
835  if ( name.right( theSuffix.length() ) == theSuffix ) {
836  phoneType = TDEABC::PhoneNumber::Car;
837  name = stripWhiteSpaces(
838  name.left( name.length() - theSuffix.length() ) );
839  goon = false;
840  }
841  }
842  if ( goon && (*mPrefs).useISDNSuff() ) {
843  TQString theSuffix = decodeSuffix( (*mPrefs).iSDNSuff() );
844  if ( name.right( theSuffix.length() ) == theSuffix ) {
845  phoneType = TDEABC::PhoneNumber::Isdn;
846  name = stripWhiteSpaces(
847  name.left( name.length() - theSuffix.length() ) );
848  goon = false;
849  }
850  }
851  if ( goon && (*mPrefs).usePagerSuff() ) {
852  TQString theSuffix = decodeSuffix( (*mPrefs).pagerSuff() );
853  if ( name.right( theSuffix.length() ) == theSuffix ) {
854  phoneType = TDEABC::PhoneNumber::Pager;
855  name = stripWhiteSpaces(
856  name.left( name.length() - theSuffix.length() ) );
857  goon = false;
858  }
859  }
860 
861 
862  //
863  // Search for a KAB entry whose name, if formatted in exactly the
864  // same way as was done in readKabc, is equal to the actual name.
865  //
866 
867  for ( it = addressBook->begin(); it != addressBook->end(); it++ ) {
868  TQString kabName = (*it).familyName();
869  TDEABC::AddressBook::Iterator it3;
870  TDEABC::Addressee::List tmp;
871  bool firstCharIsUnique = true;
872  unsigned int minLength;
873 
874 
875  for ( it3 = addressBook->begin(); it3 != addressBook->end(); it3++ )
876  if ( ( (*it3).familyName() == kabName ) && ( it3 != it ) ) {
877  tmp.append( (*it3) );
878  if ( (*it3).givenName()[0] == (*it).givenName()[0] )
879  firstCharIsUnique = false;
880  }
881 
882  // There are several KAB entries with the same family name.
883  // So, we need to append the given name in order to
884  // distinguish them.
885  if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) {
886  kabName += ", ";
887 
888  if ( firstCharIsUnique )
889  kabName += (*it).givenName()[0] + ".";
890  else
891  kabName += (*it).givenName();
892  }
893 
894  // Truncate name field if it's too long for mobile phone
895  if ( kabName.length() > mPBNameLength )
896  kabName = kabName.remove( mPBNameLength,
897  kabName.length() - mPBNameLength );
898 
899  minLength = kabName.length();
900  if ( name.length() < minLength )
901  minLength = name.length();
902 
903  if ( name.left( minLength ) == kabName.left( minLength ) ) {
904  (*it).insertPhoneNumber( TDEABC::PhoneNumber( phoneNumber,
905  phoneType ) );
906 
907  equivalentEntryFound = true;
908  break;
909  }
910  }
911 
912  //
913  // If no equivalent entry was found in KAB, we need to generate
914  // a complete new entry.
915  //
916 
917  if ( !equivalentEntryFound ) {
918  TDEABC::Addressee entry;
919  TQStringList *fields = new TQStringList;
920 
921 
922  *fields = TQStringList::split( ',', name );
923 
924  if ( fields->count() > 1 ) {
925  // Name string contains comma separated entry so that we
926  // need to build family and given names out of them.
927  TQString givenName = "";
928 
929 
930  entry.setFamilyName( stripWhiteSpaces( (*fields)[ 0 ] ) );
931 
932  for ( unsigned int i = 1; i < fields->count(); i++ )
933  givenName += stripWhiteSpaces( (*fields)[ i ] ) + " ";
934  entry.setGivenName( stripWhiteSpaces( givenName ) );
935  } else
936  // Name string contains only one string without comma.
937  entry.setFamilyName( stripWhiteSpaces( name ) );
938 
939  entry.insertPhoneNumber( TDEABC::PhoneNumber( phoneNumber, phoneType ) );
940 
941  addressBook->insertAddressee( entry );
942  }
943  }
944 
945  kabEntry->mToBeUpdated = false;
946  kabEntry->mToBeInserted = false;
947  }
948 
949  addressBook->save( ticket );
950 
951  emit transienStatusMessage( i18n( "Wrote TDE address book." ) );
952 
953  setKabState( LOADED );
954 }
955 
956 
957 void MobileGui::refreshStatus()
958 {
959  mScheduler->executeId( "+cbc" );
960  mScheduler->executeId( "+csq" );
961 }
962 
963 
964 void MobileGui::processResult( ATCommand *command )
965 {
966  if ( command->id() == "+cbc" )
967  mBatteryChargeLabel->setText( command->resultField( 1 ) + " %" );
968  else
969  if ( command->id() == "+csq" )
970  mSignalQualityLabel->setText( command->resultField( 0 ) );
971  else
972  if ( command->id() == "+cgmi" ) {
973  mMobManufacturer = command->resultField( 0 );
974  mManufacturerLabel->setText( mMobManufacturer );
975  } else
976  if ( command->id() == "+cgmm" ) {
977  mMobModel = command->resultField( 0 );
978  mModelLabel->setText( mMobModel );
979  } else
980  if ( command->id() == "+cgmr" )
981  mGSMVersionLabel->setText( command->resultField( 0 ) );
982  else
983  if ( command->id() == "+cgsn" )
984  mSerialNumberLabel->setText( command->resultField( 0 ) );
985  else
986  if ( command->id() == "+cpbr=?" )
987  {
988  TQStringList tmpList = TQStringList::split( "-", command->resultField( 0 ) );
989  TQString tmpString = tmpList.first().right( tmpList.first().length() - 1 );
990  mPBStartIndex = tmpString.toUInt();
991  mPBNameLength = command->resultField( 2 ).toUInt();
992  } else
993  if ( command->id() == "+cpbs?" ) {
994  mPBLength = command->resultField( 2 ).toUInt();
995 
996  // Allocate and initialize memory for the buckets of indices
997  mPBIndexOccupied.resize( mPBLength, false );
998  for ( unsigned int i = 0; i < mPBLength; i++ )
999  mPBIndexOccupied[ i ] = false;
1000  } else
1001  if ( command->id() == "+cpbr=" ) {
1002  fillPhonebook( command );
1003 
1004  if ( mComingFromSyncPhonebooks ) {
1005  mComingFromSyncPhonebooks = false;
1006  mergePhonebooks();
1007  }
1008  } else
1009  if ( command->id() == mLastWriteId )
1010  writePhonebookPostProcessing();
1011  else
1012  if ( command->id() == "+cpbs=?" ) {
1013  TQPtrList<TQStringList> *list = command->resultFields();
1014  TQStringList *fields = list->first();
1015 
1016 
1017  while( fields ) {
1018  for ( unsigned int i = 0; i < fields->count(); i++ ) {
1019  TQString memory = dequote( (*fields)[ i ] );
1020 
1021 
1022  if ( memory == "FD" )
1023  mMobHasFD = true;
1024  else
1025  if ( memory == "LD" )
1026  mMobHasLD = true;
1027  else
1028  if ( memory == "ME" )
1029  mMobHasME = true;
1030  else
1031  if ( memory == "MT" )
1032  mMobHasMT = true;
1033  else
1034  if ( memory == "TA" )
1035  mMobHasTA = true;
1036  else
1037  if ( ( memory == "OW" ) ||
1038  ( ( memory == "ON" ) && ( mMobManufacturer == "SIEMENS" ) ) )
1039  mMobHasOW = true;
1040  else
1041  if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "MC" ) )
1042  mMobHasMC = true;
1043  else
1044  if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "RC" ) )
1045  mMobHasRC = true;
1046  }
1047 
1048  fields = list->next();
1049  }
1050  }
1051 }
1052 
1053 
1054 TQString MobileGui::noSpaces( const TQString &theString )
1055 {
1056  TQString result = "";
1057 
1058 
1059  for ( unsigned int i = 0; i < theString.length(); i++ )
1060  if ( theString[ i ].latin1() != ' ' )
1061  result += theString[ i ];
1062 
1063  return result;
1064 }
1065 
1066 
1067 int MobileGui::firstFreeIndex()
1068 {
1069  unsigned int i;
1070 
1071 
1072  if ( mPBIndexOccupied.capacity() == 0 )
1073  return 0;
1074 
1075  for ( i = 1; i < mPBLength; i++ )
1076  if ( !mPBIndexOccupied[ i ] )
1077  break;
1078 
1079  if ( i < mPBLength )
1080  return i;
1081 
1082  return 0;
1083 }
1084 
1085 
1086 TQString MobileGui::string2GSM( const TQString &theString )
1087 {
1088  TQString result = "";
1089 
1090 
1091  for ( unsigned int i = 0; i < theString.length(); i++ )
1092  switch ( theString[ i ].latin1() ) {
1093  case 'Ä': result += '['; break;
1094  case 'ä': result += '{'; break;
1095  case 'Ö': result += 92; break;
1096  case 'ö': result += '|'; break;
1097  case 'Ü': result += '^'; break;
1098  case 'ü': result += '~'; break;
1099  case 'ß': result += 30; break;
1100  case 'è': result += 4; break;
1101  case 'é': result += 5; break;
1102 
1103  default: result += theString[ i ];
1104  }
1105 
1106  return result;
1107 }
1108 
1109 
1110 TQString MobileGui::GSM2String( const TQString &theString )
1111 {
1112  TQString result = "";
1113 
1114 
1115  for ( unsigned int i = 0; i < theString.length(); i++ )
1116  switch ( theString[ i ].latin1() ) {
1117  case '[': result += 'Ä'; break;
1118  case '{': result += 'ä'; break;
1119  case 92: result += 'Ö'; break;
1120  case '|': result += 'ö'; break;
1121  case '^': result += 'Ü'; break;
1122  case '~': result += 'ü'; break;
1123  case 30: result += 'ß'; break;
1124  case 4: result += 'è'; break;
1125  case 5: result += 'é'; break;
1126 
1127  default: result += theString[ i ];
1128  }
1129 
1130  return result;
1131 }
1132 
1133 
1134 void MobileGui::fillPhonebook( ATCommand *cmd )
1135 {
1136  mSyncer->mMobileEntries.clear();
1137 
1138  TQPtrList<TQStringList> *list = cmd->resultFields();
1139  TQStringList *fields = list->first();
1140 
1141  while( fields ) {
1142  if ( fields->count() != 4 )
1143  kdDebug() << "Error! Unexpected number of address fields." << endl;
1144  else {
1145  TQString index = (*fields)[0];
1146  TQString phone = (*fields)[1];
1147  TQString type = (*fields)[2];
1148  TQString name = GSM2String( (*fields)[3] );
1149 
1150  SyncEntryMobile *phoneEntry = new SyncEntryMobile( true, dequote( index ),
1151  dequote( phone ),
1152  dequote( name ) );
1153  mPBIndexOccupied[ index.toUInt() - mPBStartIndex ] = true;
1154  mSyncer->mMobileEntries.append( phoneEntry );
1155  }
1156  fields = list->next();
1157  }
1158 
1159  // Display mobile entries
1160  updateMobileBook();
1161 
1162  emit transienStatusMessage(i18n("Read mobile phonebook."));
1163  emit phonebookRead();
1164 
1165  setMobState( LOADED );
1166 }
1167 
1168 
1169 TQString MobileGui::quote( const TQString &str )
1170 {
1171  if ( ( str.left(1) == "\"" ) && ( str.right(1) == "\"" ) )
1172  return str;
1173 
1174  return "\"" + str + "\"";
1175 }
1176 
1177 
1178 TQString MobileGui::dequote( const TQString &str )
1179 {
1180  int pos = 0;
1181  int len = str.length();
1182 
1183 
1184  if ( str.left(1) == "\"" ) {
1185  pos = 1;
1186  len --;
1187  }
1188 
1189  if ( str.right(1) == "\"" )
1190  len--;
1191 
1192  return str.mid( pos, len );
1193 }
1194 
1195 
1196 void MobileGui::savePhonebook()
1197 {
1198  if ( mMobState == UNLOADED )
1199  return;
1200 
1201  TQString fileName = KFileDialog::getSaveFileName( "phonebook.csv" );
1202  TQFile outFile( fileName );
1203 
1204  if ( outFile.open( IO_WriteOnly ) ) {
1205  TQTextStream t( &outFile ); // use a text stream
1206 
1207  for( uint i = 0; i < mSyncer->mMobileEntries.count(); i++) {
1208  SyncEntryMobile *e = mSyncer->mMobileEntries.at( i );
1209 
1210 
1211  if ( !e->mToBeDeleted )
1212  t << e->mIndex << "," << e->mPhone << "," << e->mName << endl;
1213  }
1214 
1215  outFile.close();
1216  }
1217 }
1218 
1219 
1220 void MobileGui::deleteMobPhonebook()
1221 {
1222 
1223  //
1224  // Process all elements selected in the GUI
1225  //
1226 
1227  PhoneBookItem *item = (PhoneBookItem *) mMobileBook->firstChild();
1228  while ( item ) {
1229  if ( item->isOn() ) {
1230  SyncEntryMobile *mobileItem = (SyncEntryMobile *) item->syncEntry();
1231 
1232 
1233  // Deselect current item
1234  item->setOn( false );
1235  mobileItem->mOn = false;
1236 
1237  // Mark current item as deleted
1238  mobileItem->mToBeDeleted = true;
1239  }
1240 
1241  item = (PhoneBookItem *) item->nextSibling();
1242  }
1243 
1244  // Update GUI
1245  updateMobileBook();
1246  setMobState( MODIFIED );
1247 }
1248 
1249 
1250 void MobileGui::mergePhonebooks()
1251 {
1252  uint i;
1253 
1254 
1255  //
1256  // Transfer current Selection State from GUI to mSyncer
1257  //
1258 
1259  PhoneBookItem *item = (PhoneBookItem *) mKabBook->firstChild();
1260  while ( item ) {
1261  item->syncEntry()->mOn = item->isOn();
1262  item = (PhoneBookItem *) item->nextSibling();
1263  }
1264 
1265  item = (PhoneBookItem *) mMobileBook->firstChild();
1266  while ( item ) {
1267  item->syncEntry()->mOn = item->isOn();
1268  item = (PhoneBookItem *) item->nextSibling();
1269  }
1270 
1271  mSyncer->mCommonEntries.clear();
1272 
1273 
1274  //
1275  // Put TDE Address Book list into Common List
1276  //
1277 
1278  for ( i = 0; i < mSyncer->mKabEntries.count(); i++ )
1279  if ( mSyncer->mKabEntries.at( i )->mOn ) {
1280  mSyncer->mCommonEntries.append(
1281  new SyncEntryCommon( true, mSyncer->mKabEntries.at( i ), 0 ) );
1282  mSyncer->mKabEntries.at( i )->mOn = false;
1283  }
1284 
1285 
1286  //
1287  // Put Mobile Address Book list into Common List; Merge equivalent entries
1288  //
1289 
1290  for ( i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
1291  SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at( i );
1292  bool equivalentEntryFound = false;
1293  uint j;
1294 
1295 
1296  if( !mobileEntry->mToBeDeleted )
1297  for ( j = 0; j < mSyncer->mCommonEntries.count(); j++ ) {
1298  SyncEntryCommon *theCommonEntry = mSyncer->mCommonEntries.at( j );
1299 
1300 
1301  if ( theCommonEntry->mKabEntry &&
1302  ( theCommonEntry->mKabEntry->mName == mobileEntry->mName ) ) {
1303  theCommonEntry->mMobileEntry = mobileEntry;
1304  equivalentEntryFound = true;
1305 
1306  if ( noSpaces( theCommonEntry->mKabEntry->mPhone ) ==
1307  mobileEntry->mPhone ) {
1308  mobileEntry->mOn = false;
1309  break;
1310  } else {
1311  // Conflict: 2 Entries have same name but different numbers.
1312  // Prompt user.
1313  TQString text = "<qt><b>" + i18n( "Kab Entry:" ) + "</b><br>";
1314  text += " " + theCommonEntry->mKabEntry->mName + " " +
1315  theCommonEntry->mKabEntry->mPhone + "<br>";
1316  text += "<b>" + i18n( "Mobile Entry:" ) + "</b><br>";
1317  text += " " + mobileEntry->mName + " " + mobileEntry->mPhone;
1318  text += "</qt>";
1319 
1320  TQMessageBox *msg =
1321  new TQMessageBox( i18n( "Conflicting Entries" ), text,
1322  TQMessageBox::Warning, 1, 2, 0, this );
1323  msg->setButtonText( 1, i18n( "Use Kab Entry" ) );
1324  msg->setButtonText( 2, i18n( "Use Mobile Entry" ) );
1325 
1326  switch ( msg->exec() ) {
1327  case 1:
1328  // Use TDE Address Book Entry
1329  mobileEntry->mPhone = theCommonEntry->mKabEntry->mPhone;
1330  mobileEntry->mName = theCommonEntry->mKabEntry->mName;
1331  mobileEntry->mOn = true;
1332  mobileEntry->mToBeUpdated = true;
1333 
1334  setMobState( MODIFIED );
1335  break;
1336 
1337  case 2:
1338  // Use Mobile Address Book Entry
1339  theCommonEntry->mKabEntry->mPhone = mobileEntry->mPhone;
1340  theCommonEntry->mKabEntry->mName = mobileEntry->mName;
1341  theCommonEntry->mKabEntry->mOn = true;
1342  theCommonEntry->mKabEntry->mToBeUpdated = true;
1343 
1344  mobileEntry->mOn = false;
1345 
1346  setKabState( MODIFIED );
1347  break;
1348  }
1349  }
1350  }
1351  }
1352 
1353  if ( !equivalentEntryFound && mobileEntry->mOn ) {
1354  // No equivalent entry exists; generate a new one.
1355  mSyncer->mCommonEntries.append(
1356  new SyncEntryCommon( true, 0, mobileEntry ) );
1357  mobileEntry->mOn = false;
1358  }
1359  }
1360 
1361 
1362  //
1363  // Create new KAB and Mobile Entries
1364  //
1365 
1366  for ( i = 0; i < mSyncer->mCommonEntries.count(); i++ ) {
1367  SyncEntryCommon *entry = mSyncer->mCommonEntries.at( i );
1368  SyncEntryKab *kabEntry = entry->mKabEntry;
1369  SyncEntryMobile *mobileEntry = entry->mMobileEntry;
1370 
1371 
1372  if ( kabEntry && !mobileEntry ) {
1373  // Create Mobile Entry
1374  entry->mMobileEntry = new SyncEntryMobile( true, "", kabEntry->mPhone,
1375  kabEntry->mName );
1376  entry->mMobileEntry->mToBeInserted = true;
1377  mSyncer->mMobileEntries.append( entry->mMobileEntry );
1378 
1379  setMobState( MODIFIED );
1380  } else
1381  if ( mobileEntry && !kabEntry ) {
1382  // Create KAB Entry
1383  entry->mKabEntry = new SyncEntryKab( true, mobileEntry->mIndex,
1384  mobileEntry->mName,
1385  mobileEntry->mPhone );
1386  entry->mKabEntry->mToBeInserted = true;
1387  mSyncer->mKabEntries.append( entry->mKabEntry );
1388 
1389  setKabState( MODIFIED );
1390  }
1391  }
1392 
1393 
1394  //
1395  // Update GUI
1396  //
1397 
1398  updateKabBook();
1399  updateMobileBook();
1400 
1401  emit transienStatusMessage( i18n( "Synced phonebooks." ) );
1402  PushButton8_3->setEnabled( true );
1403 }
1404 
1405 
1406 void MobileGui::syncPhonebooks()
1407 {
1408  PushButton8_3->setEnabled( false );
1409 
1410  if ( mKabState == UNLOADED )
1411  readKabc();
1412  if ( mMobState == UNLOADED ) {
1413  mComingFromSyncPhonebooks = true;
1414  readPhonebook();
1415  } else
1416  mergePhonebooks();
1417 }
1418 
1419 
1420 void MobileGui::updateKabBook()
1421 {
1422  mKabBook->clear();
1423 
1424  for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) {
1425  SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i );
1426  PhoneBookItem *item = new PhoneBookItem( mKabBook, kabEntry,
1427  kabEntry->mName, kabEntry->mPhone,
1428  kabEntry->mIndex );
1429  item->setOn( kabEntry->mOn );
1430  }
1431 }
1432 
1433 
1434 void MobileGui::updateMobileBook()
1435 {
1436  mMobileBook->clear();
1437 
1438  for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
1439  SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
1440 
1441  if ( !entry->mToBeDeleted ) {
1442  PhoneBookItem *item = new PhoneBookItem( mMobileBook, entry, entry->mName,
1443  entry->mPhone, entry->mIndex );
1444  item->setOn( entry->mOn );
1445  }
1446  }
1447 }
1448 
1449 
1450 void MobileGui::toggleConnection()
1451 {
1452  if ( mConnectButton->text() == i18n( "Connect" ) ) {
1453  emit connectModem();
1454 
1455  readModelInformation();
1456  refreshStatus();
1457 
1458  mConnectButton->setText( tr2i18n( "Disconnect" ) );
1459  PushButton1->setEnabled( true );
1460  PushButton5_3->setEnabled( true );
1461 
1462  mABTab->setEnabled( true );
1463  setKabState( UNLOADED );
1464  setMobState( UNLOADED );
1465 
1466  ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Connected "), 1 );
1467  } else {
1468  warnKabState( UNLOADED );
1469 
1470  mComingFromToggleConnection = true;
1471  if ( !warnMobState( UNLOADED ) ) {
1472  mComingFromToggleConnection = false;
1473  disconnectGUI();
1474  }
1475  }
1476 }
1477 
1478 
1479 void MobileGui::disconnectGUI()
1480 {
1481  emit disconnectModem();
1482 
1483  mManufacturerLabel->setText( "x" );
1484  mModelLabel->setText( "x" );
1485  mGSMVersionLabel->setText( "x" );
1486  mSerialNumberLabel->setText( "x" );
1487 
1488  mBatteryChargeLabel->setText( "xx %" );
1489  mSignalQualityLabel->setText( "x" );
1490 
1491  mConnectButton->setText( tr2i18n( "Connect" ) );
1492  PushButton1->setEnabled( false );
1493  PushButton5_3->setEnabled( false );
1494 
1495  mKabBook->clear();
1496  mMobileBook->clear();
1497  setKabState( UNLOADED );
1498  setMobState( UNLOADED );
1499 
1500  mABTab->setEnabled( false );
1501 
1502  mMobHasFD = false;
1503  mMobHasLD = false;
1504  mMobHasME = false;
1505  mMobHasMT = false;
1506  mMobHasTA = false;
1507  mMobHasOW = false;
1508  mMobHasMC = false;
1509  mMobHasRC = false;
1510 
1511  mPBIndexOccupied.resize( 0, false );
1512 
1513  ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Disconnected "),
1514  1 );
1515 }
1516 
1517 
1518 void MobileGui::termAddOutput( const char *line )
1519 {
1520  mTermIO->append( line );
1521  mTermIO->setCursorPosition( mTermIO->paragraphs() - 1, 0 );
1522 }
1523 
1524 
1525 void MobileGui::setKabState( ABState newState )
1526 {
1527  switch ( mKabState ) {
1528  case UNLOADED:
1529  groupBox3->setTitle( tr2i18n( "TDE Address Book" ) );
1530  mReadKabButton->setEnabled( true );
1531  PushButton8->setEnabled( false );
1532  break;
1533 
1534  case LOADED:
1535  if ( newState == MODIFIED ) {
1536  groupBox3->setTitle( tr2i18n( "TDE Address Book (modified)" ) );
1537  mReadKabButton->setEnabled( true );
1538  PushButton8->setEnabled( true );
1539  } else
1540  if ( newState == UNLOADED ) {
1541  groupBox3->setTitle( tr2i18n( "TDE Address Book" ) );
1542  mReadKabButton->setEnabled( true );
1543  PushButton8->setEnabled( false );
1544  }
1545  break;
1546 
1547  case MODIFIED:
1548  if ( newState != MODIFIED ) {
1549  groupBox3->setTitle( tr2i18n( "TDE Address Book" ) );
1550  mReadKabButton->setEnabled( true );
1551  PushButton8->setEnabled( false );
1552  }
1553  break;
1554  }
1555 
1556  mKabState = newState;
1557 }
1558 
1559 
1560 void MobileGui::warnKabState( ABState newState )
1561 {
1562  if ( ( mKabState == MODIFIED ) && ( newState != MODIFIED ) ) {
1563  TQString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>";
1564  text += i18n( "The TDE address book contains unsaved changes." ) +
1565  "<br></qt>";
1566 
1567  TQMessageBox *msg = new TQMessageBox( i18n( "Unsaved Changes" ), text,
1568  TQMessageBox::Critical, 1, 2, 0, this );
1569  msg->setButtonText( 1, i18n( "Save" ) );
1570  msg->setButtonText( 2, i18n( "Discard" ) );
1571 
1572  switch ( msg->exec() ) {
1573  case 1:
1574  // Save Changes first
1575  writeKabc();
1576  break;
1577 
1578  case 2:
1579  break;
1580  }
1581  }
1582 }
1583 
1584 
1585 void MobileGui::setMobState( ABState newState )
1586 {
1587  switch ( mMobState ) {
1588  case UNLOADED:
1589  if ( newState == UNLOADED ) {
1590  groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
1591  PushButton3->setEnabled( true );
1592  PushButton12->setEnabled( false );
1593  PushButton4_2->setEnabled( false );
1594  MobDeleteButton->setEnabled( false );
1595  } else
1596  if ( newState == LOADED ) {
1597  groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
1598  PushButton3->setEnabled( true );
1599  PushButton12->setEnabled( false );
1600  PushButton4_2->setEnabled( true );
1601  MobDeleteButton->setEnabled( true );
1602  }
1603  break;
1604 
1605  case LOADED:
1606  if ( newState == MODIFIED ) {
1607  groupBox4->setTitle( tr2i18n( "Mobile Phone Book (modified)" ) );
1608  PushButton3->setEnabled( true );
1609  PushButton12->setEnabled( true );
1610  PushButton4_2->setEnabled( true );
1611  MobDeleteButton->setEnabled( true );
1612  } else
1613  if ( newState == UNLOADED ) {
1614  groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
1615  PushButton3->setEnabled( true );
1616  PushButton12->setEnabled( false );
1617  PushButton4_2->setEnabled( false );
1618  MobDeleteButton->setEnabled( false );
1619  }
1620  break;
1621 
1622  case MODIFIED:
1623  if ( newState == UNLOADED ) {
1624  groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
1625  PushButton3->setEnabled( true );
1626  PushButton12->setEnabled( false );
1627  PushButton4_2->setEnabled( false );
1628  MobDeleteButton->setEnabled( false );
1629  } else
1630  if ( newState == LOADED ) {
1631  groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
1632  PushButton3->setEnabled( true );
1633  PushButton12->setEnabled( false );
1634  PushButton4_2->setEnabled( true );
1635  MobDeleteButton->setEnabled( true );
1636  }
1637  break;
1638  }
1639 
1640  mMobState = newState;
1641 }
1642 
1643 
1644 bool MobileGui::warnMobState( ABState newState )
1645 {
1646  if ( ( mMobState == MODIFIED ) && ( newState != MODIFIED ) )
1647  {
1648  TQString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>";
1649  text += i18n( "The mobile phone book contains unsaved changes." ) +
1650  "<br></qt>";
1651 
1652  TQMessageBox *msg = new TQMessageBox( i18n( "Unsaved Changes" ), text,
1653  TQMessageBox::Critical, 1, 2, 0, this );
1654  msg->setButtonText( 1, i18n( "Save" ) );
1655  msg->setButtonText( 2, i18n( "Discard" ) );
1656 
1657  switch ( msg->exec() ) {
1658  case 1:
1659  // Save Changes first
1660  writePhonebook();
1661  return true;
1662  break;
1663 
1664  case 2:
1665  return false;
1666  break;
1667  }
1668  }
1669 
1670  return false;
1671 }
This class provides an abstraction of an AT command.
Definition: atcommand.h:54
This class serves as the main window for MobileMain.
Definition: mobilemain.h:47