-rw-r--r-- | kaddressbook/kabcore.cpp | 11 | ||||
-rw-r--r-- | kaddressbook/kaddressbook.pro | 31 | ||||
-rw-r--r-- | kaddressbook/mainembedded.cpp | 30 |
3 files changed, 34 insertions, 38 deletions
diff --git a/kaddressbook/kabcore.cpp b/kaddressbook/kabcore.cpp index 505cbf4..590cc82 100644 --- a/kaddressbook/kabcore.cpp +++ b/kaddressbook/kabcore.cpp @@ -1,351 +1,352 @@ /* This file is part of KAddressbook. Copyright (c) 2003 Tobias Koenig <tokoe@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */ /*s Enhanced Version of the file for platform independent KDE tools. Copyright (c) 2004 Ulf Schenk $Id$ */ #include "kabcore.h" #include <stdaddressbook.h> #include <klocale.h> #include <kfiledialog.h> #include <qtimer.h> #include <qlabel.h> #include <qregexp.h> #include <qlineedit.h> #include <qcheckbox.h> #include <qpushbutton.h> #include <qprogressbar.h> #include <libkdepim/phoneaccess.h> #ifndef KAB_EMBEDDED #include <qclipboard.h> #include <qdir.h> #include <qfile.h> #include <qapplicaton.h> #include <qprogressbar.h> #include <qlayout.h> #include <qregexp.h> #include <qvbox.h> #include <kabc/addresseelist.h> #include <kabc/errorhandler.h> #include <kabc/resource.h> #include <kabc/vcardconverter.h> #include <kapplication.h> #include <kactionclasses.h> #include <kcmultidialog.h> #include <kdebug.h> #include <kdeversion.h> #include <kkeydialog.h> #include <kmessagebox.h> #include <kprinter.h> #include <kprotocolinfo.h> #include <kresources/selectdialog.h> #include <kstandarddirs.h> #include <ktempfile.h> #include <kxmlguiclient.h> #include <kaboutdata.h> #include <libkdepim/categoryselectdialog.h> #include "addresseeutil.h" #include "addresseeeditordialog.h" #include "extensionmanager.h" #include "kstdaction.h" #include "kaddressbookservice.h" #include "ldapsearchdialog.h" #include "printing/printingwizard.h" #else // KAB_EMBEDDED #include <kapplication.h> #include "KDGanttMinimizeSplitter.h" #include "kaddressbookmain.h" #include "kactioncollection.h" #include "addresseedialog.h" //US #include <addresseeview.h> #include <qapp.h> #include <qmenubar.h> //#include <qtoolbar.h> #include <qmessagebox.h> #include <kdebug.h> #include <kiconloader.h> // needed for SmallIcon #include <kresources/kcmkresources.h> #include <ktoolbar.h> //#include <qlabel.h> #ifndef DESKTOP_VERSION #include <qpe/ir.h> #include <qpe/qpemenubar.h> #include <qtopia/qcopenvelope_qws.h> #else #include <qmenubar.h> #endif #endif // KAB_EMBEDDED #include "kcmconfigs/kcmkabconfig.h" #include "kcmconfigs/kcmkdepimconfig.h" #include "kpimglobalprefs.h" #include "externalapphandler.h" #include "xxportselectdialog.h" #include <kresources/selectdialog.h> #include <kmessagebox.h> #include <picture.h> #include <resource.h> //US#include <qsplitter.h> #include <qmap.h> #include <qdir.h> #include <qfile.h> #include <qvbox.h> #include <qlayout.h> #include <qclipboard.h> #include <qtextstream.h> #include <qradiobutton.h> #include <qbuttongroup.h> #include <libkdepim/categoryselectdialog.h> #include <libkdepim/categoryeditdialog.h> #include <kabc/vcardconverter.h> #include "addresseeutil.h" #include "undocmds.h" #include "addresseeeditordialog.h" #include "viewmanager.h" #include "details/detailsviewcontainer.h" #include "kabprefs.h" #include "xxportmanager.h" #include "incsearchwidget.h" #include "jumpbuttonbar.h" #include "extensionmanager.h" #include "addresseeconfig.h" #include "nameeditdialog.h" #include <kcmultidialog.h> #ifdef _WIN32_ - +#ifdef _OL_IMPORT_ #include "kaimportoldialog.h" +#endif #else #include <unistd.h> #endif // sync includes #include <libkdepim/ksyncprofile.h> #include <libkdepim/ksyncprefsdialog.h> class KABCatPrefs : public QDialog { public: KABCatPrefs( QWidget *parent=0, const char *name=0 ) : QDialog( parent, name, true ) { setCaption( i18n("Manage new Categories") ); QVBoxLayout* lay = new QVBoxLayout( this ); lay->setSpacing( 3 ); lay->setMargin( 3 ); QLabel * lab = new QLabel( i18n("After importing/loading/syncing\nthere may be new categories in\naddressees\nwhich are not in the category list.\nPlease choose what to do:\n "), this ); lay->addWidget( lab ); QButtonGroup* format = new QButtonGroup( 1, Horizontal, i18n("New categories not in list:"), this ); lay->addWidget( format ); format->setExclusive ( true ) ; addCatBut = new QRadioButton(i18n("Add to category list"), format ); new QRadioButton(i18n("Remove from addressees"), format ); addCatBut->setChecked( true ); QPushButton * ok = new QPushButton( i18n("OK"), this ); lay->addWidget( ok ); QPushButton * cancel = new QPushButton( i18n("Cancel"), this ); lay->addWidget( cancel ); connect ( ok,SIGNAL(clicked() ),this , SLOT ( accept() ) ); connect (cancel, SIGNAL(clicked() ), this, SLOT ( reject()) ); resize( 200, 200 ); } bool addCat() { return addCatBut->isChecked(); } private: QRadioButton* addCatBut; }; class KABFormatPrefs : public QDialog { public: KABFormatPrefs( QWidget *parent=0, const char *name=0 ) : QDialog( parent, name, true ) { setCaption( i18n("Set formatted name") ); QVBoxLayout* lay = new QVBoxLayout( this ); lay->setSpacing( 3 ); lay->setMargin( 3 ); QLabel * lab = new QLabel( i18n("You can set the formatted name\nfor a list of contacts in one go."), this ); lay->addWidget( lab ); QButtonGroup* format = new QButtonGroup( 1, Horizontal, i18n("Set formatted name to:"), this ); lay->addWidget( format ); format->setExclusive ( true ) ; simple = new QRadioButton(i18n("Simple: James Bond"), format ); full = new QRadioButton(i18n("Full: Mr. James 007 Bond I"), format ); reverse = new QRadioButton(i18n("Reverse: Bond, James"), format ); company = new QRadioButton(i18n("Organization: MI6"), format ); simple->setChecked( true ); setCompany = new QCheckBox(i18n("Set formatted name to\norganization, if name empty"), this); lay->addWidget( setCompany ); QPushButton * ok = new QPushButton( i18n("Select contact list"), this ); lay->addWidget( ok ); QPushButton * cancel = new QPushButton( i18n("Cancel"), this ); lay->addWidget( cancel ); connect ( ok,SIGNAL(clicked() ),this , SLOT ( accept() ) ); connect (cancel, SIGNAL(clicked() ), this, SLOT ( reject()) ); //resize( 200, 200 ); } public: QRadioButton* simple, *full, *reverse, *company; QCheckBox* setCompany; }; class KAex2phonePrefs : public QDialog { public: KAex2phonePrefs( QWidget *parent=0, const char *name=0 ) : QDialog( parent, name, true ) { setCaption( i18n("Export to phone options") ); QVBoxLayout* lay = new QVBoxLayout( this ); lay->setSpacing( 3 ); lay->setMargin( 3 ); QLabel *lab; lay->addWidget(lab = new QLabel( i18n("Please read Help-Sync Howto\nto know what settings to use."), this ) ); lab->setAlignment (AlignHCenter ); QHBox* temphb; temphb = new QHBox( this ); new QLabel( i18n("I/O device: "), temphb ); mPhoneDevice = new QLineEdit( temphb); lay->addWidget( temphb ); temphb = new QHBox( this ); new QLabel( i18n("Connection: "), temphb ); mPhoneConnection = new QLineEdit( temphb); lay->addWidget( temphb ); temphb = new QHBox( this ); new QLabel( i18n("Model(opt.): "), temphb ); mPhoneModel = new QLineEdit( temphb); lay->addWidget( temphb ); // mWriteToSim = new QCheckBox( i18n("Write Contacts to SIM card\n(if not, write to phone memory)"), this ); // lay->addWidget( mWriteToSim ); lay->addWidget(lab = new QLabel( i18n("NOTE: This will remove all old\ncontact data on phone!"), this ) ); lab->setAlignment (AlignHCenter); QPushButton * ok = new QPushButton( i18n("Export to mobile phone!"), this ); lay->addWidget( ok ); QPushButton * cancel = new QPushButton( i18n("Cancel"), this ); lay->addWidget( cancel ); connect ( ok,SIGNAL(clicked() ),this , SLOT ( accept() ) ); connect (cancel, SIGNAL(clicked() ), this, SLOT ( reject()) ); resize( 220, 240 ); } public: QLineEdit* mPhoneConnection, *mPhoneDevice, *mPhoneModel; QCheckBox* mWriteToSim; }; bool pasteWithNewUid = true; #ifdef KAB_EMBEDDED KABCore::KABCore( KAddressBookMain *client, bool readWrite, QWidget *parent, const char *name ) : QWidget( parent, name ), KSyncInterface(), mGUIClient( client ), mViewManager( 0 ), mExtensionManager( 0 ),mConfigureDialog( 0 ),/*US mLdapSearchDialog( 0 ),*/ mReadWrite( readWrite ), mModified( false ), mMainWindow(client) #else //KAB_EMBEDDED KABCore::KABCore( KXMLGUIClient *client, bool readWrite, QWidget *parent, const char *name ) : QWidget( parent, name ), KSyncInterface(), mGUIClient( client ), mViewManager( 0 ), mExtensionManager( 0 ), mConfigureDialog( 0 ), mLdapSearchDialog( 0 ), mReadWrite( readWrite ), mModified( false ) #endif //KAB_EMBEDDED { // syncManager = new KSyncManager((QWidget*)this, (KSyncInterface*)this, KSyncManager::KAPI, KABPrefs::instance(), syncMenu); // syncManager->setBlockSave(false); mMiniSplitter = 0; mExtensionBarSplitter = 0; mIsPart = !parent->inherits( "KAddressBookMain" ); mAddressBook = KABC::StdAddressBook::self(); KABC::StdAddressBook::setAutomaticSave( false ); #ifndef KAB_EMBEDDED mAddressBook->setErrorHandler( new KABC::GUIErrorHandler ); #endif //KAB_EMBEDDED connect( mAddressBook, SIGNAL( addressBookChanged( AddressBook * ) ), SLOT( addressBookChanged() ) ); #if 0 // LP moved to addressbook init method mAddressBook->addCustomField( i18n( "Department" ), KABC::Field::Organization, "X-Department", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Profession" ), KABC::Field::Organization, "X-Profession", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Assistant's Name" ), KABC::Field::Organization, "X-AssistantsName", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Manager's Name" ), KABC::Field::Organization, "X-ManagersName", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Spouse's Name" ), KABC::Field::Personal, "X-SpousesName", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Office" ), KABC::Field::Personal, "X-Office", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "IM Address" ), KABC::Field::Personal, "X-IMAddress", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Anniversary" ), KABC::Field::Personal, "X-Anniversary", "KADDRESSBOOK" ); //US added this field to become compatible with Opie/qtopia addressbook // values can be "female" or "male" or "". An empty field represents undefined. mAddressBook->addCustomField( i18n( "Gender" ), KABC::Field::Personal, "X-Gender", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "Children" ), KABC::Field::Personal, "X-Children", "KADDRESSBOOK" ); mAddressBook->addCustomField( i18n( "FreeBusyUrl" ), KABC::Field::Personal, "X-FreeBusyUrl", "KADDRESSBOOK" ); #endif initGUI(); mIncSearchWidget->setFocus(); connect( mViewManager, SIGNAL( selected( const QString& ) ), SLOT( setContactSelected( const QString& ) ) ); connect( mViewManager, SIGNAL( executed( const QString& ) ), SLOT( executeContact( const QString& ) ) ); connect( mViewManager, SIGNAL( deleteRequest( ) ), @@ -1102,385 +1103,385 @@ void KABCore::setCategories() uids = dlgx.uids(); else return; if ( uids.isEmpty() ) return; // qDebug("count %d ", uids.count()); KPIM::CategorySelectDialog dlg( KABPrefs::instance(), this, "", true ); if ( !dlg.exec() ) { message( i18n("Setting categories cancelled") ); return; } bool merge = false; QString msg = i18n( "Merge with existing categories?" ); if ( KMessageBox::questionYesNo( this, msg ) == KMessageBox::Yes ) merge = true; message( i18n("Setting categories ... please wait!") ); QStringList categories = dlg.selectedCategories(); //QStringList uids = mViewManager->selectedUids(); QStringList::Iterator it; for ( it = uids.begin(); it != uids.end(); ++it ) { KABC::Addressee addr = mAddressBook->findByUid( *it ); if ( !addr.isEmpty() ) { if ( !merge ) addr.setCategories( categories ); else { QStringList addrCategories = addr.categories(); QStringList::Iterator catIt; for ( catIt = categories.begin(); catIt != categories.end(); ++catIt ) { if ( !addrCategories.contains( *catIt ) ) addrCategories.append( *catIt ); } addr.setCategories( addrCategories ); } mAddressBook->insertAddressee( addr ); } } if ( uids.count() > 0 ) setModified( true ); message( i18n("Setting categories completed!") ); } void KABCore::setSearchFields( const KABC::Field::List &fields ) { mIncSearchWidget->setFields( fields ); } void KABCore::incrementalSearch( const QString& text ) { mViewManager->doSearch( text, mIncSearchWidget->currentField() ); } void KABCore::setModified() { setModified( true ); } void KABCore::setModifiedWOrefresh() { // qDebug("KABCore::setModifiedWOrefresh() "); mModified = true; mActionSave->setEnabled( mModified ); } void KABCore::setModified( bool modified ) { mModified = modified; mActionSave->setEnabled( mModified ); if ( modified ) mJumpButtonBar->recreateButtons(); mViewManager->refreshView(); } bool KABCore::modified() const { return mModified; } void KABCore::contactModified( const KABC::Addressee &addr ) { addrModified( addr ); #if 0 // debug only KABC::Addressee ad = addr; ad.computeCsum( "123"); #endif } void KABCore::addrModified( const KABC::Addressee &addr ,bool updateDetails ) { Command *command = 0; QString uid; // check if it exists already KABC::Addressee origAddr = mAddressBook->findByUid( addr.uid() ); if ( origAddr.isEmpty() ) command = new PwNewCommand( mAddressBook, addr ); else { command = new PwEditCommand( mAddressBook, origAddr, addr ); uid = addr.uid(); } UndoStack::instance()->push( command ); RedoStack::instance()->clear(); if ( updateDetails ) mDetails->setAddressee( addr ); setModified( true ); } void KABCore::newContact() { QPtrList<KABC::Resource> kabcResources = mAddressBook->resources(); QPtrList<KRES::Resource> kresResources; QPtrListIterator<KABC::Resource> it( kabcResources ); KABC::Resource *resource; while ( ( resource = it.current() ) != 0 ) { ++it; if ( !resource->readOnly() ) { KRES::Resource *res = static_cast<KRES::Resource*>( resource ); if ( res ) kresResources.append( res ); } } KRES::Resource *res = KRES::SelectDialog::getResource( kresResources, this ); resource = static_cast<KABC::Resource*>( res ); if ( resource ) { KABC::Addressee addr; addr.setResource( resource ); mEditorDialog->setAddressee( addr ); KApplication::execDialog ( mEditorDialog ); } else return; // mEditorDict.insert( dialog->addressee().uid(), dialog ); } void KABCore::addEmail( QString aStr ) { #ifndef KAB_EMBEDDED QString fullName, email; KABC::Addressee::parseEmailAddress( aStr, fullName, email ); // Try to lookup the addressee matching the email address bool found = false; QStringList emailList; KABC::AddressBook::Iterator it; for ( it = mAddressBook->begin(); !found && (it != mAddressBook->end()); ++it ) { emailList = (*it).emails(); if ( emailList.contains( email ) > 0 ) { found = true; (*it).setNameFromString( fullName ); editContact( (*it).uid() ); } } if ( !found ) { KABC::Addressee addr; addr.setNameFromString( fullName ); addr.insertEmail( email, true ); mAddressBook->insertAddressee( addr ); mViewManager->refreshView( addr.uid() ); editContact( addr.uid() ); } #else //KAB_EMBEDDED qDebug("KABCore::addEmail finsih method"); #endif //KAB_EMBEDDED } void KABCore::importVCard( const KURL &url, bool showPreview ) { mXXPortManager->importVCard( url, showPreview ); } void KABCore::importFromOL() { -#ifdef _WIN32_ +#ifdef _OL_IMPORT_ KAImportOLdialog* idgl = new KAImportOLdialog( i18n("Import Contacts from OL"), mAddressBook, this ); idgl->exec(); KABC::Addressee::List list = idgl->getAddressList(); if ( list.count() > 0 ) { KABC::Addressee::List listNew; KABC::Addressee::List listExisting; KABC::Addressee::List::Iterator it; KABC::AddressBook::Iterator iter; for ( it = list.begin(); it != list.end(); ++it ) { if ( mAddressBook->findByUid((*it).uid() ).isEmpty()) listNew.append( (*it) ); else listExisting.append( (*it) ); } if ( listExisting.count() > 0 ) KMessageBox::information( this, i18n("%1 contacts not added to addressbook\nbecause they were already in the addressbook!").arg( listExisting.count() )); if ( listNew.count() > 0 ) { pasteWithNewUid = false; pasteContacts( listNew ); pasteWithNewUid = true; } } delete idgl; #endif } void KABCore::importVCard( const QString &vCard, bool showPreview ) { mXXPortManager->importVCard( vCard, showPreview ); } //US added a second method without defaultparameter void KABCore::editContact2() { editContact( QString::null ); } void KABCore::editContact( const QString &uid ) { if ( mExtensionManager->isQuickEditVisible() ) return; // First, locate the contact entry QString localUID = uid; if ( localUID.isNull() ) { QStringList uidList = mViewManager->selectedUids(); if ( uidList.count() > 0 ) localUID = *( uidList.at( 0 ) ); } KABC::Addressee addr = mAddressBook->findByUid( localUID ); if ( !addr.isEmpty() ) { mEditorDialog->setAddressee( addr ); KApplication::execDialog ( mEditorDialog ); } } /** Shows or edits the detail view for the given uid. If the uid is QString::null, the method will try to find a selected addressee in the view. */ void KABCore::executeContact( const QString &uid /*US = QString::null*/ ) { if ( mMultipleViewsAtOnce ) { editContact( uid ); } else { setDetailsVisible( true ); mActionDetails->setChecked(true); } } void KABCore::save() { if (syncManager->blockSave()) return; if ( !mModified ) return; syncManager->setBlockSave(true); QString text = i18n( "There was an error while attempting to save\n the " "address book. Please check that some \nother application is " "not using it. " ); message(i18n("Saving ... please wait! "), false); //qApp->processEvents(); #ifndef KAB_EMBEDDED KABC::StdAddressBook *b = dynamic_cast<KABC::StdAddressBook*>( mAddressBook ); if ( !b || !b->save() ) { KMessageBox::error( this, text, i18n( "Unable to Save" ) ); } #else //KAB_EMBEDDED KABC::StdAddressBook *b = (KABC::StdAddressBook*)( mAddressBook ); if ( !b || !b->save() ) { QMessageBox::critical( this, i18n( "Unable to Save" ), text, i18n("Ok")); } #endif //KAB_EMBEDDED message(i18n("Addressbook saved!")); setModified( false ); syncManager->setBlockSave(false); } void KABCore::undo() { UndoStack::instance()->undo(); // Refresh the view mViewManager->refreshView(); } void KABCore::redo() { RedoStack::instance()->redo(); // Refresh the view mViewManager->refreshView(); } void KABCore::setJumpButtonBarVisible( bool visible ) { if (mMultipleViewsAtOnce) { if ( visible ) mJumpButtonBar->show(); else mJumpButtonBar->hide(); } else { // show the jumpbar only if "the details are hidden" == "viewmanager are shown" if (mViewManager->isVisible()) { if ( visible ) mJumpButtonBar->show(); else mJumpButtonBar->hide(); } else { mJumpButtonBar->hide(); } } } void KABCore::setDetailsToState() { setDetailsVisible( mActionDetails->isChecked() ); } void KABCore::setDetailsToggle() { mActionDetails->setChecked( !mActionDetails->isChecked() ); setDetailsToState(); } void KABCore::setDetailsVisible( bool visible ) { if (visible && mDetails->isHidden()) { KABC::Addressee::List addrList = mViewManager->selectedAddressees(); if ( addrList.count() > 0 ) mDetails->setAddressee( addrList[ 0 ] ); } // mMultipleViewsAtOnce=false: mDetails is always visible. But we switch between // the listview and the detailview. We do that by changing the splitbar size. if (mMultipleViewsAtOnce) { if ( visible ) mDetails->show(); else mDetails->hide(); } else { if ( visible ) { mViewManager->hide(); mDetails->show(); mIncSearchWidget->setFocus(); } else { mViewManager->show(); mDetails->hide(); mViewManager->setFocusAV(); } setJumpButtonBarVisible( !visible ); @@ -1977,441 +1978,441 @@ void KABCore::initActions() // you do that through the control center !!! mActionConfigResources = new KAction( i18n( "Configure &Resources..." ), "configure_resources", 0, this, SLOT( configureResources() ), actionCollection(), "kaddressbook_configure_resources" ); #endif //KAB_EMBEDDED if ( mIsPart ) { mActionConfigKAddressbook = new KAction( i18n( "&Configure KAddressBook..." ), "configure", 0, this, SLOT( openConfigDialog() ), actionCollection(), "kaddressbook_configure" ); //US not implemented yet //mActionConfigShortcuts = new KAction( i18n( "Configure S&hortcuts..." ), "configure_shortcuts", 0, // this, SLOT( configureKeyBindings() ), actionCollection(), // "kaddressbook_configure_shortcuts" ); #ifdef KAB_EMBEDDED mActionConfigureToolbars = KStdAction::configureToolbars( this, SLOT( mMainWindow->configureToolbars() ), actionCollection() ); mActionConfigureToolbars->setEnabled( false ); #endif //KAB_EMBEDDED } else { mActionConfigKAddressbook = KStdAction::preferences( this, SLOT( openConfigDialog() ), actionCollection() ); //US not implemented yet //mActionKeyBindings = KStdAction::keyBindings( this, SLOT( configureKeyBindings() ), actionCollection() ); } mActionJumpBar = new KToggleAction( i18n( "Show Jump Bar" ), 0, 0, actionCollection(), "options_show_jump_bar" ); connect( mActionJumpBar, SIGNAL( toggled( bool ) ), SLOT( setJumpButtonBarVisible( bool ) ) ); mActionDetails = new KToggleAction( i18n( "Show Details" ), "listview", 0, actionCollection(), "options_show_details" ); connect( mActionDetails, SIGNAL( toggled( bool ) ), SLOT( setDetailsVisible( bool ) ) ); mActionBR = new KToggleAction( i18n( "Beam receive enabled" ), "beam", 0, this, SLOT( toggleBeamReceive() ), actionCollection(), "kaddressbook_beam_rec" ); // misc // only enable LDAP lookup if we can handle the protocol #ifndef KAB_EMBEDDED if ( KProtocolInfo::isKnownProtocol( KURL( "ldap://localhost" ) ) ) { new KAction( i18n( "&Lookup Addresses in Directory" ), "find", 0, this, SLOT( openLDAPDialog() ), actionCollection(), "ldap_lookup" ); } #else //KAB_EMBEDDED //qDebug("KABCore::initActions() LDAP has to be implemented"); #endif //KAB_EMBEDDED mActionWhoAmI = new KAction( i18n( "Set Who Am I" ), "personal", 0, this, SLOT( setWhoAmI() ), actionCollection(), "set_personal" ); mActionCategories = new KAction( i18n( "Set Categories" ), 0, this, SLOT( setCategories() ), actionCollection(), "edit_set_categories" ); mActionEditCategories = new KAction( i18n( "Edit Categories" ), 0, this, SLOT( editCategories() ), actionCollection(), "edit__categories" ); mActionRemoveVoice = new KAction( i18n( "Remove \"voice\"..." ), 0, this, SLOT( removeVoice() ), actionCollection(), "remove_voice" ); mActionSetFormattedName = new KAction( i18n( "Set formatted name..." ), 0, this, SLOT( setFormattedName() ), actionCollection(), "set_formatted" ); mActionManageCategories= new KAction( i18n( "Manage new categories..." ), 0, this, SLOT( manageCategories() ), actionCollection(), "remove_voice" ); mActionImportOL = new KAction( i18n( "Import from Outlook..." ), 0, this, SLOT( importFromOL() ), actionCollection(), "import_OL" ); #ifdef KAB_EMBEDDED mActionLicence = new KAction( i18n( "Licence" ), 0, this, SLOT( showLicence() ), actionCollection(), "licence_about_data" ); mActionFaq = new KAction( i18n( "Faq" ), 0, this, SLOT( faq() ), actionCollection(), "faq_about_data" ); mActionWN = new KAction( i18n( "What's New?" ), 0, this, SLOT( whatsnew() ), actionCollection(), "wn" ); mActionSyncHowto = new KAction( i18n( "Sync HowTo" ), 0, this, SLOT( synchowto() ), actionCollection(), "sync" ); mActionKdeSyncHowto = new KAction( i18n( "Kde Sync HowTo" ), 0, this, SLOT( kdesynchowto() ), actionCollection(), "kdesync" ); mActionMultiSyncHowto = new KAction( i18n( "Multi Sync HowTo" ), 0, this, SLOT( multisynchowto() ), actionCollection(), "multisync" ); mActionAboutKAddressbook = new KAction( i18n( "&About KAddressBook" ), "kaddressbook2", 0, this, SLOT( createAboutData() ), actionCollection(), "kaddressbook_about_data" ); #endif //KAB_EMBEDDED clipboardDataChanged(); connect( UndoStack::instance(), SIGNAL( changed() ), SLOT( updateActionMenu() ) ); connect( RedoStack::instance(), SIGNAL( changed() ), SLOT( updateActionMenu() ) ); } //US we need this function, to plug all actions into the correct menues. // KDE uses a XML format to plug the actions, but we work her without this overhead. void KABCore::addActionsManually() { //US qDebug("KABCore::initActions(): mIsPart %i", mIsPart); #ifdef KAB_EMBEDDED QPopupMenu *fileMenu = new QPopupMenu( this ); QPopupMenu *editMenu = new QPopupMenu( this ); QPopupMenu *helpMenu = new QPopupMenu( this ); KToolBar* tb = mMainWindow->toolBar(); #ifndef DESKTOP_VERSION if ( KABPrefs::instance()->mFullMenuBarVisible ) { #endif QMenuBar* mb = mMainWindow->menuBar(); //US setup menubar. //Disable the following block if you do not want to have a menubar. mb->insertItem( i18n("&File"), fileMenu ); mb->insertItem( i18n("&Edit"), editMenu ); mb->insertItem( i18n("&View"), viewMenu ); mb->insertItem( i18n("&Settings"), settingsMenu ); mb->insertItem( i18n("Synchronize"), syncMenu ); //mb->insertItem( i18n("&Change"), changeMenu ); mb->insertItem( i18n("&Help"), helpMenu ); mIncSearchWidget = new IncSearchWidget( tb ); // tb->insertWidget(-1, 0, mIncSearchWidget); #ifndef DESKTOP_VERSION } else { //US setup toolbar QPEMenuBar *menuBarTB = new QPEMenuBar( tb ); QPopupMenu *popupBarTB = new QPopupMenu( this ); menuBarTB->insertItem( "ME", popupBarTB); tb->insertWidget(-1, 0, menuBarTB); mIncSearchWidget = new IncSearchWidget( tb ); tb->enableMoving(false); popupBarTB->insertItem( i18n("&File"), fileMenu ); popupBarTB->insertItem( i18n("&Edit"), editMenu ); popupBarTB->insertItem( i18n("&View"), viewMenu ); popupBarTB->insertItem( i18n("&Settings"), settingsMenu ); popupBarTB->insertItem( i18n("Synchronize"), syncMenu ); mViewManager->getFilterAction()->plug ( popupBarTB); //popupBarTB->insertItem( i18n("&Change selected"), changeMenu ); popupBarTB->insertItem( i18n("&Help"), helpMenu ); if (QApplication::desktop()->width() > 320 ) { // mViewManager->getFilterAction()->plug ( tb); } } #endif // mActionQuit->plug ( mMainWindow->toolBar()); //US Now connect the actions with the menue entries. #ifdef DESKTOP_VERSION mActionPrint->plug( fileMenu ); mActionPrintDetails->plug( fileMenu ); fileMenu->insertSeparator(); #endif mActionMail->plug( fileMenu ); fileMenu->insertSeparator(); mActionNewContact->plug( fileMenu ); mActionNewContact->plug( tb ); mActionEditAddressee->plug( fileMenu ); // if ((KGlobal::getDesktopSize() > KGlobal::Small ) || // (!KABPrefs::instance()->mMultipleViewsAtOnce )) mActionEditAddressee->plug( tb ); fileMenu->insertSeparator(); mActionSave->plug( fileMenu ); fileMenu->insertItem( "&Import", ImportMenu ); fileMenu->insertItem( "&Export", ExportMenu ); fileMenu->insertItem( i18n("&Change"), changeMenu ); #ifndef DESKTOP_VERSION if ( Ir::supported() ) fileMenu->insertItem( i18n("&Beam"), beamMenu ); #endif -#if 0 +#if 0 // PENDING fix MailVCard fileMenu->insertSeparator(); mActionMailVCard->plug( fileMenu ); #endif #ifndef DESKTOP_VERSION if ( Ir::supported() ) mActionBR->plug( beamMenu ); if ( Ir::supported() ) mActionBeamVCard->plug( beamMenu ); if ( Ir::supported() ) mActionBeam->plug( beamMenu ); #endif fileMenu->insertSeparator(); mActionQuit->plug( fileMenu ); -#ifdef _WIN32_ +#ifdef _OL_IMPORT_ mActionImportOL->plug( ImportMenu ); #endif // edit menu mActionUndo->plug( editMenu ); mActionRedo->plug( editMenu ); editMenu->insertSeparator(); mActionCut->plug( editMenu ); mActionCopy->plug( editMenu ); mActionPaste->plug( editMenu ); mActionDelete->plug( editMenu ); editMenu->insertSeparator(); mActionSelectAll->plug( editMenu ); mActionSetFormattedName->plug( changeMenu ); mActionRemoveVoice->plug( changeMenu ); // settings menu //US special menuentry to configure the addressbook resources. On KDE // you do that through the control center !!! mActionConfigResources->plug( settingsMenu ); settingsMenu->insertSeparator(); mActionConfigKAddressbook->plug( settingsMenu ); if ( mIsPart ) { //US not implemented yet //mActionConfigShortcuts->plug( settingsMenu ); //mActionConfigureToolbars->plug( settingsMenu ); } else { //US not implemented yet //mActionKeyBindings->plug( settingsMenu ); } settingsMenu->insertSeparator(); mActionJumpBar->plug( settingsMenu ); mActionDetails->plug( settingsMenu ); //if (!KABPrefs::instance()->mMultipleViewsAtOnce || KGlobal::getDesktopSize() == KGlobal::Desktop ) mActionDetails->plug( tb ); settingsMenu->insertSeparator(); #ifndef DESKTOP_VERSION if ( Ir::supported() ) mActionBR->plug(settingsMenu ); -#endif settingsMenu->insertSeparator(); +#endif mActionWhoAmI->plug( settingsMenu ); mActionEditCategories->plug( settingsMenu ); mActionEditCategories->plug( changeMenu ); mActionCategories->plug( changeMenu ); mActionManageCategories->plug( changeMenu ); mActionCategories->plug( settingsMenu ); mActionManageCategories->plug( settingsMenu ); mActionWN->plug( helpMenu ); mActionSyncHowto->plug( helpMenu ); mActionKdeSyncHowto->plug( helpMenu ); mActionMultiSyncHowto->plug( helpMenu ); mActionFaq->plug( helpMenu ); mActionLicence->plug( helpMenu ); mActionAboutKAddressbook->plug( helpMenu ); if (KGlobal::getDesktopSize() > KGlobal::Small ) { mActionSave->plug( tb ); mViewManager->getFilterAction()->plug ( tb); //LR hide filteraction on started in 480x640 if (QApplication::desktop()->width() == 480 ) { mViewManager->getFilterAction()->setComboWidth( 0 ); } mActionUndo->plug( tb ); mActionDelete->plug( tb ); mActionRedo->plug( tb ); } else { mActionSave->plug( tb ); tb->enableMoving(false); } //mActionQuit->plug ( tb ); // tb->insertWidget(-1, 0, mIncSearchWidget, 6); //US link the searchwidget first to this. // The real linkage to the toolbar happens later. //US mIncSearchWidget->reparent(tb, 0, QPoint(50,0), TRUE); //US tb->insertItem( mIncSearchWidget ); /*US mIncSearchWidget = new IncSearchWidget( tb ); connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), SLOT( incrementalSearch( const QString& ) ) ); mJumpButtonBar = new JumpButtonBar( this, this ); //US topLayout->addWidget( mJumpButtonBar ); this->layout()->add( mJumpButtonBar ); */ #endif //KAB_EMBEDDED mActionExport2phone->plug( ExportMenu ); connect ( syncMenu, SIGNAL( activated ( int ) ), syncManager, SLOT (slotSyncMenu( int ) ) ); syncManager->fillSyncMenu(); } void KABCore::showLicence() { KApplication::showLicence(); } void KABCore::manageCategories( ) { KABCatPrefs* cp = new KABCatPrefs(); cp->show(); int w =cp->sizeHint().width() ; int h = cp->sizeHint().height() ; int dw = QApplication::desktop()->width(); int dh = QApplication::desktop()->height(); cp->setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); if ( !cp->exec() ) { delete cp; return; } int count = 0; int cc = 0; message( i18n("Please wait, processing categories...")); if ( cp->addCat() ) { KABC::AddressBook::Iterator it; QStringList catList = KABPrefs::instance()->mCustomCategories; for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { ++cc; if ( cc %10 == 0) message(i18n("Processing contact #%1").arg(cc)); QStringList catIncList = (*it).categories(); int i; for( i = 0; i< catIncList.count(); ++i ) { if ( !catList.contains (catIncList[i])) { catList.append( catIncList[i] ); //qDebug("add cat %s ", catIncList[i].latin1()); ++count; } } } catList.sort(); KABPrefs::instance()->mCustomCategories = catList; KABPrefs::instance()->writeConfig(); message(QString::number( count )+ i18n(" categories added to list! ")); } else { QStringList catList = KABPrefs::instance()->mCustomCategories; QStringList catIncList; QStringList newCatList; KABC::AddressBook::Iterator it; for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { ++cc; if ( cc %10 == 0) message(i18n("Processing contact #%1").arg(cc)); QStringList catIncList = (*it).categories(); int i; if ( catIncList.count() ) { newCatList.clear(); for( i = 0; i< catIncList.count(); ++i ) { if ( catList.contains (catIncList[i])) { newCatList.append( catIncList[i] ); } } newCatList.sort(); (*it).setCategories( newCatList ); mAddressBook->insertAddressee( (*it) ); } } setModified( true ); mViewManager->refreshView(); message( i18n("Removing categories done!")); } delete cp; } void KABCore::removeVoice() { if ( KMessageBox::questionYesNo( this, i18n("After importing, phone numbers\nmay have two or more types.\n(E.g. work+voice)\nThese numbers are shown as \"other\".\nClick Yes to remove the voice type\nfrom numbers with more than one type.\n\nRemove voice type?") ) == KMessageBox::No ) return; XXPortSelectDialog dlg( this, false, this ); if ( !dlg.exec() ) return; mAddressBook->setUntagged(); dlg.tagSelected(); message(i18n("Removing voice..."), false ); KABC::AddressBook::Iterator it; for ( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { if ( (*it).tagged() ) { (*it).removeVoice(); } } message(i18n("Refreshing view...") ); qApp->processEvents(); mViewManager->refreshView( "" ); Addressee add; mDetails->setAddressee( add ); message(i18n("Remove voice completed!") ); } void KABCore::setFormattedName() { KABFormatPrefs setpref; if ( !setpref.exec() ) { return; } XXPortSelectDialog dlg( this, false, this ); if ( !dlg.exec() ) return; mAddressBook->setUntagged(); dlg.tagSelected(); int count = 0; KABC::AddressBook::Iterator it; for ( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { if ( (*it).tagged() ) { ++count; if ( count %10 == 0 ) message(i18n("Changing contact #%1").arg( count ) ); qApp->processEvents(); QString fName; if ( setpref.simple->isChecked() ) fName = NameEditDialog::formattedName( (*it), NameEditDialog::SimpleName ); else if ( setpref.full->isChecked() ) fName = NameEditDialog::formattedName( (*it), NameEditDialog::FullName ); else if ( setpref.reverse->isChecked() ) fName = NameEditDialog::formattedName( (*it), NameEditDialog::ReverseName ); else fName = (*it).organization(); if ( setpref.setCompany->isChecked() ) if ( fName.isEmpty() || fName =="," ) fName = (*it).organization(); (*it).setFormattedName( fName ); } } message(i18n("Refreshing view...") ); diff --git a/kaddressbook/kaddressbook.pro b/kaddressbook/kaddressbook.pro index fbbc026..e73de06 100644 --- a/kaddressbook/kaddressbook.pro +++ b/kaddressbook/kaddressbook.pro @@ -1,184 +1,177 @@ TEMPLATE = app CONFIG = qt warn_on TARGET = kapi DESTDIR= ../bin include( ../variables.pri ) INCLUDEPATH += . ./details ./features ./xxport ../libkdepim ../microkde ../microkde/kdecore ../microkde/kutils ../microkde/kio/kfile ../microkde/kio/kio ../microkde/kdeui ../microkde/kresources ../kabc ../ interfaces DEFINES += KAB_EMBEDDED KAB_NOSPLITTER DESKTOP_VERSION unix : { LIBS += ../bin/libmicrokdepim.so LIBS += ../bin/libmicrokde.so LIBS += ../bin/libmicrokabc.so LIBS += ../bin/libmicrokcal.so #LIBS += -lldap OBJECTS_DIR = obj/unix MOC_DIR = moc/unix } win32: { RC_FILE = winicons.rc DEFINES += _WIN32_ LIBS += ../bin/microkdepim.lib LIBS += ../bin/microkcal.lib LIBS += ../bin/microkde.lib LIBS += ../bin/microkabc.lib QMAKE_LINK += /NODEFAULTLIB:LIBC OBJECTS_DIR = obj/win MOC_DIR = moc/win +#olimport section +#blabla: { + LIBS += mfc71u.lib +DEFINES += _OL_IMPORT_ +HEADERS = ../outport/msoutl9.h \ + kaimportoldialog.h +SOURCES = ../outport/msoutl9.cpp \ + kaimportoldialog.cpp +#} +#olimport section end } - - - - - - - INTERFACES = \ # filteredit_base.ui \ # kofilterview_base.ui \ -HEADERS = \ +HEADERS += \ features/mergewidget.h \ features/distributionlistwidget.h \ kcmconfigs/addresseewidget.h \ kcmconfigs/extensionconfigdialog.h \ kcmconfigs/kcmkabconfig.h \ kcmconfigs/kabconfigwidget.h \ addresseeeditordialog.h \ addresseeeditorwidget.h \ addresseditwidget.h \ addresseeconfig.h \ addresseeutil.h \ emaileditwidget.h \ filtereditdialog.h \ kaddressbookmain.h \ kabprefs.h \ kabcore.h \ viewmanager.h \ extensionmanager.h \ extensionwidget.h \ kaddressbookview.h \ geowidget.h \ imagewidget.h \ incsearchwidget.h \ jumpbuttonbar.h \ phoneeditwidget.h \ secrecywidget.h \ keywidget.h \ nameeditdialog.h \ filter.h \ addviewdialog.h \ configurewidget.h \ viewconfigurewidget.h \ viewconfigurefieldspage.h \ viewconfigurefilterpage.h \ typecombo.h \ undo.h \ undocmds.h \ xxportmanager.h \ xxportobject.h \ xxportselectdialog.h \ details/detailsviewcontainer.h \ details/look_basic.h \ details/look_html.h \ views/kaddressbookiconview.h \ views/kaddressbooktableview.h \ views/kaddressbookcardview.h \ views/configuretableviewdialog.h \ views/configurecardviewdialog.h \ views/cardview.h \ views/colorlistbox.h \ views/contactlistview.h \ xxport/vcard_xxport.h \ xxport/kde2_xxport.h \ xxport/csv_xxport.h \ xxport/csvimportdialog.h \ xxport/opie_xxport.h \ xxport/qtopia_xxport.h \ xxport/sharpdtm_xxport.h \ #details/look_details.h \ #mainwindoiw.h \ # alarmclient.h \ # calendarview.h \ # customlistviewitem.h \ # datenavigator.h -SOURCES = \ +SOURCES += \ addresseeeditordialog.cpp \ addresseeeditorwidget.cpp \ addresseditwidget.cpp \ addresseeconfig.cpp \ addresseeutil.cpp \ extensionmanager.cpp \ features/mergewidget.cpp \ features/distributionlistwidget.cpp \ kcmconfigs/addresseewidget.cpp \ kcmconfigs/extensionconfigdialog.cpp \ kcmconfigs/kcmkabconfig.cpp \ kcmconfigs/kabconfigwidget.cpp \ emaileditwidget.cpp \ filtereditdialog.cpp \ mainembedded.cpp \ kaddressbookmain.cpp \ kabcore.cpp \ kabprefs.cpp \ viewmanager.cpp \ kaddressbookview.cpp \ extensionwidget.cpp \ geowidget.cpp \ imagewidget.cpp \ incsearchwidget.cpp \ jumpbuttonbar.cpp \ phoneeditwidget.cpp \ secrecywidget.cpp \ keywidget.cpp \ nameeditdialog.cpp \ filter.cpp \ addviewdialog.cpp \ configurewidget.cpp \ viewconfigurewidget.cpp \ viewconfigurefieldspage.cpp \ viewconfigurefilterpage.cpp \ undo.cpp \ undocmds.cpp \ xxportmanager.cpp \ xxportobject.cpp \ xxportselectdialog.cpp \ details/detailsviewcontainer.cpp \ details/look_basic.cpp \ details/look_html.cpp \ views/kaddressbookiconview.cpp \ views/kaddressbooktableview.cpp \ views/kaddressbookcardview.cpp \ views/configuretableviewdialog.cpp \ views/configurecardviewdialog.cpp \ views/cardview.cpp \ views/contactlistview.cpp \ views/colorlistbox.cpp \ xxport/vcard_xxport.cpp \ xxport/kde2_xxport.cpp \ xxport/csv_xxport.cpp \ xxport/csvimportdialog.cpp \ xxport/opie_xxport.cpp \ xxport/qtopia_xxport.cpp \ xxport/sharpdtm_xxport.cpp \ #details/look_details.cpp \ #mainwindow.cpp \ # calendarview.cpp \ # timespanview.cpp - - -win32: { -HEADERS += ../outport/msoutl9.h \ - kaimportoldialog.h - -SOURCES += ../outport/msoutl9.cpp \ - kaimportoldialog.cpp -} - diff --git a/kaddressbook/mainembedded.cpp b/kaddressbook/mainembedded.cpp index 1e03dba..d9968f3 100644 --- a/kaddressbook/mainembedded.cpp +++ b/kaddressbook/mainembedded.cpp @@ -1,100 +1,102 @@ #ifndef DESKTOP_VERSION #include <qpe/qpeapplication.h> #include <qcopchannel_qws.h> #include <stdlib.h> #else #include <qapplication.h> #include <qwindowsstyle.h> #include <qplatinumstyle.h> #include <qmainwindow.h> +#include <qmessagebox.h> +#include <stdlib.h> #endif #include <qtextcodec.h> #include <kstandarddirs.h> #include <qregexp.h> #include <kglobal.h> #include <stdio.h> #include <qdir.h> #include "kabprefs.h" #include "kaddressbookmain.h" #include "externalapphandler.h" #include <libkdepim/kpimglobalprefs.h> void dumpMissing(); int main( int argc, char **argv ) { #ifndef DESKTOP_VERSION QPEApplication a( argc, argv ); a.setKeepRunning (); #else QApplication a( argc, argv ); QApplication::setStyle( new QPlatinumStyle ()); - QString hdir = QDir::homeDirPath(); - // there is a bug when creating dirs for WIN 98 - // it is difficult to fix, because we have no WIN 98 runnung - // such that we try it to create the dirs at startup here - if ( hdir == "C:\\" ) { // win 98 or ME - QDir app_dir; - if ( !app_dir.exists("C:\\kdepim") ) - app_dir.mkdir ("C:\\kdepim"); - if ( !app_dir.exists("C:\\kdepim\\apps") ) - app_dir.mkdir ("C:\\kdepim\\apps"); - if ( !app_dir.exists("C:\\kdepim\\config") ) - app_dir.mkdir ("C:\\kdepim\\config"); - if ( !app_dir.exists("C:\\kdepim\\apps\\kaddressbook") ) - app_dir.mkdir ("C:\\kdepim\\apps\\kaddressbook"); +#ifdef _WIN32_ + QString hdir ( getenv( "HOME") ); + if ( hdir.isEmpty() ) { + QString hd ("C:/" ); + //QMessageBox::information(0,"hh",QDir::homeDirPath()+" xx" +hd ); + if ( QDir::homeDirPath().lower() == hd.lower() ) { + _putenv( "HOME=C:"); + //QMessageBox::information(0,"hh",QString ( getenv( "HOME") ) ); + } + } else { + QDir app_dir; + if ( !app_dir.exists(hdir) ) + app_dir.mkdir (hdir); } #endif +#endif bool exitHelp = false; if ( argc > 1 ) { QString command = argv[1]; if ( command == "-help" ){ printf("KA/E command line commands:\n"); printf(" no command: Start KA/E in usual way\n"); printf(" -help: This output\n"); printf(" KA/E is exiting now. Bye!\n"); exitHelp = true; } } if ( ! exitHelp ) { KGlobal::setAppName( "kaddressbook" ); #ifndef DESKTOP_VERSION if ( QApplication::desktop()->width() > 320 ) KGlobal::iconLoader()->setIconPath(QString(getenv("QPEDIR"))+"/pics/kdepim/kaddressbook/icons22/"); else KGlobal::iconLoader()->setIconPath(QString(getenv("QPEDIR"))+"/pics/kdepim/kaddressbook/icons16/"); #else QString fileName ; fileName = qApp->applicationDirPath () + "/kdepim/kaddressbook/icons22/"; KGlobal::iconLoader()->setIconPath(QDir::convertSeparators(fileName)); QApplication::addLibraryPath ( qApp->applicationDirPath () ); #endif KStandardDirs::setAppDir( QDir::convertSeparators(locateLocal("data", "kaddressbook"))); // init language KPimGlobalPrefs::instance()->setGlobalConfig(); KAddressBookMain m ; //US MainWindow m; #ifndef DESKTOP_VERSION QObject::connect(&a, SIGNAL (appMessage ( const QCString &, const QByteArray & )), ExternalAppHandler::instance(), SLOT (appMessage ( const QCString &, const QByteArray & ))); #endif #ifndef DESKTOP_VERSION a.showMainWidget( &m ); #else a.setMainWidget( &m ); m.resize (640, 480 ); m.show(); #endif a.exec(); dumpMissing(); KPimGlobalPrefs::instance()->writeConfig(); } qDebug("KA: Bye! "); } |