diff options
Diffstat (limited to 'kandy/src/mobilegui.cpp')
-rw-r--r-- | kandy/src/mobilegui.cpp | 1671 |
1 files changed, 1671 insertions, 0 deletions
diff --git a/kandy/src/mobilegui.cpp b/kandy/src/mobilegui.cpp new file mode 100644 index 000000000..374660902 --- /dev/null +++ b/kandy/src/mobilegui.cpp @@ -0,0 +1,1671 @@ +/* + This file is part of Kandy. + + Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <time.h> + +#include <qlabel.h> +#include <qlistview.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qmessagebox.h> + +#include <qtextedit.h> +#include <qgroupbox.h> +#include <qpushbutton.h> + +#include <kdebug.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kapplication.h> +#include <kstatusbar.h> + +#include <kabc/stdaddressbook.h> + +#include "modem.h" +#include "atcommand.h" +#include "commandscheduler.h" + +#include "mobilegui.h" +#include "mobilegui.moc" +#include "mobilemain.h" + + +class SyncEntry +{ + public: + SyncEntry() + { + mOn = true; + mToBeUpdated = false; + mToBeInserted = false; + } + + bool mOn; + bool mToBeUpdated; + bool mToBeInserted; +}; + + +class SyncEntryKab : public SyncEntry +{ + public: + SyncEntryKab( bool on, const QString &index, const QString &name, + const QString &phone ) + { + mOn = on; + + mIndex = index; + mName = name; + mPhone = phone; + + mKABindex = -1; + mPhoneNumberIndex = -1; + } + + QString mIndex; + QString mName; + QString mPhone; + + KABC::Addressee mAddressee; + int mKABindex; + int mPhoneNumberIndex; +}; + + +class SyncEntryMobile : public SyncEntry +{ + public: + SyncEntryMobile( bool on, const QString &index, const QString &phone, + const QString &name ) + { + mOn = on; + mToBeDeleted = false; + + mIndex = index; + mName = name; + mPhone = phone; + } + + QString mIndex; + QString mName; + QString mPhone; + + bool mToBeDeleted; +}; + + +class SyncEntryCommon : public SyncEntry +{ + public: + SyncEntryCommon( bool on, SyncEntryKab *kabEntry, + SyncEntryMobile *mobileEntry ) + { + mOn = on; + mKabEntry = kabEntry; + mMobileEntry = mobileEntry; + } + + SyncEntryKab *mKabEntry; + SyncEntryMobile *mMobileEntry; +}; + + +class AddressSyncer +{ + public: + AddressSyncer() + { + mKabEntries.setAutoDelete( true ); + mMobileEntries.setAutoDelete( true ); + mCommonEntries.setAutoDelete( true ); + } + + QPtrList<SyncEntryKab> mKabEntries; + QPtrList<SyncEntryMobile> mMobileEntries; + QPtrList<SyncEntryCommon> mCommonEntries; +}; + + +class PhoneBookItem : public QCheckListItem +{ + public: + PhoneBookItem( QListView *v ) : + QCheckListItem( v, "", QCheckListItem::CheckBox ) + { + mSyncEntry = 0; + } + + PhoneBookItem( QListView *v, SyncEntry *syncEntry, const QString &name, + const QString &phone, const QString &index ) : + QCheckListItem( v, index, QCheckListItem::CheckBox ) + { + mSyncEntry = syncEntry; + + setText( 0, name ); + setText( 1, phone ); + setText( 2, index ); + } + + SyncEntry *syncEntry() { return mSyncEntry; } + + private: + SyncEntry *mSyncEntry; +}; + + +/* + * Constructs a MobileGui which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +MobileGui::MobileGui( CommandScheduler *scheduler, KandyPrefs *kprefs, + QWidget* parent, const char* name, WFlags fl ) : + DCOPObject( "KandyIface" ), MobileGui_base( parent, name, fl ) +{ + // Setup links to related classes + mScheduler = scheduler; + mSyncer = new AddressSyncer; + mPrefs = kprefs; + mparent = parent; + + // Setup mobile phone specific data + mMobManufacturer = ""; + mMobModel = ""; + mPBStartIndex = 0; + mPBLength = 0; + mPBNameLength = 0; + mPBIndexOccupied.resize( 0, false ); + mMobHasFD = false; + mMobHasLD = false; + mMobHasME = false; + mMobHasMT = false; + mMobHasTA = false; + mMobHasOW = false; + mMobHasMC = false; + mMobHasRC = false; + + // Setup status for asynchronous control flow + mLastWriteId = ""; + mComingFromToggleConnection = false; + mComingFromReadPhonebook = false; + mComingFromSyncPhonebooks = false; + mComingFromExit = false; + + // Setup initial state of phone books + setKabState( UNLOADED ); + setMobState( UNLOADED ); + + // Setup signal handlers + connect( mScheduler, SIGNAL( commandProcessed( ATCommand * ) ), + SLOT( processResult( ATCommand * ) ) ); + connect( mScheduler->modem(), SIGNAL( gotLine( const char * ) ), + SLOT( termAddOutput( const char * ) ) ); +} + + +MobileGui::~MobileGui() +{ + delete mSyncer; +} + + +void MobileGui::exit() +{ + warnKabState( UNLOADED ); + + mComingFromExit = true; + if ( !warnMobState( UNLOADED ) ) { + mComingFromExit = false; + kapp->quit(); + } +} + + +void MobileGui::readModelInformation() +{ + // Read generic manufacturer and model information + mScheduler->executeId( "+cgmi" ); + mScheduler->executeId( "+cgmm" ); + mScheduler->executeId( "+cgmr" ); + mScheduler->executeId( "+cgsn" ); + + // Read information about additional phonebook memories + ATCommand *cmd = new ATCommand( "+cpbs=?" ); + cmd->setAutoDelete( true ); + mScheduler->execute( cmd ); + + // Select SIM phonebook by default + cmd = new ATCommand( "+cpbs=" ); + cmd->setAutoDelete( true ); + cmd->addParameter( new ATParameter( "SM" ) ); + mScheduler->execute( cmd ); + + // Read phonebook properties + mScheduler->executeId( "+cpbr=?" ); + mScheduler->executeId( "+cpbs?" ); + + // Set clock + if ( (*mPrefs).autoSetClock() ) + setClock(); +} + + +void MobileGui::readPhonebook() +{ + if ( mMobState == LOADED ) + return; + + mComingFromReadPhonebook = true; + if ( !warnMobState( LOADED ) ) { + mComingFromReadPhonebook = false; + QString tmp = ""; + + ATCommand *cmd = new ATCommand( "+cpbr=" ); + cmd->setAutoDelete( true ); + cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) ); + cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex + + mPBLength - 1 ) ) ); + + mScheduler->execute( cmd ); + + emit statusMessage( i18n( "Reading mobile phonebook..." ) ); + } +} + + +void MobileGui::writePhonebook() +{ + bool ModemCommandScheduled = false; + + + if ( mMobState != MODIFIED ) + return; + + PushButton12->setEnabled( false ); + + + // + // Remove all entries from data structures which are marked as + // deleted but which are not found on the mobile phone + // + + for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { + SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); + + + if ( entry->mToBeDeleted ) + if ( entry->mIndex.isEmpty() ) { + // The current entry has to be deleted but doesn't come from + // the mobile phone. Hence, it was inserted during phonebook + // synchronisation or so. + // => It is sufficient to remove it from mMobileEntries, no + // ATCommand for deletion needs to be scheduled. + mSyncer->mMobileEntries.remove( i ); + i--; + } else { + // The current entry has to be deleted and stems from the + // mobile phone. First thing to do is to free its associated + // index. This way, its index can be reused for entries which + // have be newly inserted to the mobile phone and we can save + // an explicit ATCommand for deletion and save time & battery + // energy. + uint theIndex = entry->mIndex.toUInt(); + mPBIndexOccupied[ theIndex - mPBStartIndex ] = false; + } + } + + + // + // Write all elements which need an update to the mobile phone + // + + for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { + SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); + QString id; + + + // Only process changed items of the mobile phonebook in + // order to save time. + if ( entry->mToBeUpdated || entry->mToBeInserted ) { + QString tmp = ""; + + + if ( entry->mToBeUpdated ) { + id = "+cpbw=" + entry->mIndex; + } else { + int index = firstFreeIndex(); + + + mPBIndexOccupied[ index ] = true; + id = "+cpbw=" + tmp.setNum( index + mPBStartIndex ); + } + mLastWriteId = id; + entry->mToBeUpdated = false; + entry->mToBeInserted = false; + + ATCommand *cmd = new ATCommand( id ); + cmd->setAutoDelete( true ); + cmd->addParameter( new ATParameter( quote( entry->mPhone ) ) ); + + if ( entry->mPhone.left( 1 ) == "+" ) + cmd->addParameter( new ATParameter( "145" ) ); + else + cmd->addParameter( new ATParameter( "129" ) ); + + cmd->addParameter( new ATParameter( + quote( string2GSM( entry->mName ) ) ) ); + + mScheduler->execute( cmd ); + ModemCommandScheduled = true; + } + } + + + // + // As a final step, we need to check again all entries which should be + // deleted. If entries exist stemming from the mobile phone and whose + // index-position was not reused for updating or inserting other entries in + // the previous loop, we need to issue an explicit ATCommand for its deletion. + // + + for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { + SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); + + + if ( entry->mToBeDeleted ) { + uint theIndex = entry->mIndex.toUInt(); + + + if ( !mPBIndexOccupied[ theIndex - mPBStartIndex ] ) { + // Index of item to be deleted still is 0, so that index position + // wasn't reused. We must delete it explicitly. + QString id = "+cpbw=" + entry->mIndex; + + + mLastWriteId = id; + ATCommand *cmd = new ATCommand( id ); + cmd->setAutoDelete( true ); + + mScheduler->execute( cmd ); + ModemCommandScheduled = true; + } + + // Remove entry from internal data structures + mSyncer->mMobileEntries.remove( i ); + i--; + } + } + + if ( ModemCommandScheduled ) + emit statusMessage( i18n( "Writing mobile phonebook..." ) ); + else + writePhonebookPostProcessing(); +} + + +void MobileGui::writePhonebookPostProcessing() +{ + mLastWriteId = ""; + emit transientStatusMessage( i18n( "Wrote mobile phonebook." ) ); + PushButton12->setEnabled( true ); + setMobState( LOADED ); + updateMobileBook(); + + if ( mComingFromToggleConnection ) { + mComingFromToggleConnection = false; + disconnectGUI(); + } else + if ( mComingFromReadPhonebook ) { + mComingFromReadPhonebook = false; + QString tmp = ""; + + ATCommand *cmd = new ATCommand( "+cpbr=" ); + cmd->setAutoDelete( true ); + cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) ); + cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex + + mPBLength - 1 ) ) ); + + mScheduler->execute( cmd ); + + emit statusMessage( i18n( "Reading mobile phonebook..." ) ); + } else + if ( mComingFromExit ) { + mComingFromExit = false; + kapp->quit(); + } +} + + +void MobileGui::setClock() +{ + char *timeStr = new char[50]; + QString id = "+cclk="; + ATCommand *cmd = new ATCommand( id ); + + + cmd->setAutoDelete( true ); + + time_t tloc; + time( &tloc ); + struct tm *theTime = localtime( &tloc ); + strftime( timeStr, 50, "%y/%m/%d,%T+00", theTime ); + + QString Time = timeStr; + cmd->addParameter( new ATParameter( quote( Time ) ) ); + + mScheduler->execute( cmd ); + + delete[] timeStr; +} + + +void MobileGui::readKabc() +{ + if ( mKabState == LOADED ) + return; + + warnKabState( LOADED ); + + emit statusMessage( i18n( "Reading KDE address book..." ) ); + + mSyncer->mKabEntries.clear(); + + KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true ); + KABC::AddressBook::Iterator it; + int kabIndex = 0; + + for ( it = addressBook->begin(); it != addressBook->end(); + it++, kabIndex++ ) { + QString index, name; + KABC::PhoneNumber phoneNumber; + KABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers(); + KABC::PhoneNumber::List::Iterator it2; + int phoneNumberIndex = 0; + + + // Scan all numbers associated with a KAB entry + for ( it2 = phoneNumbers.begin(); it2 != phoneNumbers.end(); + it2++, phoneNumberIndex++ ) { + bool excludeNumber = false; + phoneNumber = (*it2); + QString phone = phoneNumber.number(); + + + if ( (*mPrefs).excludeHome() && + ( phoneNumber.type() & KABC::PhoneNumber::Home ) ) + excludeNumber = true; + if ( (*mPrefs).excludeWork() && + ( phoneNumber.type() & KABC::PhoneNumber::Work ) ) + excludeNumber = true; + if ( (*mPrefs).excludeMessaging() && + ( phoneNumber.type() & KABC::PhoneNumber::Msg ) ) + excludeNumber = true; + if ( (*mPrefs).excludeFax() && + ( phoneNumber.type() & KABC::PhoneNumber::Fax ) ) + excludeNumber = true; + if ( (*mPrefs).excludeCell() && + ( phoneNumber.type() & KABC::PhoneNumber::Cell ) ) + excludeNumber = true; + if ( (*mPrefs).excludeVideo() && + ( phoneNumber.type() & KABC::PhoneNumber::Video ) ) + excludeNumber = true; + if ( (*mPrefs).excludeMailbox() && + ( phoneNumber.type() & KABC::PhoneNumber::Bbs ) ) + excludeNumber = true; + if ( (*mPrefs).excludeModem() && + ( phoneNumber.type() & KABC::PhoneNumber::Modem ) ) + excludeNumber = true; + if ( (*mPrefs).excludeCar() && + ( phoneNumber.type() & KABC::PhoneNumber::Car ) ) + excludeNumber = true; + if ( (*mPrefs).excludeISDN() && + ( phoneNumber.type() & KABC::PhoneNumber::Isdn ) ) + excludeNumber = true; + if ( (*mPrefs).excludePager() && + ( phoneNumber.type() & KABC::PhoneNumber::Pager ) ) + excludeNumber = true; + + if ( excludeNumber == false ) { + SyncEntryKab *kabEntry; + + + index = ""; + name = (*it).familyName(); + + KABC::AddressBook::Iterator it3; + KABC::Addressee::List tmp; + bool firstCharIsUnique = true; + for ( it3 = addressBook->begin(); it3 != addressBook->end(); ++it3 ) + if ( ( (*it3).familyName() == name ) && ( it3 != it ) ) { + tmp.append( (*it3) ); + if ( (*it3).givenName()[0] == (*it).givenName()[0] ) + firstCharIsUnique = false; + } + + // There are several KAB entries with the same family name. + // So, we need to append the given name in order to + // distinguish them. + if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) { + name += ", "; + + if ( firstCharIsUnique ) + name += (*it).givenName()[0] + "."; + else + name += (*it).givenName(); + } + + // Truncate name field if it's too long for mobile phone + if ( name.length() > mPBNameLength ) + name = name.remove( mPBNameLength, name.length() - mPBNameLength ); + + // Append Suffix to name if specified in preferences + if ( (*mPrefs).useHomeSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Home ) ) + formatPBName( &name, (*mPrefs).homeSuff() ); + else + if ( (*mPrefs).useWorkSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Work ) ) + formatPBName( &name, (*mPrefs).workSuff() ); + else + if ( (*mPrefs).useMessagingSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Msg ) ) + formatPBName( &name, (*mPrefs).messagingSuff() ); + else + if ( (*mPrefs).useFaxSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Fax ) ) + formatPBName( &name, (*mPrefs).faxSuff() ); + else + if ( (*mPrefs).useCellSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Cell ) ) + formatPBName( &name, (*mPrefs).cellSuff() ); + else + if ( (*mPrefs).useVideoSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Video ) ) + formatPBName( &name, (*mPrefs).videoSuff() ); + else + if ( (*mPrefs).useMailboxSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Bbs ) ) + formatPBName( &name, (*mPrefs).mailboxSuff() ); + else + if ( (*mPrefs).useModemSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Modem ) ) + formatPBName( &name, (*mPrefs).modemSuff() ); + else + if ( (*mPrefs).useCarSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Car ) ) + formatPBName( &name, (*mPrefs).carSuff() ); + else + if ( (*mPrefs).useISDNSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Isdn ) ) + formatPBName( &name, (*mPrefs).iSDNSuff() ); + else + if ( (*mPrefs).usePagerSuff() && + ( phoneNumber.type() & KABC::PhoneNumber::Pager ) ) + formatPBName( &name, (*mPrefs).pagerSuff() ); + + kabEntry = new SyncEntryKab( true, index, name, phone ); + kabEntry->mKABindex = kabIndex; + kabEntry->mPhoneNumberIndex = phoneNumberIndex; + + kabEntry->mAddressee = (*it); + mSyncer->mKabEntries.append( kabEntry ); + } + } + } + + // Display KAB entries + updateKabBook(); + + emit transientStatusMessage( i18n( "Read KDE address book." ) ); + + setKabState( LOADED ); +} + + +QString MobileGui::decodeSuffix( const QString &suffix ) +{ + QString theSuffix = suffix; + + + // Check whether suffix is quoted. If so, it should be interpreted + // as Hex-Number of a special GSM character. + if ( ( theSuffix.left( 1 ) == "\"" ) && ( theSuffix.right( 1 ) == "\"" ) ) { + QString tmp = ""; + char suffixNumber = (char) dequote( suffix ).toUInt( 0, 16 ); + tmp += suffixNumber; + + theSuffix = GSM2String( tmp ); + } + + return theSuffix; +} + + +void MobileGui::formatPBName( QString *name, QString suffix ) +{ + QString theSuffix = decodeSuffix( suffix ); + + + if ( name->length() + theSuffix.length() > mPBNameLength ) { + // Truncate name field if it's too long for mobile phone + unsigned int toolong = name->length() + theSuffix.length() - mPBNameLength; + (*name) = name->remove( name->length() - toolong, toolong ); + } else + if ( name->length() + theSuffix.length() < mPBNameLength ) + // Add white spaces so that suffix is right justified + while ( name->length() + theSuffix.length() != mPBNameLength ) + (*name) += ' '; + + (*name) += theSuffix; +} + + +QString MobileGui::stripWhiteSpaces( const QString &theString ) +{ + int pos = 0; + int len = theString.length(); + + + for ( unsigned int i = 0; i < theString.length(); i++ ) + if ( theString[ i ].latin1() == ' ' ) { + pos++; + len--; + } else + break; + + if ( len == 0 ) + return ""; + + for ( int i = theString.length() - 1; i >= 0; i-- ) + if ( theString[ i ].latin1() == ' ' ) + len--; + else + break; + + return theString.mid( pos, len ); +} + + +void MobileGui::writeKabc() +{ + if ( mKabState != MODIFIED ) + return; + + KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true ); + KABC::Ticket *ticket = addressBook->requestSaveTicket(); + + if ( !ticket ) { + kdDebug() << "Error! No ticket to save." << endl; + return; + } + + + for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) { + SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i ); + QString phoneNumber = kabEntry->mPhone; + + + if ( kabEntry->mToBeUpdated ) { + // Find the entry in the KAB which has to be updated + KABC::AddressBook::Iterator it = addressBook->begin(); + for ( int KABindex = 0; KABindex != kabEntry->mKABindex; + it++, KABindex++ ) ; + + // Find the correct phonenumber of the phonebook entry + KABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers(); + KABC::PhoneNumber::List::Iterator it2 = phoneNumbers.begin(); + for ( int phoneNumberIndex = 0; + phoneNumberIndex != kabEntry->mPhoneNumberIndex; + it2++, phoneNumberIndex++ ) ; + + (*it2).setNumber( phoneNumber ); + (*it).insertPhoneNumber( (*it2) ); + } else + + if ( kabEntry->mToBeInserted ) { + int phoneType = 0; + bool goon = true; + KABC::AddressBook::Iterator it; + bool equivalentEntryFound = false; + QString name = kabEntry->mName; + + + // + // Identify Type of Phonenumber using possibly appended suffixes. + // If a suffix is found, remove it from the name. + // + if ( goon && (*mPrefs).useHomeSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).homeSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Home; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useWorkSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).workSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Work; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useMessagingSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).messagingSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Msg; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useFaxSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).faxSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Fax; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useCellSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).cellSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Cell; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useVideoSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).videoSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Video; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useMailboxSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).mailboxSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Bbs; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useModemSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).modemSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Modem; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useCarSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).carSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Car; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).useISDNSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).iSDNSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Isdn; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + if ( goon && (*mPrefs).usePagerSuff() ) { + QString theSuffix = decodeSuffix( (*mPrefs).pagerSuff() ); + if ( name.right( theSuffix.length() ) == theSuffix ) { + phoneType = KABC::PhoneNumber::Pager; + name = stripWhiteSpaces( + name.left( name.length() - theSuffix.length() ) ); + goon = false; + } + } + + + // + // Search for a KAB entry whose name, if formatted in exactly the + // same way as was done in readKabc, is equal to the actual name. + // + + for ( it = addressBook->begin(); it != addressBook->end(); it++ ) { + QString kabName = (*it).familyName(); + KABC::AddressBook::Iterator it3; + KABC::Addressee::List tmp; + bool firstCharIsUnique = true; + unsigned int minLength; + + + for ( it3 = addressBook->begin(); it3 != addressBook->end(); it3++ ) + if ( ( (*it3).familyName() == kabName ) && ( it3 != it ) ) { + tmp.append( (*it3) ); + if ( (*it3).givenName()[0] == (*it).givenName()[0] ) + firstCharIsUnique = false; + } + + // There are several KAB entries with the same family name. + // So, we need to append the given name in order to + // distinguish them. + if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) { + kabName += ", "; + + if ( firstCharIsUnique ) + kabName += (*it).givenName()[0] + "."; + else + kabName += (*it).givenName(); + } + + // Truncate name field if it's too long for mobile phone + if ( kabName.length() > mPBNameLength ) + kabName = kabName.remove( mPBNameLength, + kabName.length() - mPBNameLength ); + + minLength = kabName.length(); + if ( name.length() < minLength ) + minLength = name.length(); + + if ( name.left( minLength ) == kabName.left( minLength ) ) { + (*it).insertPhoneNumber( KABC::PhoneNumber( phoneNumber, + phoneType ) ); + + equivalentEntryFound = true; + break; + } + } + + // + // If no equivalent entry was found in KAB, we need to generate + // a complete new entry. + // + + if ( !equivalentEntryFound ) { + KABC::Addressee entry; + QStringList *fields = new QStringList; + + + *fields = QStringList::split( ',', name ); + + if ( fields->count() > 1 ) { + // Name string contains comma separated entry so that we + // need to build family and given names out of them. + QString givenName = ""; + + + entry.setFamilyName( stripWhiteSpaces( (*fields)[ 0 ] ) ); + + for ( unsigned int i = 1; i < fields->count(); i++ ) + givenName += stripWhiteSpaces( (*fields)[ i ] ) + " "; + entry.setGivenName( stripWhiteSpaces( givenName ) ); + } else + // Name string contains only one string without comma. + entry.setFamilyName( stripWhiteSpaces( name ) ); + + entry.insertPhoneNumber( KABC::PhoneNumber( phoneNumber, phoneType ) ); + + addressBook->insertAddressee( entry ); + } + } + + kabEntry->mToBeUpdated = false; + kabEntry->mToBeInserted = false; + } + + addressBook->save( ticket ); + + emit transientStatusMessage( i18n( "Wrote KDE address book." ) ); + + setKabState( LOADED ); +} + + +void MobileGui::refreshStatus() +{ + mScheduler->executeId( "+cbc" ); + mScheduler->executeId( "+csq" ); +} + + +void MobileGui::processResult( ATCommand *command ) +{ + if ( command->id() == "+cbc" ) + mBatteryChargeLabel->setText( command->resultField( 1 ) + " %" ); + else + if ( command->id() == "+csq" ) + mSignalQualityLabel->setText( command->resultField( 0 ) ); + else + if ( command->id() == "+cgmi" ) { + mMobManufacturer = command->resultField( 0 ); + mManufacturerLabel->setText( mMobManufacturer ); + } else + if ( command->id() == "+cgmm" ) { + mMobModel = command->resultField( 0 ); + mModelLabel->setText( mMobModel ); + } else + if ( command->id() == "+cgmr" ) + mGSMVersionLabel->setText( command->resultField( 0 ) ); + else + if ( command->id() == "+cgsn" ) + mSerialNumberLabel->setText( command->resultField( 0 ) ); + else + if ( command->id() == "+cpbr=?" ) + { + QStringList tmpList = QStringList::split( "-", command->resultField( 0 ) ); + QString tmpString = tmpList.first().right( tmpList.first().length() - 1 ); + mPBStartIndex = tmpString.toUInt(); + mPBNameLength = command->resultField( 2 ).toUInt(); + } else + if ( command->id() == "+cpbs?" ) { + mPBLength = command->resultField( 2 ).toUInt(); + + // Allocate and initialize memory for the buckets of indices + mPBIndexOccupied.resize( mPBLength, false ); + for ( unsigned int i = 0; i < mPBLength; i++ ) + mPBIndexOccupied[ i ] = false; + } else + if ( command->id() == "+cpbr=" ) { + fillPhonebook( command ); + + if ( mComingFromSyncPhonebooks ) { + mComingFromSyncPhonebooks = false; + mergePhonebooks(); + } + } else + if ( command->id() == mLastWriteId ) + writePhonebookPostProcessing(); + else + if ( command->id() == "+cpbs=?" ) { + QPtrList<QStringList> *list = command->resultFields(); + QStringList *fields = list->first(); + + + while( fields ) { + for ( unsigned int i = 0; i < fields->count(); i++ ) { + QString memory = dequote( (*fields)[ i ] ); + + + if ( memory == "FD" ) + mMobHasFD = true; + else + if ( memory == "LD" ) + mMobHasLD = true; + else + if ( memory == "ME" ) + mMobHasME = true; + else + if ( memory == "MT" ) + mMobHasMT = true; + else + if ( memory == "TA" ) + mMobHasTA = true; + else + if ( ( memory == "OW" ) || + ( ( memory == "ON" ) && ( mMobManufacturer == "SIEMENS" ) ) ) + mMobHasOW = true; + else + if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "MC" ) ) + mMobHasMC = true; + else + if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "RC" ) ) + mMobHasRC = true; + } + + fields = list->next(); + } + } +} + + +QString MobileGui::noSpaces( const QString &theString ) +{ + QString result = ""; + + + for ( unsigned int i = 0; i < theString.length(); i++ ) + if ( theString[ i ].latin1() != ' ' ) + result += theString[ i ]; + + return result; +} + + +int MobileGui::firstFreeIndex() +{ + unsigned int i; + + + if ( mPBIndexOccupied.capacity() == 0 ) + return 0; + + for ( i = 1; i < mPBLength; i++ ) + if ( !mPBIndexOccupied[ i ] ) + break; + + if ( i < mPBLength ) + return i; + + return 0; +} + + +QString MobileGui::string2GSM( const QString &theString ) +{ + QString result = ""; + + + for ( unsigned int i = 0; i < theString.length(); i++ ) + switch ( theString[ i ].latin1() ) { + case 'Ä': result += '['; break; + case 'ä': result += '{'; break; + case 'Ö': result += 92; break; + case 'ö': result += '|'; break; + case 'Ü': result += '^'; break; + case 'ü': result += '~'; break; + case 'ß': result += 30; break; + case 'è': result += 4; break; + case 'é': result += 5; break; + + default: result += theString[ i ]; + } + + return result; +} + + +QString MobileGui::GSM2String( const QString &theString ) +{ + QString result = ""; + + + for ( unsigned int i = 0; i < theString.length(); i++ ) + switch ( theString[ i ].latin1() ) { + case '[': result += 'Ä'; break; + case '{': result += 'ä'; break; + case 92: result += 'Ö'; break; + case '|': result += 'ö'; break; + case '^': result += 'Ü'; break; + case '~': result += 'ü'; break; + case 30: result += 'ß'; break; + case 4: result += 'è'; break; + case 5: result += 'é'; break; + + default: result += theString[ i ]; + } + + return result; +} + + +void MobileGui::fillPhonebook( ATCommand *cmd ) +{ + mSyncer->mMobileEntries.clear(); + + QPtrList<QStringList> *list = cmd->resultFields(); + QStringList *fields = list->first(); + + while( fields ) { + if ( fields->count() != 4 ) + kdDebug() << "Error! Unexpected number of address fields." << endl; + else { + QString index = (*fields)[0]; + QString phone = (*fields)[1]; + QString type = (*fields)[2]; + QString name = GSM2String( (*fields)[3] ); + + SyncEntryMobile *phoneEntry = new SyncEntryMobile( true, dequote( index ), + dequote( phone ), + dequote( name ) ); + mPBIndexOccupied[ index.toUInt() - mPBStartIndex ] = true; + mSyncer->mMobileEntries.append( phoneEntry ); + } + fields = list->next(); + } + + // Display mobile entries + updateMobileBook(); + + emit transientStatusMessage(i18n("Read mobile phonebook.")); + emit phonebookRead(); + + setMobState( LOADED ); +} + + +QString MobileGui::quote( const QString &str ) +{ + if ( ( str.left(1) == "\"" ) && ( str.right(1) == "\"" ) ) + return str; + + return "\"" + str + "\""; +} + + +QString MobileGui::dequote( const QString &str ) +{ + int pos = 0; + int len = str.length(); + + + if ( str.left(1) == "\"" ) { + pos = 1; + len --; + } + + if ( str.right(1) == "\"" ) + len--; + + return str.mid( pos, len ); +} + + +void MobileGui::savePhonebook() +{ + if ( mMobState == UNLOADED ) + return; + + QString fileName = KFileDialog::getSaveFileName( "phonebook.csv" ); + QFile outFile( fileName ); + + if ( outFile.open( IO_WriteOnly ) ) { + QTextStream t( &outFile ); // use a text stream + + for( uint i = 0; i < mSyncer->mMobileEntries.count(); i++) { + SyncEntryMobile *e = mSyncer->mMobileEntries.at( i ); + + + if ( !e->mToBeDeleted ) + t << e->mIndex << "," << e->mPhone << "," << e->mName << endl; + } + + outFile.close(); + } +} + + +void MobileGui::deleteMobPhonebook() +{ + + // + // Process all elements selected in the GUI + // + + PhoneBookItem *item = (PhoneBookItem *) mMobileBook->firstChild(); + while ( item ) { + if ( item->isOn() ) { + SyncEntryMobile *mobileItem = (SyncEntryMobile *) item->syncEntry(); + + + // Deselect current item + item->setOn( false ); + mobileItem->mOn = false; + + // Mark current item as deleted + mobileItem->mToBeDeleted = true; + } + + item = (PhoneBookItem *) item->nextSibling(); + } + + // Update GUI + updateMobileBook(); + setMobState( MODIFIED ); +} + + +void MobileGui::mergePhonebooks() +{ + uint i; + + + // + // Transfer current Selection State from GUI to mSyncer + // + + PhoneBookItem *item = (PhoneBookItem *) mKabBook->firstChild(); + while ( item ) { + item->syncEntry()->mOn = item->isOn(); + item = (PhoneBookItem *) item->nextSibling(); + } + + item = (PhoneBookItem *) mMobileBook->firstChild(); + while ( item ) { + item->syncEntry()->mOn = item->isOn(); + item = (PhoneBookItem *) item->nextSibling(); + } + + mSyncer->mCommonEntries.clear(); + + + // + // Put KDE Address Book list into Common List + // + + for ( i = 0; i < mSyncer->mKabEntries.count(); i++ ) + if ( mSyncer->mKabEntries.at( i )->mOn ) { + mSyncer->mCommonEntries.append( + new SyncEntryCommon( true, mSyncer->mKabEntries.at( i ), 0 ) ); + mSyncer->mKabEntries.at( i )->mOn = false; + } + + + // + // Put Mobile Address Book list into Common List; Merge equivalent entries + // + + for ( i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { + SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at( i ); + bool equivalentEntryFound = false; + uint j; + + + if( !mobileEntry->mToBeDeleted ) + for ( j = 0; j < mSyncer->mCommonEntries.count(); j++ ) { + SyncEntryCommon *theCommonEntry = mSyncer->mCommonEntries.at( j ); + + + if ( theCommonEntry->mKabEntry && + ( theCommonEntry->mKabEntry->mName == mobileEntry->mName ) ) { + theCommonEntry->mMobileEntry = mobileEntry; + equivalentEntryFound = true; + + if ( noSpaces( theCommonEntry->mKabEntry->mPhone ) == + mobileEntry->mPhone ) { + mobileEntry->mOn = false; + break; + } else { + // Conflict: 2 Entries have same name but different numbers. + // Prompt user. + QString text = "<qt><b>" + i18n( "Kab Entry:" ) + "</b><br>"; + text += " " + theCommonEntry->mKabEntry->mName + " " + + theCommonEntry->mKabEntry->mPhone + "<br>"; + text += "<b>" + i18n( "Mobile Entry:" ) + "</b><br>"; + text += " " + mobileEntry->mName + " " + mobileEntry->mPhone; + text += "</qt>"; + + QMessageBox *msg = + new QMessageBox( i18n( "Conflicting Entries" ), text, + QMessageBox::Warning, 1, 2, 0, this ); + msg->setButtonText( 1, i18n( "Use Kab Entry" ) ); + msg->setButtonText( 2, i18n( "Use Mobile Entry" ) ); + + switch ( msg->exec() ) { + case 1: + // Use KDE Address Book Entry + mobileEntry->mPhone = theCommonEntry->mKabEntry->mPhone; + mobileEntry->mName = theCommonEntry->mKabEntry->mName; + mobileEntry->mOn = true; + mobileEntry->mToBeUpdated = true; + + setMobState( MODIFIED ); + break; + + case 2: + // Use Mobile Address Book Entry + theCommonEntry->mKabEntry->mPhone = mobileEntry->mPhone; + theCommonEntry->mKabEntry->mName = mobileEntry->mName; + theCommonEntry->mKabEntry->mOn = true; + theCommonEntry->mKabEntry->mToBeUpdated = true; + + mobileEntry->mOn = false; + + setKabState( MODIFIED ); + break; + } + } + } + } + + if ( !equivalentEntryFound && mobileEntry->mOn ) { + // No equivalent entry exists; generate a new one. + mSyncer->mCommonEntries.append( + new SyncEntryCommon( true, 0, mobileEntry ) ); + mobileEntry->mOn = false; + } + } + + + // + // Create new KAB and Mobile Entries + // + + for ( i = 0; i < mSyncer->mCommonEntries.count(); i++ ) { + SyncEntryCommon *entry = mSyncer->mCommonEntries.at( i ); + SyncEntryKab *kabEntry = entry->mKabEntry; + SyncEntryMobile *mobileEntry = entry->mMobileEntry; + + + if ( kabEntry && !mobileEntry ) { + // Create Mobile Entry + entry->mMobileEntry = new SyncEntryMobile( true, "", kabEntry->mPhone, + kabEntry->mName ); + entry->mMobileEntry->mToBeInserted = true; + mSyncer->mMobileEntries.append( entry->mMobileEntry ); + + setMobState( MODIFIED ); + } else + if ( mobileEntry && !kabEntry ) { + // Create KAB Entry + entry->mKabEntry = new SyncEntryKab( true, mobileEntry->mIndex, + mobileEntry->mName, + mobileEntry->mPhone ); + entry->mKabEntry->mToBeInserted = true; + mSyncer->mKabEntries.append( entry->mKabEntry ); + + setKabState( MODIFIED ); + } + } + + + // + // Update GUI + // + + updateKabBook(); + updateMobileBook(); + + emit transientStatusMessage( i18n( "Synced phonebooks." ) ); + PushButton8_3->setEnabled( true ); +} + + +void MobileGui::syncPhonebooks() +{ + PushButton8_3->setEnabled( false ); + + if ( mKabState == UNLOADED ) + readKabc(); + if ( mMobState == UNLOADED ) { + mComingFromSyncPhonebooks = true; + readPhonebook(); + } else + mergePhonebooks(); +} + + +void MobileGui::updateKabBook() +{ + mKabBook->clear(); + + for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) { + SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i ); + PhoneBookItem *item = new PhoneBookItem( mKabBook, kabEntry, + kabEntry->mName, kabEntry->mPhone, + kabEntry->mIndex ); + item->setOn( kabEntry->mOn ); + } +} + + +void MobileGui::updateMobileBook() +{ + mMobileBook->clear(); + + for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) { + SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i ); + + if ( !entry->mToBeDeleted ) { + PhoneBookItem *item = new PhoneBookItem( mMobileBook, entry, entry->mName, + entry->mPhone, entry->mIndex ); + item->setOn( entry->mOn ); + } + } +} + + +void MobileGui::toggleConnection() +{ + if ( mConnectButton->text() == i18n( "Connect" ) ) { + emit connectModem(); + + readModelInformation(); + refreshStatus(); + + mConnectButton->setText( tr2i18n( "Disconnect" ) ); + PushButton1->setEnabled( true ); + PushButton5_3->setEnabled( true ); + + mABTab->setEnabled( true ); + setKabState( UNLOADED ); + setMobState( UNLOADED ); + + ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Connected "), 1 ); + } else { + warnKabState( UNLOADED ); + + mComingFromToggleConnection = true; + if ( !warnMobState( UNLOADED ) ) { + mComingFromToggleConnection = false; + disconnectGUI(); + } + } +} + + +void MobileGui::disconnectGUI() +{ + emit disconnectModem(); + + mManufacturerLabel->setText( "x" ); + mModelLabel->setText( "x" ); + mGSMVersionLabel->setText( "x" ); + mSerialNumberLabel->setText( "x" ); + + mBatteryChargeLabel->setText( "xx %" ); + mSignalQualityLabel->setText( "x" ); + + mConnectButton->setText( tr2i18n( "Connect" ) ); + PushButton1->setEnabled( false ); + PushButton5_3->setEnabled( false ); + + mKabBook->clear(); + mMobileBook->clear(); + setKabState( UNLOADED ); + setMobState( UNLOADED ); + + mABTab->setEnabled( false ); + + mMobHasFD = false; + mMobHasLD = false; + mMobHasME = false; + mMobHasMT = false; + mMobHasTA = false; + mMobHasOW = false; + mMobHasMC = false; + mMobHasRC = false; + + mPBIndexOccupied.resize( 0, false ); + + ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Disconnected "), + 1 ); +} + + +void MobileGui::termAddOutput( const char *line ) +{ + mTermIO->append( line ); + mTermIO->setCursorPosition( mTermIO->paragraphs() - 1, 0 ); +} + + +void MobileGui::setKabState( ABState newState ) +{ + switch ( mKabState ) { + case UNLOADED: + groupBox3->setTitle( tr2i18n( "KDE Address Book" ) ); + mReadKabButton->setEnabled( true ); + PushButton8->setEnabled( false ); + break; + + case LOADED: + if ( newState == MODIFIED ) { + groupBox3->setTitle( tr2i18n( "KDE Address Book (modified)" ) ); + mReadKabButton->setEnabled( true ); + PushButton8->setEnabled( true ); + } else + if ( newState == UNLOADED ) { + groupBox3->setTitle( tr2i18n( "KDE Address Book" ) ); + mReadKabButton->setEnabled( true ); + PushButton8->setEnabled( false ); + } + break; + + case MODIFIED: + if ( newState != MODIFIED ) { + groupBox3->setTitle( tr2i18n( "KDE Address Book" ) ); + mReadKabButton->setEnabled( true ); + PushButton8->setEnabled( false ); + } + break; + } + + mKabState = newState; +} + + +void MobileGui::warnKabState( ABState newState ) +{ + if ( ( mKabState == MODIFIED ) && ( newState != MODIFIED ) ) { + QString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>"; + text += i18n( "The KDE address book contains unsaved changes." ) + + "<br></qt>"; + + QMessageBox *msg = new QMessageBox( i18n( "Unsaved Changes" ), text, + QMessageBox::Critical, 1, 2, 0, this ); + msg->setButtonText( 1, i18n( "Save" ) ); + msg->setButtonText( 2, i18n( "Discard" ) ); + + switch ( msg->exec() ) { + case 1: + // Save Changes first + writeKabc(); + break; + + case 2: + break; + } + } +} + + +void MobileGui::setMobState( ABState newState ) +{ + switch ( mMobState ) { + case UNLOADED: + if ( newState == UNLOADED ) { + groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); + PushButton3->setEnabled( true ); + PushButton12->setEnabled( false ); + PushButton4_2->setEnabled( false ); + MobDeleteButton->setEnabled( false ); + } else + if ( newState == LOADED ) { + groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); + PushButton3->setEnabled( true ); + PushButton12->setEnabled( false ); + PushButton4_2->setEnabled( true ); + MobDeleteButton->setEnabled( true ); + } + break; + + case LOADED: + if ( newState == MODIFIED ) { + groupBox4->setTitle( tr2i18n( "Mobile Phone Book (modified)" ) ); + PushButton3->setEnabled( true ); + PushButton12->setEnabled( true ); + PushButton4_2->setEnabled( true ); + MobDeleteButton->setEnabled( true ); + } else + if ( newState == UNLOADED ) { + groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); + PushButton3->setEnabled( true ); + PushButton12->setEnabled( false ); + PushButton4_2->setEnabled( false ); + MobDeleteButton->setEnabled( false ); + } + break; + + case MODIFIED: + if ( newState == UNLOADED ) { + groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); + PushButton3->setEnabled( true ); + PushButton12->setEnabled( false ); + PushButton4_2->setEnabled( false ); + MobDeleteButton->setEnabled( false ); + } else + if ( newState == LOADED ) { + groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) ); + PushButton3->setEnabled( true ); + PushButton12->setEnabled( false ); + PushButton4_2->setEnabled( true ); + MobDeleteButton->setEnabled( true ); + } + break; + } + + mMobState = newState; +} + + +bool MobileGui::warnMobState( ABState newState ) +{ + if ( ( mMobState == MODIFIED ) && ( newState != MODIFIED ) ) + { + QString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>"; + text += i18n( "The mobile phone book contains unsaved changes." ) + + "<br></qt>"; + + QMessageBox *msg = new QMessageBox( i18n( "Unsaved Changes" ), text, + QMessageBox::Critical, 1, 2, 0, this ); + msg->setButtonText( 1, i18n( "Save" ) ); + msg->setButtonText( 2, i18n( "Discard" ) ); + + switch ( msg->exec() ) { + case 1: + // Save Changes first + writePhonebook(); + return true; + break; + + case 2: + return false; + break; + } + } + + return false; +} |