-rw-r--r-- | kaddressbook/kabcore.cpp | 2 | ||||
-rw-r--r-- | kaddressbook/views/cardview.cpp | 10 |
2 files changed, 6 insertions, 6 deletions
diff --git a/kaddressbook/kabcore.cpp b/kaddressbook/kabcore.cpp index d651224..c339244 100644 --- a/kaddressbook/kabcore.cpp +++ b/kaddressbook/kabcore.cpp @@ -1210,1887 +1210,1887 @@ void KABCore::importFromOL() } 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 addressbook ... ")); #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 ); } } void KABCore::extensionChanged( int id ) { //change the details view only for non desktop systems #ifndef DESKTOP_VERSION if (id == 0) { //the user disabled the extension. if (mMultipleViewsAtOnce) { // enable detailsview again setDetailsVisible( true ); mActionDetails->setChecked( true ); } else { //go back to the listview setDetailsVisible( false ); mActionDetails->setChecked( false ); mActionDetails->setEnabled(true); } } else { //the user enabled the extension. setDetailsVisible( false ); mActionDetails->setChecked( false ); if (!mMultipleViewsAtOnce) { mActionDetails->setEnabled(false); } mExtensionManager->setSelectionChanged(); } #endif// DESKTOP_VERSION } void KABCore::extensionModified( const KABC::Addressee::List &list ) { if ( list.count() != 0 ) { KABC::Addressee::List::ConstIterator it; for ( it = list.begin(); it != list.end(); ++it ) mAddressBook->insertAddressee( *it ); if ( list.count() > 1 ) setModified(); else setModifiedWOrefresh(); } if ( list.count() == 0 ) mViewManager->refreshView(); else mViewManager->refreshView( list[ 0 ].uid() ); } QString KABCore::getNameByPhone( const QString &phone ) { #ifndef KAB_EMBEDDED QRegExp r( "[/*/-/ ]" ); QString localPhone( phone ); bool found = false; QString ownerName = ""; KABC::AddressBook::Iterator iter; KABC::PhoneNumber::List::Iterator phoneIter; KABC::PhoneNumber::List phoneList; for ( iter = mAddressBook->begin(); !found && ( iter != mAddressBook->end() ); ++iter ) { phoneList = (*iter).phoneNumbers(); for ( phoneIter = phoneList.begin(); !found && ( phoneIter != phoneList.end() ); ++phoneIter) { // Get rid of separator chars so just the numbers are compared. if ( (*phoneIter).number().replace( r, "" ) == localPhone.replace( r, "" ) ) { ownerName = (*iter).formattedName(); found = true; } } } return ownerName; #else //KAB_EMBEDDED qDebug("KABCore::getNameByPhone finsih method"); return ""; #endif //KAB_EMBEDDED } void KABCore::openConfigDialog() { KCMultiDialog* ConfigureDialog = new KCMultiDialog( "PIM", this ,"kabconfigdialog", true ); KCMKabConfig* kabcfg = new KCMKabConfig( ConfigureDialog->getNewVBoxPage(i18n( "Addressbook")) , "KCMKabConfig" ); ConfigureDialog->addModule(kabcfg ); KCMKdePimConfig* kdelibcfg = new KCMKdePimConfig( ConfigureDialog->getNewVBoxPage(i18n( "Global")) , "KCMKdeLibConfig" ); ConfigureDialog->addModule(kdelibcfg ); connect( ConfigureDialog, SIGNAL( applyClicked() ), this, SLOT( configurationChanged() ) ); connect( ConfigureDialog, SIGNAL( okClicked() ), this, SLOT( configurationChanged() ) ); saveSettings(); #ifndef DESKTOP_VERSION ConfigureDialog->showMaximized(); #endif if ( ConfigureDialog->exec() ) KMessageBox::information( this, i18n("Some changes are only\neffective after a restart!\n") ); delete ConfigureDialog; } void KABCore::openLDAPDialog() { #ifndef KAB_EMBEDDED if ( !mLdapSearchDialog ) { mLdapSearchDialog = new LDAPSearchDialog( mAddressBook, this ); connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ), mViewManager, SLOT( refreshView() ) ); connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ), this, SLOT( setModified() ) ); } else mLdapSearchDialog->restoreSettings(); if ( mLdapSearchDialog->isOK() ) mLdapSearchDialog->exec(); #else //KAB_EMBEDDED qDebug("KABCore::openLDAPDialog() finsih method"); #endif //KAB_EMBEDDED } void KABCore::print() { #ifndef KAB_EMBEDDED KPrinter printer; if ( !printer.setup( this ) ) return; KABPrinting::PrintingWizard wizard( &printer, mAddressBook, mViewManager->selectedUids(), this ); wizard.exec(); #else //KAB_EMBEDDED qDebug("KABCore::print() finsih method"); #endif //KAB_EMBEDDED } void KABCore::addGUIClient( KXMLGUIClient *client ) { if ( mGUIClient ) mGUIClient->insertChildClient( client ); else KMessageBox::error( this, "no KXMLGUICLient"); } void KABCore::configurationChanged() { mExtensionManager->reconfigure(); } void KABCore::addressBookChanged() { /*US QDictIterator<AddresseeEditorDialog> it( mEditorDict ); while ( it.current() ) { if ( it.current()->dirty() ) { QString text = i18n( "Data has been changed externally. Unsaved " "changes will be lost." ); KMessageBox::information( this, text ); } it.current()->setAddressee( mAddressBook->findByUid( it.currentKey() ) ); ++it; } */ if (mEditorDialog) { if (mEditorDialog->dirty()) { QString text = i18n( "Data has been changed externally. Unsaved " "changes will be lost." ); KMessageBox::information( this, text ); } QString currentuid = mEditorDialog->addressee().uid(); mEditorDialog->setAddressee( mAddressBook->findByUid( currentuid ) ); } mViewManager->refreshView(); // mDetails->refreshView(); } AddresseeEditorDialog *KABCore::createAddresseeEditorDialog( QWidget *parent, const char *name ) { if ( mEditorDialog == 0 ) { mEditorDialog = new AddresseeEditorDialog( this, parent, name ? name : "editorDialog" ); connect( mEditorDialog, SIGNAL( contactModified( const KABC::Addressee& ) ), SLOT( contactModified( const KABC::Addressee& ) ) ); //connect( mEditorDialog, SIGNAL( editorDestroyed( const QString& ) ), // SLOT( slotEditorDestroyed( const QString& ) ) ; } return mEditorDialog; } void KABCore::slotEditorDestroyed( const QString &uid ) { //mEditorDict.remove( uid ); } void KABCore::initGUI() { #ifndef KAB_EMBEDDED QHBoxLayout *topLayout = new QHBoxLayout( this ); topLayout->setSpacing( KDialogBase::spacingHint() ); mExtensionBarSplitter = new QSplitter( this ); mExtensionBarSplitter->setOrientation( Qt::Vertical ); mDetailsSplitter = new QSplitter( mExtensionBarSplitter ); QVBox *viewSpace = new QVBox( mDetailsSplitter ); mIncSearchWidget = new IncSearchWidget( viewSpace ); connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), SLOT( incrementalSearch( const QString& ) ) ); mViewManager = new ViewManager( this, viewSpace ); viewSpace->setStretchFactor( mViewManager, 1 ); mDetails = new ViewContainer( mDetailsSplitter ); mJumpButtonBar = new JumpButtonBar( this, this ); mExtensionManager = new ExtensionManager( this, mExtensionBarSplitter ); topLayout->addWidget( mExtensionBarSplitter ); topLayout->setStretchFactor( mExtensionBarSplitter, 100 ); topLayout->addWidget( mJumpButtonBar ); topLayout->setStretchFactor( mJumpButtonBar, 1 ); mXXPortManager = new XXPortManager( this, this ); #else //KAB_EMBEDDED //US initialize viewMenu before settingup viewmanager. // Viewmanager needs this menu to plugin submenues. viewMenu = new QPopupMenu( this ); settingsMenu = new QPopupMenu( this ); //filterMenu = new QPopupMenu( this ); ImportMenu = new QPopupMenu( this ); ExportMenu = new QPopupMenu( this ); syncMenu = new QPopupMenu( this ); changeMenu= new QPopupMenu( this ); //US since we have no splitter for the embedded system, setup // a layout with two frames. One left and one right. QBoxLayout *topLayout; // = new QHBoxLayout( this ); // QBoxLayout *topLayout = (QBoxLayout*)layout(); // QWidget *mainBox = new QWidget( this ); // QBoxLayout * mainBoxLayout = new QHBoxLayout(mainBox); #ifdef DESKTOP_VERSION topLayout = new QHBoxLayout( this ); mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Horizontal, this); mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Right ); topLayout->addWidget(mMiniSplitter ); mExtensionBarSplitter = new KDGanttMinimizeSplitter( Qt::Vertical,mMiniSplitter ); mExtensionBarSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Down ); mViewManager = new ViewManager( this, mExtensionBarSplitter ); mDetails = new ViewContainer( mMiniSplitter ); mExtensionManager = new ExtensionManager( this, mExtensionBarSplitter ); #else if ( QApplication::desktop()->width() > 480 ) { topLayout = new QHBoxLayout( this ); mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Horizontal, this); mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Right ); } else { topLayout = new QHBoxLayout( this ); mMiniSplitter = new KDGanttMinimizeSplitter( Qt::Vertical, this); mMiniSplitter->setMinimizeDirection ( KDGanttMinimizeSplitter::Down ); } topLayout->addWidget(mMiniSplitter ); mViewManager = new ViewManager( this, mMiniSplitter ); mDetails = new ViewContainer( mMiniSplitter ); mExtensionManager = new ExtensionManager( this, mMiniSplitter ); #endif //eh->hide(); // topLayout->addWidget(mExtensionManager ); /*US #ifndef KAB_NOSPLITTER QHBoxLayout *topLayout = new QHBoxLayout( this ); //US topLayout->setSpacing( KDialogBase::spacingHint() ); topLayout->setSpacing( 10 ); mDetailsSplitter = new QSplitter( this ); QVBox *viewSpace = new QVBox( mDetailsSplitter ); mViewManager = new ViewManager( this, viewSpace ); viewSpace->setStretchFactor( mViewManager, 1 ); mDetails = new ViewContainer( mDetailsSplitter ); topLayout->addWidget( mDetailsSplitter ); topLayout->setStretchFactor( mDetailsSplitter, 100 ); #else //KAB_NOSPLITTER QHBoxLayout *topLayout = new QHBoxLayout( this ); //US topLayout->setSpacing( KDialogBase::spacingHint() ); topLayout->setSpacing( 10 ); // mDetailsSplitter = new QSplitter( this ); QVBox *viewSpace = new QVBox( this ); mViewManager = new ViewManager( this, viewSpace ); viewSpace->setStretchFactor( mViewManager, 1 ); mDetails = new ViewContainer( this ); topLayout->addWidget( viewSpace ); // topLayout->setStretchFactor( mDetailsSplitter, 100 ); topLayout->addWidget( mDetails ); #endif //KAB_NOSPLITTER */ syncManager = new KSyncManager((QWidget*)this, (KSyncInterface*)this, KSyncManager::KAPI, KABPrefs::instance(), syncMenu); syncManager->setBlockSave(false); connect(syncManager , SIGNAL( request_file() ), this, SLOT( syncFileRequest() ) ); connect(syncManager , SIGNAL( getFile( bool )), this, SLOT(getFile( bool ) ) ); syncManager->setDefaultFileName( sentSyncFile()); //connect(syncManager , SIGNAL( ), this, SLOT( ) ); #endif //KAB_EMBEDDED initActions(); #ifdef KAB_EMBEDDED addActionsManually(); //US make sure the export and import menues are initialized before creating the xxPortManager. mXXPortManager = new XXPortManager( this, this ); // LR mIncSearchWidget = new IncSearchWidget( mMainWindow->getIconToolBar() ); //mMainWindow->toolBar()->insertWidget(-1, 4, mIncSearchWidget); // mActionQuit->plug ( mMainWindow->toolBar()); //mIncSearchWidget = new IncSearchWidget( mMainWindow->toolBar() ); //mMainWindow->toolBar()->insertWidget(-1, 0, mIncSearchWidget); // mIncSearchWidget->hide(); connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ), SLOT( incrementalSearch( const QString& ) ) ); connect( mIncSearchWidget, SIGNAL( scrollUP() ),mViewManager, SLOT( scrollUP() ) ); connect( mIncSearchWidget, SIGNAL( scrollDOWN() ),mViewManager, SLOT( scrollDOWN() ) ); mJumpButtonBar = new JumpButtonBar( this, this ); topLayout->addWidget( mJumpButtonBar ); //US topLayout->setStretchFactor( mJumpButtonBar, 10 ); // mMainWindow->getIconToolBar()->raise(); #endif //KAB_EMBEDDED } void KABCore::initActions() { //US qDebug("KABCore::initActions(): mIsPart %i", mIsPart); #ifndef KAB_EMBEDDED connect( QApplication::clipboard(), SIGNAL( dataChanged() ), SLOT( clipboardDataChanged() ) ); #endif //KAB_EMBEDDED // file menu if ( mIsPart ) { mActionMail = new KAction( i18n( "&Mail" ), "mail_generic", 0, this, SLOT( sendMail() ), actionCollection(), "kaddressbook_mail" ); mActionPrint = new KAction( i18n( "&Print" ), "fileprint", CTRL + Key_P, this, SLOT( print() ), actionCollection(), "kaddressbook_print" ); } else { mActionMail = KStdAction::mail( this, SLOT( sendMail() ), actionCollection() ); mActionPrint = KStdAction::print( this, SLOT( print() ), actionCollection() ); } mActionSave = new KAction( i18n( "&Save" ), "filesave", CTRL+Key_S, this, SLOT( save() ), actionCollection(), "file_sync" ); mActionNewContact = new KAction( i18n( "&New Contact..." ), "filenew", CTRL+Key_N, this, SLOT( newContact() ), actionCollection(), "file_new_contact" ); mActionMailVCard = new KAction(i18n("Mail &vCard..."), "mail_post_to", 0, this, SLOT( mailVCard() ), actionCollection(), "file_mail_vcard"); mActionExport2phone = new KAction( i18n( "Selected to phone" ), "ex2phone", 0, this, SLOT( export2phone() ), actionCollection(), "kaddressbook_ex2phone" ); mActionBeamVCard = 0; mActionBeam = 0; #ifndef DESKTOP_VERSION if ( Ir::supported() ) { mActionBeamVCard = new KAction( i18n( "Beam selected v&Card(s)" ), "beam", 0, this, SLOT( beamVCard() ), actionCollection(), "kaddressbook_beam_vcard" ); mActionBeam = new KAction( i18n( "&Beam personal vCard" ), "beam", 0, this, SLOT( beamMySelf() ), actionCollection(), "kaddressbook_beam_myself" ); } #endif mActionEditAddressee = new KAction( i18n( "&Edit Contact..." ), "edit", 0, this, SLOT( editContact2() ), actionCollection(), "file_properties" ); #ifdef KAB_EMBEDDED // mActionQuit = KStdAction::quit( mMainWindow, SLOT( exit() ), actionCollection() ); mActionQuit = new KAction( i18n( "&Exit" ), "exit", 0, mMainWindow, SLOT( exit() ), actionCollection(), "quit" ); #endif //KAB_EMBEDDED // edit menu if ( mIsPart ) { mActionCopy = new KAction( i18n( "&Copy" ), "editcopy", CTRL + Key_C, this, SLOT( copyContacts() ), actionCollection(), "kaddressbook_copy" ); mActionCut = new KAction( i18n( "Cu&t" ), "editcut", CTRL + Key_X, this, SLOT( cutContacts() ), actionCollection(), "kaddressbook_cut" ); mActionPaste = new KAction( i18n( "&Paste" ), "editpaste", CTRL + Key_V, this, SLOT( pasteContacts() ), actionCollection(), "kaddressbook_paste" ); mActionSelectAll = new KAction( i18n( "Select &All" ), CTRL + Key_A, this, SLOT( selectAllContacts() ), actionCollection(), "kaddressbook_select_all" ); mActionUndo = new KAction( i18n( "&Undo" ), "undo", CTRL + Key_Z, this, SLOT( undo() ), actionCollection(), "kaddressbook_undo" ); mActionRedo = new KAction( i18n( "Re&do" ), "redo", CTRL + SHIFT + Key_Z, this, SLOT( redo() ), actionCollection(), "kaddressbook_redo" ); } else { mActionCopy = KStdAction::copy( this, SLOT( copyContacts() ), actionCollection() ); mActionCut = KStdAction::cut( this, SLOT( cutContacts() ), actionCollection() ); mActionPaste = KStdAction::paste( this, SLOT( pasteContacts() ), actionCollection() ); mActionSelectAll = KStdAction::selectAll( this, SLOT( selectAllContacts() ), actionCollection() ); mActionUndo = KStdAction::undo( this, SLOT( undo() ), actionCollection() ); mActionRedo = KStdAction::redo( this, SLOT( redo() ), actionCollection() ); } mActionDelete = new KAction( i18n( "&Delete Contact" ), "editdelete", Key_Delete, this, SLOT( deleteContacts() ), actionCollection(), "edit_delete" ); mActionUndo->setEnabled( false ); mActionRedo->setEnabled( false ); // settings menu #ifdef KAB_EMBEDDED //US special menuentry to configure the addressbook resources. On KDE // 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" ); 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 selected"), 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. mActionPrint->plug( fileMenu ); 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->insertSeparator(); mActionMailVCard->plug( fileMenu ); #ifndef DESKTOP_VERSION if ( Ir::supported() ) mActionBeamVCard->plug( fileMenu ); if ( Ir::supported() ) mActionBeam->plug(fileMenu ); #endif fileMenu->insertSeparator(); mActionQuit->plug( fileMenu ); #ifdef _WIN32_ 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 ); 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(); mActionBR->plug(settingsMenu ); settingsMenu->insertSeparator(); mActionWhoAmI->plug( settingsMenu ); mActionEditCategories->plug( settingsMenu ); 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); if (KGlobal::getDesktopSize() == KGlobal::Desktop ) { 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; 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 ) { 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 ) { 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(); mDetails->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; KABC::Addressee::List list = mViewManager->selectedAddressees(); KABC::Addressee::List::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { if ( (*it).removeVoice() ) contactModified((*it) ); } } void KABCore::clipboardDataChanged() { if ( mReadWrite ) mActionPaste->setEnabled( !QApplication::clipboard()->text().isEmpty() ); } void KABCore::updateActionMenu() { UndoStack *undo = UndoStack::instance(); RedoStack *redo = RedoStack::instance(); if ( undo->isEmpty() ) mActionUndo->setText( i18n( "Undo" ) ); else mActionUndo->setText( i18n( "Undo %1" ).arg( undo->top()->name() ) ); mActionUndo->setEnabled( !undo->isEmpty() ); if ( !redo->top() ) mActionRedo->setText( i18n( "Redo" ) ); else mActionRedo->setText( i18n( "Redo %1" ).arg( redo->top()->name() ) ); mActionRedo->setEnabled( !redo->isEmpty() ); } void KABCore::configureKeyBindings() { #ifndef KAB_EMBEDDED KKeyDialog::configure( actionCollection(), true ); #else //KAB_EMBEDDED qDebug("KABCore::configureKeyBindings() not implemented"); #endif //KAB_EMBEDDED } #ifdef KAB_EMBEDDED void KABCore::configureResources() { KRES::KCMKResources dlg( this, "" , 0 ); if ( !dlg.exec() ) return; KMessageBox::information( this, i18n("Please restart to get the \nchanged resources (re)loaded!\n") ); } #endif //KAB_EMBEDDED /* this method will be called through the QCop interface from Ko/Pi to select addresses * for the attendees list of an event. */ void KABCore::requestForNameEmailUidList(const QString& sourceChannel, const QString& uid) { QStringList nameList; QStringList emailList; QStringList uidList; KABC::Addressee::List list = KABC::AddresseeDialog::getAddressees(this); uint i=0; for (i=0; i < list.count(); i++) { nameList.append(list[i].realName()); emailList.append(list[i].preferredEmail()); uidList.append(list[i].uid()); } bool res = ExternalAppHandler::instance()->returnNameEmailUidListFromKAPI(sourceChannel, uid, nameList, emailList, uidList); } /* this method will be called through the QCop interface from Ko/Pi to select birthdays * to put them into the calendar. */ void KABCore::requestForBirthdayList(const QString& sourceChannel, const QString& uid) { // qDebug("KABCore::requestForBirthdayList"); QStringList birthdayList; QStringList anniversaryList; QStringList realNameList; QStringList preferredEmailList; QStringList assembledNameList; QStringList uidList; KABC::AddressBook::Iterator it; int count = 0; for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { ++count; } QProgressBar bar(count,0 ); int w = 300; if ( QApplication::desktop()->width() < 320 ) w = 220; int h = bar.sizeHint().height() ; int dw = QApplication::desktop()->width(); int dh = QApplication::desktop()->height(); bar.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h ); bar.show(); bar.setCaption (i18n("Collecting birthdays - close to abort!") ); qApp->processEvents(); QDate bday; QString anni; QString formattedbday; for( it = mAddressBook->begin(); it != mAddressBook->end(); ++it ) { if ( ! bar.isVisible() ) return; bar.setProgress( count++ ); qApp->processEvents(); bday = (*it).birthday().date(); anni = (*it).custom("KADDRESSBOOK", "X-Anniversary" ); if ( bday.isValid() || !anni.isEmpty()) { if (bday.isValid()) formattedbday = KGlobal::locale()->formatDate(bday, true, KLocale::ISODate); else formattedbday = "NOTVALID"; if (anni.isEmpty()) anni = "INVALID"; birthdayList.append(formattedbday); anniversaryList.append(anni); //should be ISODate realNameList.append((*it).realName()); preferredEmailList.append((*it).preferredEmail()); assembledNameList.append((*it).assembledName()); uidList.append((*it).uid()); //qDebug("found birthday in KA/Pi: %s,%s,%s,%s: %s, %s", (*it).realName().latin1(), (*it).preferredEmail().latin1(), (*it).assembledName().latin1(), (*it).uid().latin1(), formattedbday.latin1(), anni.latin1() ); } } bool res = ExternalAppHandler::instance()->returnBirthdayListFromKAPI(sourceChannel, uid, birthdayList, anniversaryList, realNameList, preferredEmailList, assembledNameList, uidList); } /* this method will be called through the QCop interface from other apps to show details of a contact. */ void KABCore::requestForDetails(const QString& sourceChannel, const QString& sessionuid, const QString& name, const QString& email, const QString& uid) { //qDebug("KABCore::requestForDetails %s %s %s %s %s", sourceChannel.latin1(), sessionuid.latin1(), name.latin1(), email.latin1(), uid.latin1()); QString foundUid = QString::null; if ( ! uid.isEmpty() ) { Addressee adrr = mAddressBook->findByUid( uid ); if ( !adrr.isEmpty() ) { foundUid = uid; } if ( email == "sendbacklist" ) { //qDebug("ssssssssssssssssssssssend "); QStringList nameList; QStringList emailList; QStringList uidList; nameList.append(adrr.realName()); emailList = adrr.emails(); uidList.append( adrr.preferredEmail()); bool res = ExternalAppHandler::instance()->returnNameEmailUidListFromKAPI("QPE/Application/ompi", uid, nameList, emailList, uidList); return; } } if ( email == "sendbacklist" ) return; if (foundUid.isEmpty()) { //find the uid of the person first Addressee::List namelist; Addressee::List emaillist; if (!name.isEmpty()) namelist = mAddressBook->findByName( name ); if (!email.isEmpty()) emaillist = mAddressBook->findByEmail( email ); //qDebug("count %d %d ", namelist.count(),emaillist.count() ); //check if we have a match in Namelist and Emaillist if ((namelist.count() == 0) && (emaillist.count() > 0)) { foundUid = emaillist[0].uid(); } else if ((namelist.count() > 0) && (emaillist.count() == 0)) foundUid = namelist[0].uid(); else { for (int i = 0; i < namelist.count(); i++) { for (int j = 0; j < emaillist.count(); j++) { if (namelist[i] == emaillist[j]) { foundUid = namelist[i].uid(); } } } } } else { foundUid = uid; } if (!foundUid.isEmpty()) { // raise Ka/Pi if it is in the background #ifndef DESKTOP_VERSION #ifndef KORG_NODCOP //QCopEnvelope e("QPE/Application/kapi", "raise()"); #endif #endif mMainWindow->showMaximized(); mMainWindow-> raise(); mViewManager->setSelected( "", false); mViewManager->refreshView( "" ); mViewManager->setSelected( foundUid, true ); mViewManager->refreshView( foundUid ); if ( !mMultipleViewsAtOnce ) { setDetailsVisible( true ); mActionDetails->setChecked(true); } } } void KABCore::whatsnew() { KApplication::showFile( "KDE-Pim/Pi Version Info", "kdepim/WhatsNew.txt" ); } void KABCore::synchowto() { KApplication::showFile( "KDE-Pim/Pi Synchronization HowTo", "kdepim/SyncHowto.txt" ); } void KABCore::kdesynchowto() { KApplication::showFile( "KDE-Pim/Pi Synchronization HowTo", "kdepim/Zaurus-KDE_syncHowTo.txt" ); } void KABCore::multisynchowto() { KApplication::showFile( "KDE-Pim/Pi Synchronization HowTo", "kdepim/MultiSyncHowTo.txt" ); } void KABCore::faq() { KApplication::showFile( "KA/Pi FAQ", "kdepim/kaddressbook/kapiFAQ.txt" ); } #include <libkcal/syncdefines.h> KABC::Addressee KABCore::getLastSyncAddressee() { Addressee lse; QString mCurrentSyncDevice = syncManager->getCurrentSyncDevice(); //qDebug("CurrentSyncDevice %s ",mCurrentSyncDevice .latin1() ); lse = mAddressBook->findByUid( "last-syncAddressee-"+mCurrentSyncDevice ); if (lse.isEmpty()) { qDebug("Creating new last-syncAddressee "); lse.setUid( "last-syncAddressee-"+mCurrentSyncDevice ); QString sum = ""; if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) sum = "E: "; lse.setFamilyName("!"+sum+mCurrentSyncDevice + i18n(" - sync event")); lse.setRevision( mLastAddressbookSync ); lse.setCategories( i18n("SyncEvent") ); mAddressBook->insertAddressee( lse ); } return lse; } int KABCore::takeAddressee( KABC::Addressee* local, KABC::Addressee* remote, int mode , bool full ) { //void setZaurusId(int id); // int zaurusId() const; // void setZaurusUid(int id); // int zaurusUid() const; // void setZaurusStat(int id); // int zaurusStat() const; // 0 equal // 1 take local // 2 take remote // 3 cancel QDateTime lastSync = mLastAddressbookSync; QDateTime localMod = local->revision(); QDateTime remoteMod = remote->revision(); QString mCurrentSyncDevice = syncManager->getCurrentSyncDevice(); if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { bool remCh, locCh; remCh = ( remote->getCsum(mCurrentSyncDevice) != local->getCsum(mCurrentSyncDevice) ); //qDebug("loc %s rem %s", local->getCsum(mCurrentSyncDevice).latin1(), remote->getCsum(mCurrentSyncDevice).latin1() ); locCh = ( localMod > mLastAddressbookSync ); if ( !remCh && ! locCh ) { //qDebug("both not changed "); lastSync = localMod.addDays(1); if ( mode <= SYNC_PREF_ASK ) return 0; } else { if ( locCh ) { //qDebug("loc changed %s %s", localMod.toString().latin1(), mLastAddressbookSync.toString().latin1()); lastSync = localMod.addDays( -1 ); if ( !remCh ) remoteMod =( lastSync.addDays( -1 ) ); } else { //qDebug(" not loc changed "); lastSync = localMod.addDays( 1 ); if ( remCh ) { //qDebug("rem changed "); remoteMod =( lastSync.addDays( 1 ) ); } } } full = true; if ( mode < SYNC_PREF_ASK ) mode = SYNC_PREF_ASK; } else { if ( localMod == remoteMod ) return 0; } //qDebug("%s %s --- %d %d", localMod.toString().latin1() , remoteMod.toString().latin1(), localMod.time().msec(), remoteMod.time().msec()); //qDebug("lastsync %s ", lastSync.toString().latin1() ); //full = true; //debug only if ( full ) { bool equ = ( (*local) == (*remote) ); if ( equ ) { //qDebug("equal "); if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { local->setCsum( mCurrentSyncDevice, remote->getCsum(mCurrentSyncDevice) ); } if ( mode < SYNC_PREF_FORCE_LOCAL ) return 0; }//else //debug only //qDebug("not equal %s %s ", local->summary().latin1(), remote->summary().latin1()); } int result; bool localIsNew; //qDebug("%s -- %s mLastCalendarSync %s lastsync %s --- local %s remote %s ",local->summary().latin1(), remote->summary().latin1(),mLastCalendarSync.toString().latin1() ,lastSync.toString().latin1() , local->lastModified().toString().latin1() , remote->lastModified().toString().latin1() ); if ( full && mode < SYNC_PREF_NEWEST ) mode = SYNC_PREF_ASK; switch( mode ) { case SYNC_PREF_LOCAL: if ( lastSync > remoteMod ) return 1; if ( lastSync > localMod ) return 2; return 1; break; case SYNC_PREF_REMOTE: if ( lastSync > remoteMod ) return 1; if ( lastSync > localMod ) return 2; return 2; break; case SYNC_PREF_NEWEST: if ( localMod > remoteMod ) return 1; else return 2; break; case SYNC_PREF_ASK: //qDebug("lsy %s --- lo %s --- re %s ", lastSync.toString().latin1(), localMod.toString().latin1(), remoteMod.toString().latin1() ); if ( lastSync > remoteMod ) return 1; if ( lastSync > localMod ) return 2; localIsNew = localMod >= remoteMod; //qDebug("conflict! ************************************** "); { KPIM::AddresseeChooser acd ( *local,*remote, localIsNew , this ); result = acd.executeD(localIsNew); return result; } break; case SYNC_PREF_FORCE_LOCAL: return 1; break; case SYNC_PREF_FORCE_REMOTE: return 2; break; default: // SYNC_PREF_TAKE_BOTH not implemented break; } return 0; } bool KABCore::synchronizeAddressbooks( KABC::AddressBook* local, KABC::AddressBook* remote,int mode) { bool syncOK = true; int addedAddressee = 0; int addedAddresseeR = 0; int deletedAddresseeR = 0; int deletedAddresseeL = 0; int changedLocal = 0; int changedRemote = 0; QString mCurrentSyncName = syncManager->getCurrentSyncName(); QString mCurrentSyncDevice = syncManager->getCurrentSyncDevice(); //QPtrList<Addressee> el = local->rawAddressees(); Addressee addresseeR; QString uid; int take; Addressee addresseeL; Addressee addresseeRSync; Addressee addresseeLSync; // KABC::Addressee::List addresseeRSyncSharp = remote->getExternLastSyncAddressees(); //KABC::Addressee::List addresseeLSyncSharp = local->getExternLastSyncAddressees(); bool fullDateRange = false; local->resetTempSyncStat(); mLastAddressbookSync = QDateTime::currentDateTime(); if ( syncManager->syncWithDesktop() ) { // remote->removeSyncInfo( QString());//remove all info if ( KSyncManager::mRequestedSyncEvent.isValid() ) { mLastAddressbookSync = KSyncManager::mRequestedSyncEvent; qDebug("using extern time for calendar sync: %s ", mLastAddressbookSync.toString().latin1() ); } else { qDebug("KSyncManager::mRequestedSyncEvent has invalid datatime "); } } QDateTime modifiedCalendar = mLastAddressbookSync; addresseeLSync = getLastSyncAddressee(); qDebug("Last Sync %s ", addresseeLSync.revision().toString().latin1()); addresseeR = remote->findByUid("last-syncAddressee-"+mCurrentSyncName ); if ( !addresseeR.isEmpty() ) { addresseeRSync = addresseeR; remote->removeAddressee(addresseeR ); } else { if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { addresseeRSync = addresseeLSync ; } else { //qDebug("FULLDATE 1"); fullDateRange = true; Addressee newAdd; addresseeRSync = newAdd; addresseeRSync.setFamilyName(mCurrentSyncName + i18n(" - sync addressee")); addresseeRSync.setUid("last-syncAddressee-"+mCurrentSyncName ); addresseeRSync.setRevision( mLastAddressbookSync ); addresseeRSync.setCategories( i18n("SyncAddressee") ); } } if ( addresseeLSync.revision() == mLastAddressbookSync ) { // qDebug("FULLDATE 2"); fullDateRange = true; } if ( ! fullDateRange ) { if ( addresseeLSync.revision() != addresseeRSync.revision() ) { // qDebug("set fulldate to true %s %s" ,addresseeLSync->dtStart().toString().latin1(), addresseeRSync->dtStart().toString().latin1() ); //qDebug("%d %d %d %d ", addresseeLSync->dtStart().time().second(), addresseeLSync->dtStart().time().msec() , addresseeRSync->dtStart().time().second(), addresseeRSync->dtStart().time().msec()); fullDateRange = true; //qDebug("FULLDATE 3 %s %s", addresseeLSync.revision().toString().latin1() , addresseeRSync.revision().toString().latin1() ); } } // fullDateRange = true; // debug only! if ( fullDateRange ) mLastAddressbookSync = QDateTime::currentDateTime().addDays( -100*365); else mLastAddressbookSync = addresseeLSync.revision(); // for resyncing if own file has changed // PENDING fixme later when implemented #if 0 if ( mCurrentSyncDevice == "deleteaftersync" ) { mLastAddressbookSync = loadedFileVersion; qDebug("setting mLastAddressbookSync "); } #endif //qDebug("*************************** "); // qDebug("mLastAddressbookSync %s ",mLastAddressbookSync.toString().latin1() ); QStringList er = remote->uidList(); Addressee inR ;//= er.first(); Addressee inL; syncManager->showProgressBar(0, i18n("Syncing - close to abort!"), er.count()); int modulo = (er.count()/10)+1; int incCounter = 0; while ( incCounter < er.count()) { if (syncManager->isProgressBarCanceled()) return false; if ( incCounter % modulo == 0 ) syncManager->showProgressBar(incCounter); uid = er[ incCounter ]; bool skipIncidence = false; if ( uid.left(19) == QString("last-syncAddressee-") ) skipIncidence = true; QString idS,OidS; qApp->processEvents(); if ( !skipIncidence ) { inL = local->findByUid( uid ); inR = remote->findByUid( uid ); //inL.setResource( 0 ); //inR.setResource( 0 ); if ( !inL.isEmpty() ) { // maybe conflict - same uid in both calendars if ( !inL.resource() || inL.resource()->includeInSync() ) { - if ( take = takeAddressee( &inL, &inR, mode, fullDateRange ) ) { + if ( (take = takeAddressee( &inL, &inR, mode, fullDateRange )) ) { //qDebug("take %d %s ", take, inL.summary().latin1()); if ( take == 3 ) return false; if ( take == 1 ) {// take local ********************** if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { inL.setCsum( mCurrentSyncDevice, inR.getCsum(mCurrentSyncDevice) ); inL.setID( mCurrentSyncDevice, inR.getID(mCurrentSyncDevice) ); local->insertAddressee( inL, false ); idS = inR.externalUID(); OidS = inR.originalExternalUID(); } else idS = inR.IDStr(); remote->removeAddressee( inR ); inR = inL; inR.setTempSyncStat( SYNC_TEMPSTATE_INITIAL ); if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { inR.setOriginalExternalUID( OidS ); inR.setExternalUID( idS ); if ( syncManager->syncWithDesktop() ) { inR.setIDStr("changed" ); } //inR.insertCustom( "KADDRESSBOOK", "X-KDESYNC","changed" ); } else { inR.setIDStr( idS ); } inR.setResource( 0 ); remote->insertAddressee( inR , false); ++changedRemote; } else { // take == 2 take remote ********************** if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { if ( inR.revision().date().year() < 2004 ) inR.setRevision( modifiedCalendar ); } idS = inL.IDStr(); local->removeAddressee( inL ); inL = inR; inL.setIDStr( idS ); if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { inL.setCsum( mCurrentSyncDevice, inR.getCsum(mCurrentSyncDevice) ); inL.setID( mCurrentSyncDevice, inR.getID(mCurrentSyncDevice) ); } inL.setResource( 0 ); local->insertAddressee( inL , false ); ++changedLocal; } } } } else { // no conflict ********** add or delete remote if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { QString des = addresseeLSync.note(); if ( des.find( inR.getID(mCurrentSyncDevice) +"," ) >= 0 && mode != 5) { // delete it inR.setTempSyncStat( SYNC_TEMPSTATE_DELETE ); remote->insertAddressee( inR, false ); ++deletedAddresseeR; } else { inR.setRevision( modifiedCalendar ); remote->insertAddressee( inR, false ); inL = inR; inL.setIDStr( ":" ); inL.setCsum( mCurrentSyncDevice, inR.getCsum(mCurrentSyncDevice) ); inL.setID( mCurrentSyncDevice, inR.getID(mCurrentSyncDevice) ); inL.setResource( 0 ); local->insertAddressee( inL , false); ++addedAddressee; } } else { if ( inR.revision() > mLastAddressbookSync || mode == 5 ) { inR.setRevision( modifiedCalendar ); remote->insertAddressee( inR, false ); inR.setResource( 0 ); local->insertAddressee( inR, false ); ++addedAddressee; } else { // pending checkExternSyncAddressee(addresseeRSyncSharp, inR); remote->removeAddressee( inR ); ++deletedAddresseeR; } } } } ++incCounter; } er.clear(); QStringList el = local->uidList(); modulo = (el.count()/10)+1; syncManager->showProgressBar(0, i18n("Add / remove addressees"), el.count()); incCounter = 0; while ( incCounter < el.count()) { qApp->processEvents(); if (syncManager->isProgressBarCanceled()) return false; if ( incCounter % modulo == 0 ) syncManager->showProgressBar(incCounter); uid = el[ incCounter ]; bool skipIncidence = false; if ( uid.left(19) == QString("last-syncAddressee-") ) skipIncidence = true; if ( !skipIncidence ) { inL = local->findByUid( uid ); if ( !inL.resource() || inL.resource()->includeInSync() ) { inR = remote->findByUid( uid ); if ( inR.isEmpty() ) { // no conflict ********** add or delete local if ( mGlobalSyncMode == SYNC_MODE_EXTERNAL ) { if ( !inL.getID(mCurrentSyncDevice).isEmpty() && mode != 4 ) { // pending checkExternSyncAddressee(addresseeLSyncSharp, inL); local->removeAddressee( inL ); ++deletedAddresseeL; } else { if ( ! syncManager->mWriteBackExistingOnly ) { inL.removeID(mCurrentSyncDevice ); ++addedAddresseeR; inL.setRevision( modifiedCalendar ); local->insertAddressee( inL, false ); inR = inL; inR.setTempSyncStat( SYNC_TEMPSTATE_ADDED_EXTERNAL ); inR.setResource( 0 ); remote->insertAddressee( inR, false ); } } } else { if ( inL.revision() < mLastAddressbookSync && mode != 4 ) { //qDebug("data %s ", inL.revision().toString().latin1()); // pending checkExternSyncAddressee(addresseeLSyncSharp, inL); local->removeAddressee( inL ); ++deletedAddresseeL; } else { if ( ! syncManager->mWriteBackExistingOnly ) { ++addedAddresseeR; inL.setRevision( modifiedCalendar ); local->insertAddressee( inL, false ); inR = inL; inR.setIDStr( ":" ); inR.setResource( 0 ); remote->insertAddressee( inR, false ); } } } } } } ++incCounter; } el.clear(); syncManager->hideProgressBar(); mLastAddressbookSync = QDateTime::currentDateTime().addSecs( 1 ); // get rid of micro seconds QTime t = mLastAddressbookSync.time(); mLastAddressbookSync.setTime( QTime (t.hour (), t.minute (), t.second () ) ); addresseeLSync.setRevision( mLastAddressbookSync ); addresseeRSync.setRevision( mLastAddressbookSync ); addresseeRSync.setRole( i18n("!Remote from: ")+mCurrentSyncName ) ; addresseeLSync.setRole(i18n("!Local from: ") + mCurrentSyncName ); addresseeRSync.setGivenName( i18n("!DO NOT EDIT!") ) ; addresseeLSync.setGivenName(i18n("!DO NOT EDIT!") ); addresseeRSync.setOrganization( "!"+mLastAddressbookSync.toString() ) ; addresseeLSync.setOrganization("!"+ mLastAddressbookSync.toString() ); addresseeRSync.setNote( "" ) ; addresseeLSync.setNote( "" ); if ( mGlobalSyncMode == SYNC_MODE_NORMAL) remote->insertAddressee( addresseeRSync, false ); local->insertAddressee( addresseeLSync, false ); QString mes; mes .sprintf( i18n("Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n"),addedAddressee, addedAddresseeR, changedLocal, changedRemote, deletedAddresseeL, deletedAddresseeR ); qDebug( mes ); mes = i18n("Local addressbook changed!\n") +mes; if ( syncManager->mShowSyncSummary ) { if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel(this, mes, i18n("KA/Pi Synchronization"),i18n("Write back"))) { qDebug("cancelled "); return false; } } return syncOK; } //this is a overwritten callbackmethods from the syncinterface bool KABCore::sync(KSyncManager* manager, QString filename, int mode) { //pending prepare addresseeview for output //pending detect, if remote file has REV field. if not switch to external sync mGlobalSyncMode = SYNC_MODE_NORMAL; QString mCurrentSyncDevice = manager->getCurrentSyncDevice(); AddressBook abLocal(filename,"syncContact"); bool syncOK = false; if ( abLocal.load() ) { qDebug("AB loaded %s,sync mode %d",filename.latin1(), mode ); bool external = false; bool isXML = false; if ( filename.right(4) == ".xml") { mGlobalSyncMode = SYNC_MODE_EXTERNAL; isXML = true; abLocal.preExternSync( mAddressBook ,mCurrentSyncDevice, true ); } else { external = !manager->mIsKapiFile; if ( external ) { qDebug("Setting vcf mode to external "); mGlobalSyncMode = SYNC_MODE_EXTERNAL; AddressBook::Iterator it; for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { (*it).setID( mCurrentSyncDevice, (*it).uid() ); (*it).computeCsum( mCurrentSyncDevice ); } } } //AddressBook::Iterator it; //QStringList vcards; //for ( it = abLocal.begin(); it != abLocal.end(); ++it ) { // qDebug("Name %s ", (*it).familyName().latin1()); //} syncOK = synchronizeAddressbooks( mAddressBook, &abLocal, mode ); if ( syncOK ) { if ( syncManager->mWriteBackFile ) { if ( external ) abLocal.removeSyncAddressees( !isXML); qDebug("Saving remote AB "); if ( ! abLocal.saveAB()) qDebug("Error writing back AB to file "); if ( external ) { // afterwrite processing abLocal.postExternSync( mAddressBook,mCurrentSyncDevice ,isXML); } } } setModified(); } abLocal.removeResources(); if ( syncOK ) mViewManager->refreshView(); return syncOK; } void KABCore::removeSyncInfo( QString syncProfile) { qDebug("AB:removeSyncInfo for profile %s ", syncProfile.latin1()); mAddressBook->removeSyncInfo( syncProfile ); setModified(); } //this is a overwritten callbackmethods from the syncinterface bool KABCore::syncExternal(KSyncManager* manager, QString resource) { if ( resource == "phone" ) return syncPhone(); disableBR( true ); QString mCurrentSyncDevice = manager->getCurrentSyncDevice(); AddressBook abLocal( resource,"syncContact"); bool syncOK = false; if ( abLocal.load() ) { qDebug("AB sharp loaded ,sync device %s",mCurrentSyncDevice.latin1()); mGlobalSyncMode = SYNC_MODE_EXTERNAL; abLocal.preExternSync( mAddressBook ,mCurrentSyncDevice, false ); syncOK = synchronizeAddressbooks( mAddressBook, &abLocal, syncManager->mSyncAlgoPrefs ); if ( syncOK ) { if ( syncManager->mWriteBackFile ) { abLocal.removeSyncAddressees( false ); abLocal.saveAB(); abLocal.postExternSync( mAddressBook,mCurrentSyncDevice, true ); } } else message( i18n("Sync cancelled or failed.") ); setModified(); } abLocal.removeResources(); if ( syncOK ) mViewManager->refreshView(); disableBR( false ); return syncOK; } void KABCore::message( QString m ) { topLevelWidget()->setCaption( m ); mMessageTimer->start( 15000, true ); } bool KABCore::syncPhone() { QString mCurrentSyncDevice = syncManager->getCurrentSyncDevice(); QString fileName = getPhoneFile(); if ( !PhoneAccess::readFromPhone( fileName) ) { message(i18n("Phone access failed!")); return false; } AddressBook abLocal( fileName,"syncContact"); bool syncOK = false; { abLocal.importFromFile( fileName ); qDebug("AB phone loaded ,sync device %s",mCurrentSyncDevice.latin1()); mGlobalSyncMode = SYNC_MODE_EXTERNAL; abLocal.preparePhoneSync( mCurrentSyncDevice, true ); abLocal.preExternSync( mAddressBook ,mCurrentSyncDevice, true ); syncOK = synchronizeAddressbooks( mAddressBook, &abLocal, syncManager->mSyncAlgoPrefs ); if ( syncOK ) { if ( syncManager->mWriteBackFile ) { abLocal.removeSyncAddressees( true ); abLocal.saveABphone( fileName ); abLocal.findNewExtIds( fileName, mCurrentSyncDevice ); //abLocal.preparePhoneSync( mCurrentSyncDevice, false ); abLocal.postExternSync( mAddressBook,mCurrentSyncDevice, true ); } } setModified(); } abLocal.removeResources(); if ( syncOK ) mViewManager->refreshView(); return syncOK; } void KABCore::getFile( bool success ) { if ( ! success ) { message( i18n("Error receiving file. Nothing changed!") ); return; } int count = mAddressBook->importFromFile( sentSyncFile() , false, true ); if ( count ) setModified( true ); message( i18n("Pi-Sync successful!") ); mViewManager->refreshView(); } void KABCore::syncFileRequest() { if ( KABPrefs::instance()->mPassiveSyncWithDesktop ) { syncManager->slotSyncMenu( 999 ); } mAddressBook->export2File( sentSyncFile() ); } QString KABCore::sentSyncFile() { #ifdef DESKTOP_VERSION return locateLocal( "tmp", "copysyncab.vcf" ); #else return QString( "/tmp/copysyncab.vcf" ); #endif } void KABCore::setCaptionBack() { mMessageTimer->stop(); topLevelWidget()->setCaption( i18n("KAddressbook/Pi") ); } diff --git a/kaddressbook/views/cardview.cpp b/kaddressbook/views/cardview.cpp index da552c3..03df444 100644 --- a/kaddressbook/views/cardview.cpp +++ b/kaddressbook/views/cardview.cpp @@ -1,1722 +1,1722 @@ /* This file is part of KAddressBook. Copyright (c) 2002 Mike Pilone <mpilone@slac.com> 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. */ //BEGIN Includes #include "cardview.h" #include <limits.h> #include <qpainter.h> #include <qtimer.h> #include <qdatetime.h> #include <qlabel.h> #include <qstyle.h> #include <qcursor.h> #include <qtooltip.h> #include "kabprefs.h" #include <kdebug.h> #include <kglobalsettings.h> //END includes #define MIN_ITEM_WIDTH 80 //BEGIN Helpers ////////////////////////////////////// // CardViewTip class CardViewTip : public QLabel { public: CardViewTip(QWidget *parent=0, const char *name=0) : QLabel( parent, name ) { setPalette( QToolTip::palette() ); setFrameStyle( Panel|Plain ); setMidLineWidth(0); setIndent(1); } ~CardViewTip() {}; protected: void leaveEvent( QEvent * ) { hide(); } }; ////////////////////////////////////// // CardViewItemList // // Warning: make sure you use findRef() instead of find() to find an // item! Only the pointer value is unique in the list. // class CardViewItemList : public QPtrList<CardViewItem> { protected: virtual int compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2) { CardViewItem *cItem1 = (CardViewItem*)item1; CardViewItem *cItem2 = (CardViewItem*)item2; if ( cItem1 == cItem2 ) return 0; if ((cItem1 == 0) || (cItem2 == 0)) return cItem1 ? -1 : 1; if (cItem1->caption() < cItem2->caption()) return -1; else if (cItem1->caption() > cItem2->caption()) return 1; return 0; } private: /*int find( const CardViewItem * ) { qDebug("DON'T USE CardViewItemList::find( item )! Use findRef( item )!"); }*/ }; ////////////////////////////////////// // CardViewSeparator class CardViewSeparator { friend class CardView; public: CardViewSeparator(CardView *view) : mView(view) { mRect = QRect(0, 0, view->separatorWidth(), 0); } ~CardViewSeparator() {} void paintSeparator(QPainter *p, QColorGroup &cg) { p->fillRect(0, 0, mRect.width(), mRect.height(), cg.brush(QColorGroup::Button)); } void repaintSeparator() { mView->repaintContents(mRect); } private: CardView *mView; QRect mRect; }; //END Helpers //BEGIN Private Data class CardViewPrivate { public: CardViewPrivate() : mSelectionMode( CardView::Multi ), mDrawCardBorder( true ), mDrawFieldLabels( true ), mDrawSeparators( true), mSepWidth( 2 ), mShowEmptyFields( false ), mLayoutDirty( true ), mLastClickOnItem( false ), mItemMargin( 0 ), mItemSpacing( 10 ), mItemWidth( 200 ), mMaxFieldLines( INT_MAX ), mCurrentItem( 0L ), mLastClickPos( QPoint(0, 0) ), + mResizeAnchor(0), mRubberBandAnchor( 0 ), - mCompText( QString::null ), - mResizeAnchor(0) + mCompText( QString::null ) {}; CardViewItemList mItemList; QPtrList<CardViewSeparator> mSeparatorList; QFontMetrics *mFm; QFontMetrics *mBFm; // bold font QFont mHeaderFont; // custom header font CardView::SelectionMode mSelectionMode; bool mDrawCardBorder; bool mDrawFieldLabels; bool mDrawSeparators; int mSepWidth; bool mShowEmptyFields; bool mLayoutDirty; bool mLastClickOnItem; uint mItemMargin; // internal margin in items uint mItemSpacing; // spacing between items, column seperators and border int mItemWidth; // width of all items uint mMaxFieldLines; // Max lines to dispaly pr field CardViewItem *mCurrentItem; QPoint mLastClickPos; QTimer *mTimer; // times out if mouse rests for more than 500 msecs CardViewTip *mTip; // passed to the item under a resting cursor to display full text bool mOnSeparator; // set/reset on mouse movement // for resizing by dragging the separators int mResizeAnchor; // uint, ulong? the mouse down separator left int mRubberBandAnchor; // for erasing rubber bands // data used for resizing. // as they are beeded by each mouse move while resizing, we store them here, // saving 8 calculations in each mouse move. int colspace; // amount of space between items pr column uint first; // the first col to anchor at for painting rubber bands int firstX; // X position of first in pixel int pressed; // the colummn that was pressed on at resizing start int span; // pressed - first // key completion QString mCompText; // current completion string QDateTime mCompUpdated; // ...was updated at this time }; class CardViewItemPrivate { public: CardViewItemPrivate() : - x( 0 ), - y( 0 ), - mSelected( false ){}; + mSelected( false ), + x( 0 ), + y( 0 ){}; QString mCaption; QPtrList< CardViewItem::Field > mFieldList; bool mSelected; int x; // horizontal position, set by the view int y; // vertical position, set by the view int maxLabelWidth; // the width of the widest label, according to the view font. int hcache; // height cache }; //END Private Data //BEGIN CardViewItem CardViewItem::CardViewItem(CardView *parent, QString caption) : d(new CardViewItemPrivate()), mView(parent) { d->mCaption = caption; initialize(); } CardViewItem::~CardViewItem() { // Remove ourself from the view if (mView != 0) mView->takeItem(this); delete d; d = 0; } void CardViewItem::initialize() { d->mSelected = false; d->mFieldList.setAutoDelete(true); d->maxLabelWidth = 0; d->hcache=0; //calcRect(); // Add ourself to the view if (mView != 0) mView->insertItem(this); } void CardViewItem::paintCard(QPainter *p, QColorGroup &cg) { if (!mView) return; QPen pen; QBrush brush; QFontMetrics fm = *(mView->d->mFm); QFontMetrics bFm = *(mView->d->mBFm); bool drawLabels = mView->d->mDrawFieldLabels; bool drawBorder = mView->d->mDrawCardBorder; int mg = mView->itemMargin(); int w = mView->itemWidth() - (mg*2); int h = height() - (mg*2); const int colonWidth( fm.width(":") ); int labelXPos = 2 + mg; int labelWidth = QMIN( w/2 - 4 - mg, d->maxLabelWidth + colonWidth + 4 ); int valueXPos = labelWidth + 4 + mg; int valueWidth = w - labelWidth - 4 - mg; p->setFont( mView->font() ); labelWidth -= colonWidth; // extra space for the colon if (!drawLabels) { valueXPos = labelXPos; valueWidth = w - 4; } // Draw a simple box if (isSelected()) pen = QPen(cg.highlight(), 1); else pen = QPen(cg.button(), 1); p->setPen(pen); // Draw the border - this is only draw if the user asks for it. if (drawBorder) p->drawRect( mg, mg, w, h ); // set the proper pen color for the caption box if (isSelected()) brush = cg.brush(QColorGroup::Highlight); else brush = cg.brush(QColorGroup::Button); p->fillRect(mg, mg, w, 4 + bFm.height(), brush); // Now paint the caption p->save(); QFont bFont = mView->headerFont(); //bFont.setBold(true); p->setFont(bFont); if (isSelected()) p->setPen(cg.highlightedText()); else p->setPen(cg.buttonText()); p->drawText(2+mg, 2+mg + bFm.ascent()/*bFm.height()*//*-bFm.descent()*//*-bFm.leading()*/, trimString(d->mCaption, w-4, bFm)); p->restore(); // Go through the fields and draw them QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); QString label, value; int yPos = mg + 4 + bFm.height()/* + 1*/ + fm.height(); // why the + 1 ??? (anders) p->setPen(cg.text()); int fh = fm.height(); int cln( 0 ); QString tmp; int maxLines = mView->maxFieldLines(); for (iter.toFirst(); iter.current(); ++iter) { value = (*iter)->second; if ( value.isEmpty() && ! mView->d->mShowEmptyFields ) continue; if (drawLabels) { label = trimString((*iter)->first, labelWidth, fm); p->drawText(labelXPos, yPos, label + ":"); } /* US original for (cln=0; cln <= maxLines; cln++) { tmp = value.section('\n',cln,cln); if ( !tmp.isEmpty() ) p->drawText( valueXPos, yPos + cln*fh, trimString( tmp, valueWidth, fm ) ); else break; } */ //US new implementation QStringList strlst = QStringList::split('\n', value, true); for (cln=0; cln <= maxLines && cln <= (int)strlst.count(); cln++) { tmp = strlst[cln]; if ( !tmp.isEmpty() ) p->drawText( valueXPos, yPos + cln*fh, trimString( tmp, valueWidth, fm ) ); else break; } if ( cln == 0 ) cln = 1; yPos += cln * fh + 2; } // if we are the current item and the view has focus, draw focus rect if ( mView->currentItem() == this && mView->hasFocus() ) { /*US mView->style().drawPrimitive( QStyle::PE_FocusRect, p, QRect(0, 0, mView->itemWidth(), h+(2*mg)), cg, QStyle::Style_FocusAtBorder, QStyleOption( isSelected() ? cg.highlight() : cg.base() ) ); */ const QColor pHighl = isSelected() ? cg.highlight() : cg.base(); const QRect r(0, 0, mView->itemWidth(), h+(2*mg)); #ifndef DESKTOP_VERSION mView->style().drawFocusRect(p, r, cg, &pHighl, true); #endif } } const QString &CardViewItem::caption() const { return d->mCaption; } int CardViewItem::height( bool allowCache ) const { // use cache if ( allowCache && d->hcache ) return d->hcache; // Base height: // 2 for line width // 2 for top caption pad // 2 for bottom caption pad // 2 pad for the end // + 2 times the advised margin int baseHeight = 8 + ( 2 * mView->itemMargin() ); // size of font for each field // 2 pad for each field // anders: if the view does not show empty fields, check for value bool sef = mView->showEmptyFields(); int fh = mView->d->mFm->height();//lineSpacing(); // font height //int sp = QMAX( 0, 2- mView->d->mFm->leading() ); // field spacing NOTE make a property int fieldHeight = 0; int lines; int maxLines( mView->maxFieldLines() ); QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); for (iter.toFirst(); iter.current(); ++iter) { if ( !sef && (*iter)->second.isEmpty() ) continue; lines = QMIN( (*iter)->second.contains('\n') + 1, maxLines ); fieldHeight += ( lines * fh ) + 2;//sp; } // height of caption font (bold) fieldHeight += mView->d->mBFm->height(); d->hcache = baseHeight + fieldHeight; return d->hcache; } bool CardViewItem::isSelected() const { return d->mSelected; } void CardViewItem::setSelected(bool selected) { d->mSelected = selected; } void CardViewItem::insertField(const QString &label, const QString &value) { CardViewItem::Field *f = new CardViewItem::Field(label, value); d->mFieldList.append(f); d->hcache=0; if (mView) { mView->setLayoutDirty(true); d->maxLabelWidth = QMAX( mView->d->mFm->width( label ), d->maxLabelWidth ); } } void CardViewItem::removeField(const QString &label) { CardViewItem::Field *f; QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); for (iter.toFirst(); iter.current(); ++iter) { f = *iter; if (f->first == label) break; } if (*iter) d->mFieldList.remove(*iter); d->hcache = 0; if (mView) mView->setLayoutDirty(true); } void CardViewItem::clearFields() { d->mFieldList.clear(); d->hcache = 0; if (mView) mView->setLayoutDirty(true); } QString CardViewItem::trimString(const QString &text, int width, QFontMetrics &fm) { if (fm.width(text) <= width) return text; QString dots = "..."; int dotWidth = fm.width(dots); QString trimmed; int charNum = 0; while (fm.width(trimmed) + dotWidth < width) { trimmed += text[charNum]; charNum++; } // Now trim the last char, since it put the width over the top trimmed = trimmed.left(trimmed.length()-1); trimmed += dots; return trimmed; } CardViewItem *CardViewItem::nextItem() { CardViewItem *item = 0; if (mView) item = mView->itemAfter(this); return item; } void CardViewItem::repaintCard() { if (mView) mView->repaintItem(this); } void CardViewItem::setCaption(const QString &caption) { d->mCaption = caption; repaintCard(); } QString CardViewItem::fieldValue(const QString &label) { QPtrListIterator< CardViewItem::Field > iter(d->mFieldList); for (iter.toFirst(); iter.current(); ++iter) if ((*iter)->first == label) return (*iter)->second; return QString(); } void CardViewItem::showFullString( const QPoint &itempos, CardViewTip *tip ) { bool trimmed( false ); QString s; int mrg = mView->itemMargin(); int y = mView->d->mBFm->height() + 6 + mrg; int w = mView->itemWidth() - (2*mrg); int lw; bool drawLabels = mView->drawFieldLabels(); bool isLabel = drawLabels && itempos.x() < w/2 ? true : false; if ( itempos.y() < y ) { if ( itempos.y() < 8 + mrg || itempos.y() > y - 4 ) return; // this is the caption s = caption(); trimmed = mView->d->mBFm->width( s ) > w - 4; y = 2 + mrg; lw = 0; isLabel=true; } else { // find the field Field *f = fieldAt( itempos ); if ( !f || ( !mView->showEmptyFields() && f->second.isEmpty() ) ) return; // y position: // header font height + 4px hader margin + 2px leading + item margin // + actual field index * (fontheight + 2px leading) int maxLines = mView->maxFieldLines(); bool se = mView->showEmptyFields(); int fh = mView->d->mFm->height(); // { Field *_f; for (_f = d->mFieldList.first(); _f != f; _f = d->mFieldList.next()) if ( se || ! _f->second.isEmpty() ) y += ( QMIN(_f->second.contains('\n')+1, maxLines) * fh ) + 2; // } if ( isLabel && itempos.y() > y + fh ) return; // label or data? s = isLabel ? f->first : f->second; // trimmed? int colonWidth = mView->d->mFm->width(":"); lw = drawLabels ? // label width QMIN( w/2 - 4 - mrg, d->maxLabelWidth + colonWidth + 4 ) : 0; int mw = isLabel ? lw - colonWidth : w - lw - (mrg*2); // max width for string if ( isLabel ) { trimmed = mView->d->mFm->width( s ) > mw - colonWidth; } else { QRect r( mView->d->mFm->boundingRect( 0, 0, INT_MAX, INT_MAX, Qt::AlignTop|Qt::AlignLeft, s ) ); trimmed = r.width() > mw || r.height()/fh > QMIN(s.contains('\n') + 1, maxLines); } } if ( trimmed ) { tip->setFont( (isLabel && !lw) ? mView->headerFont() : mView->font() ); // if condition is true, a header tip->setText( s ); tip->adjustSize(); // find a proper position int lx; lx = isLabel || !drawLabels ? mrg : lw + mrg + 2 /*-1*/; QPoint pnt(mView->contentsToViewport( QPoint(d->x, d->y) )); pnt += QPoint(lx, y); if ( pnt.x() < 0 ) pnt.setX( 0 ); if ( pnt.x() + tip->width() > mView->visibleWidth() ) pnt.setX( mView->visibleWidth() - tip->width() ); if ( pnt.y() + tip->height() > mView->visibleHeight() ) pnt.setY( QMAX( 0, mView->visibleHeight() - tip->height() ) ); // show tip->move( pnt ); tip->show(); } } CardViewItem::Field *CardViewItem::fieldAt( const QPoint & itempos ) const { int ypos = mView->d->mBFm->height() + 7 + mView->d->mItemMargin; int iy = itempos.y(); // skip below caption if ( iy <= ypos ) return 0; // try find a field bool showEmpty = mView->showEmptyFields(); int fh = mView->d->mFm->height(); int maxLines = mView->maxFieldLines(); Field *f; for ( f = d->mFieldList.first(); f; f = d->mFieldList.next() ) { if ( showEmpty || !f->second.isEmpty() ) ypos += ( QMIN( f->second.contains('\n')+1, maxLines ) *fh)+2; if ( iy <= ypos ) break; } return f ? f : 0; } //END CardViewItem //BEGIN CardView CardView::CardView(QWidget *parent, const char *name) : QScrollView(parent, name), d(new CardViewPrivate()) { d->mItemList.setAutoDelete(true); d->mSeparatorList.setAutoDelete(true); QFont f = font(); d->mFm = new QFontMetrics(f); f.setBold(true); d->mHeaderFont = f; d->mBFm = new QFontMetrics(f); d->mTip = ( new CardViewTip( viewport() ) ), d->mTip->hide(); d->mTimer = ( new QTimer(this, "mouseTimer") ), viewport()->setMouseTracking( true ); viewport()->setFocusProxy(this); viewport()->setFocusPolicy(WheelFocus); viewport()->setBackgroundMode(PaletteBase); connect( d->mTimer, SIGNAL(timeout()), this, SLOT(tryShowFullText()) ); //US setBackgroundMode(PaletteBackground, PaletteBase); setBackgroundMode(PaletteBackground); // no reason for a vertical scrollbar setVScrollBarMode(AlwaysOff); } CardView::~CardView() { delete d->mFm; delete d->mBFm; delete d; d = 0; } void CardView::insertItem(CardViewItem *item) { d->mItemList.inSort(item); setLayoutDirty(true); } void CardView::takeItem(CardViewItem *item) { if ( d->mCurrentItem == item ) d->mCurrentItem = item->nextItem(); d->mItemList.take(d->mItemList.findRef(item)); setLayoutDirty(true); } void CardView::clear() { d->mItemList.clear(); setLayoutDirty(true); } CardViewItem *CardView::currentItem() { if ( ! d->mCurrentItem && d->mItemList.count() ) d->mCurrentItem = d->mItemList.first(); return d->mCurrentItem; } void CardView::setCurrentItem( CardViewItem *item ) { if ( !item ) return; else if ( item->cardView() != this ) { kdDebug(5720)<<"CardView::setCurrentItem: Item ("<<item<<") not owned! Backing out.."<<endl; return; } else if ( item == currentItem() ) { return; } if ( d->mSelectionMode == Single ) { setSelected( item, true ); } else { CardViewItem *it = d->mCurrentItem; d->mCurrentItem = item; if ( it ) it->repaintCard(); item->repaintCard(); } if ( ! d->mOnSeparator ) ensureItemVisible( item ); emit currentChanged( item ); } CardViewItem *CardView::itemAt(const QPoint &viewPos) { CardViewItem *item = 0; QPtrListIterator<CardViewItem> iter(d->mItemList); bool found = false; for (iter.toFirst(); iter.current() && !found; ++iter) { item = *iter; //if (item->d->mRect.contains(viewPos)) if (QRect(item->d->x, item->d->y, d->mItemWidth, item->height()).contains(viewPos)) found = true; } if (found) return item; return 0; } QRect CardView::itemRect(const CardViewItem *item) { //return item->d->mRect; return QRect(item->d->x, item->d->y, d->mItemWidth, item->height()); } void CardView::ensureItemVisible(const CardViewItem *item) { ensureVisible(item->d->x , item->d->y, d->mItemSpacing, 0); ensureVisible(item->d->x + d->mItemWidth, item->d->y, d->mItemSpacing, 0); } void CardView::repaintItem(const CardViewItem *item) { //repaintContents(item->d->mRect); repaintContents( QRect(item->d->x, item->d->y, d->mItemWidth, item->height()) ); } void CardView::setSelectionMode(CardView::SelectionMode mode) { selectAll(false); d->mSelectionMode = mode; } CardView::SelectionMode CardView::selectionMode() const { return d->mSelectionMode; } void CardView::selectAll(bool state) { QPtrListIterator<CardViewItem> iter(d->mItemList); if (!state) { for (iter.toFirst(); iter.current(); ++iter) { if ((*iter)->isSelected()) { (*iter)->setSelected(false); (*iter)->repaintCard(); } } //emit selectionChanged(); // WARNING FIXME emit selectionChanged(0); } else if (d->mSelectionMode != CardView::Single) { for (iter.toFirst(); iter.current(); ++iter) { (*iter)->setSelected(true); } if (d->mItemList.count() > 0) { // emit, since there must have been at least one selected emit selectionChanged(); //repaint();//??? viewport()->update(); } } } void CardView::setSelected(CardViewItem *item, bool selected) { if ((item == 0) || (item->isSelected() == selected)) return; if ( selected && d->mCurrentItem != item ) { CardViewItem *it = d->mCurrentItem; d->mCurrentItem = item; if ( it ) it->repaintCard(); } if (d->mSelectionMode == CardView::Single) { bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); if (selected) { item->setSelected(selected); item->repaintCard(); emit selectionChanged(); emit selectionChanged(item); } else { emit selectionChanged(); emit selectionChanged(0); } } else if (d->mSelectionMode == CardView::Multi) { item->setSelected(selected); item->repaintCard(); emit selectionChanged(); } else if (d->mSelectionMode == CardView::Extended) { bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); item->setSelected(selected); item->repaintCard(); emit selectionChanged(); } } bool CardView::isSelected(CardViewItem *item) const { return (item && item->isSelected()); } CardViewItem *CardView::selectedItem() const { // find the first selected item QPtrListIterator<CardViewItem> iter(d->mItemList); for (iter.toFirst(); iter.current(); ++iter) { if ((*iter)->isSelected()) return *iter; } return 0; } CardViewItem *CardView::firstItem() const { return d->mItemList.first(); } int CardView::childCount() const { return d->mItemList.count(); } /*US CardViewItem *CardView::findItem(const QString &text, const QString &label, Qt::StringComparisonMode compare) { // IF the text is empty, we will return null, since empty text will // match anything! if (text.isEmpty()) return 0; QPtrListIterator<CardViewItem> iter(d->mItemList); if (compare & Qt::BeginsWith) { QString value; for (iter.toFirst(); iter.current(); ++iter) { value = (*iter)->fieldValue(label).upper(); if (value.startsWith(text.upper())) return *iter; } } else { kdDebug(5720) << "CardView::findItem: search method not implemented" << endl; } return 0; } */ uint CardView::columnWidth() { return d->mDrawSeparators ? d->mItemWidth + ( 2 * d->mItemSpacing ) + d->mSepWidth : d->mItemWidth + d->mItemSpacing; } void CardView::drawContents(QPainter *p, int clipx, int clipy, int clipw, int cliph) { QScrollView::drawContents(p, clipx, clipy, clipw, cliph); if (d->mLayoutDirty) calcLayout(); //kdDebug() << "CardView::drawContents: " << clipx << ", " << clipy // << ", " << clipw << ", " << cliph << endl; QColorGroup cg = viewport()->palette().active(); // allow setting costum colors in the viewport pale QRect clipRect(clipx, clipy, clipw, cliph); QRect cardRect; QRect sepRect; CardViewItem *item; CardViewSeparator *sep; // make sure the viewport is a pure background viewport()->erase(clipRect); // Now tell the cards to draw, if they are in the clip region QPtrListIterator<CardViewItem> iter(d->mItemList); for (iter.toFirst(); iter.current(); ++iter) { item = *iter; cardRect.setRect( item->d->x, item->d->y, d->mItemWidth, item->height() ); if (clipRect.intersects(cardRect) || clipRect.contains(cardRect)) { //kdDebug() << "\trepainting card at: " << cardRect.x() << ", " // << cardRect.y() << endl; // Tell the card to paint p->save(); p->translate(cardRect.x(), cardRect.y()); item->paintCard(p, cg); p->restore(); } } // Followed by the separators if they are in the clip region QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList); for (sepIter.toFirst(); sepIter.current(); ++sepIter) { sep = *sepIter; sepRect = sep->mRect; if (clipRect.intersects(sepRect) || clipRect.contains(sepRect)) { p->save(); p->translate(sepRect.x(), sepRect.y()); sep->paintSeparator(p, cg); p->restore(); } } } void CardView::resizeEvent(QResizeEvent *e) { QScrollView::resizeEvent(e); setLayoutDirty(true); } void CardView::calcLayout() { //kdDebug() << "CardView::calcLayout:" << endl; // Start in the upper left corner and layout all the // cars using their height and width int maxWidth = 0; int maxHeight = 0; int xPos = 0; int yPos = 0; int cardSpacing = d->mItemSpacing; // delete the old separators d->mSeparatorList.clear(); QPtrListIterator<CardViewItem> iter(d->mItemList); CardViewItem *item = 0; CardViewSeparator *sep = 0; xPos += cardSpacing; for (iter.toFirst(); iter.current(); ++iter) { item = *iter; yPos += cardSpacing; if (yPos + item->height() + cardSpacing >= height() - horizontalScrollBar()->height()) { maxHeight = QMAX(maxHeight, yPos); // Drawing in this column would be greater than the height // of the scroll view, so move to next column yPos = cardSpacing; xPos += cardSpacing + maxWidth; if (d->mDrawSeparators) { // Create a separator since the user asked sep = new CardViewSeparator(this); sep->mRect.moveTopLeft(QPoint(xPos, yPos+d->mItemMargin)); xPos += d->mSepWidth + cardSpacing; d->mSeparatorList.append(sep); } maxWidth = 0; } item->d->x = xPos; item->d->y = yPos; yPos += item->height(); maxWidth = QMAX(maxWidth, d->mItemWidth); } xPos += maxWidth; resizeContents( xPos + cardSpacing, maxHeight ); // Update the height of all the separators now that we know the // max height of a column QPtrListIterator<CardViewSeparator> sepIter(d->mSeparatorList); for (sepIter.toFirst(); sepIter.current(); ++sepIter) { (*sepIter)->mRect.setHeight(maxHeight - 2*cardSpacing - 2*d->mItemMargin); } d->mLayoutDirty = false; } CardViewItem *CardView::itemAfter(CardViewItem *item) { /*int pos = */d->mItemList.findRef(item); return d->mItemList.next();//at(pos+1); } uint CardView::itemMargin() { return d->mItemMargin; } void CardView::setItemMargin( uint margin ) { if ( margin == d->mItemMargin ) return; d->mItemMargin = margin; setLayoutDirty( true ); } uint CardView::itemSpacing() { return d->mItemSpacing; } void CardView::setItemSpacing( uint spacing ) { if ( spacing == d->mItemSpacing ) return; d->mItemSpacing = spacing; setLayoutDirty( true ); } void CardView::contentsMousePressEvent(QMouseEvent *e) { QScrollView::contentsMousePressEvent(e); QPoint pos = e->pos(); d->mLastClickPos = pos; CardViewItem *item = itemAt(pos); if (item == 0) { d->mLastClickOnItem = false; if ( d->mOnSeparator) { d->mResizeAnchor = e->x()+contentsX(); d->colspace = (2*d->mItemSpacing) /*+ (2*d->mItemMargin)*/; int ccw = d->mItemWidth + d->colspace + d->mSepWidth; d->first = (contentsX()+d->mSepWidth)/ccw; d->pressed = (d->mResizeAnchor+d->mSepWidth)/ccw; d->span = d->pressed - d->first; d->firstX = d->first * ccw; if ( d->firstX ) d->firstX -= d->mSepWidth; // (no sep in col 0) } else { selectAll(false); } return; } d->mLastClickOnItem = true; CardViewItem *other = d->mCurrentItem; setCurrentItem( item ); // Always emit the selection emit clicked(item); // Check the selection type and update accordingly if (d->mSelectionMode == CardView::Single) { // make sure it isn't already selected if (item->isSelected()) return; bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); item->setSelected(true); item->repaintCard(); emit selectionChanged(item); } else if (d->mSelectionMode == CardView::Multi) { // toggle the selection item->setSelected(!item->isSelected()); item->repaintCard(); emit selectionChanged(); } else if (d->mSelectionMode == CardView::Extended) { if ((e->button() & Qt::LeftButton) && (e->state() & Qt::ShiftButton)) { if ( item == other ) return; bool s = ! item->isSelected(); if ( s && ! (e->state() & ControlButton) ) { bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); } int from, to, a, b; a = d->mItemList.findRef( item ); b = d->mItemList.findRef( other ); from = a < b ? a : b; to = a > b ? a : b; //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl; CardViewItem *aItem; for ( ; from <= to; from++ ) { aItem = d->mItemList.at( from ); aItem->setSelected( s ); repaintItem( aItem ); } emit selectionChanged(); } else if ((e->button() & Qt::LeftButton) && (e->state() & Qt::ControlButton)) { item->setSelected(!item->isSelected()); item->repaintCard(); emit selectionChanged(); } else if (e->button() & Qt::LeftButton) { bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); item->setSelected(true); item->repaintCard(); emit selectionChanged(); } } } void CardView::contentsMouseReleaseEvent(QMouseEvent *e) { QScrollView::contentsMouseReleaseEvent(e); if ( d->mResizeAnchor ) { // finish the resizing: unsetCursor(); // hide rubber bands int newiw = d->mItemWidth - ((d->mResizeAnchor - d->mRubberBandAnchor)/d->span); drawRubberBands( 0 ); // we should move to reflect the new position if we are scrolled. if ( contentsX() ) { int newX = QMAX( 0, ( d->pressed * ( newiw + d->colspace + d->mSepWidth ) ) - e->x() ); setContentsPos( newX, contentsY() ); } // set new item width setItemWidth( newiw ); // reset anchors d->mResizeAnchor = 0; d->mRubberBandAnchor = 0; return; } // If there are accel keys, we will not emit signals if ((e->state() & Qt::ShiftButton) || (e->state() & Qt::ControlButton)) return; // Get the item at this position CardViewItem *item = itemAt(e->pos()); if (item && KABPrefs::instance()->mHonorSingleClick) { emit executed(item); } } void CardView::contentsMouseDoubleClickEvent(QMouseEvent *e) { QScrollView::contentsMouseDoubleClickEvent(e); CardViewItem *item = itemAt(e->pos()); if (item) { d->mCurrentItem = item; } if (item && !KABPrefs::instance()->mHonorSingleClick) { emit executed(item); } else emit doubleClicked(item); } void CardView::contentsMouseMoveEvent( QMouseEvent *e ) { // resizing if ( d->mResizeAnchor ) { int x = e->x(); if ( x != d->mRubberBandAnchor ) drawRubberBands( x ); return; } if (d->mLastClickOnItem && (e->state() & Qt::LeftButton) && ((e->pos() - d->mLastClickPos).manhattanLength() > 4)) { startDrag(); return; } d->mTimer->start( 500 ); // see if we are over a separator // only if we actually have them painted? if ( d->mDrawSeparators ) { int colcontentw = d->mItemWidth + (2*d->mItemSpacing); int colw = colcontentw + d->mSepWidth; int m = e->x()%colw; if ( m >= colcontentw && m > 0 ) { setCursor( SplitVCursor ); // Why does this fail sometimes? d->mOnSeparator = true; } else { setCursor( ArrowCursor ); d->mOnSeparator = false; } } } void CardView::enterEvent( QEvent * ) { d->mTimer->start( 500 ); } void CardView::leaveEvent( QEvent * ) { d->mTimer->stop(); if (d->mOnSeparator) { d->mOnSeparator = false; setCursor( ArrowCursor ); } } void CardView::focusInEvent( QFocusEvent * ) { if (!d->mCurrentItem && d->mItemList.count() ) { setCurrentItem( d->mItemList.first() ); } else if ( d->mCurrentItem ) { d->mCurrentItem->repaintCard(); } } void CardView::focusOutEvent( QFocusEvent * ) { if (d->mCurrentItem) d->mCurrentItem->repaintCard(); } void CardView::keyPressEvent( QKeyEvent *e ) { if ( ! ( childCount() && d->mCurrentItem ) ) { e->ignore(); return; } uint pos = d->mItemList.findRef( d->mCurrentItem ); CardViewItem *aItem = 0L; // item that gets the focus CardViewItem *old = d->mCurrentItem; switch ( e->key() ) { case Key_Up: if ( pos > 0 ) { aItem = d->mItemList.at( pos - 1 ); setCurrentItem( aItem ); } break; case Key_Down: if ( pos < d->mItemList.count() - 1 ) { aItem = d->mItemList.at( pos + 1 ); setCurrentItem( aItem ); } break; case Key_Left: { // look for an item in the previous/next column, starting from // the vertical middle of the current item. // FIXME use nice calculatd measures!!! QPoint aPoint( d->mCurrentItem->d->x, d->mCurrentItem->d->y ); aPoint -= QPoint( 30,-(d->mCurrentItem->height()/2) ); aItem = itemAt( aPoint ); // maybe we hit some space below an item while ( !aItem && aPoint.y() > 27 ) { aPoint -= QPoint( 0, 16 ); aItem = itemAt( aPoint ); } if ( aItem ) setCurrentItem( aItem ); } break; case Key_Right: { // FIXME use nice calculated measures!!! QPoint aPoint( d->mCurrentItem->d->x + d->mItemWidth, d->mCurrentItem->d->y ); aPoint += QPoint( 30,(d->mCurrentItem->height()/2) ); aItem = itemAt( aPoint ); while ( !aItem && aPoint.y() > 27 ) { aPoint -= QPoint( 0, 16 ); aItem = itemAt( aPoint ); } if ( aItem ) setCurrentItem( aItem ); } break; case Key_Home: aItem = d->mItemList.first(); setCurrentItem( aItem ); break; case Key_End: aItem = d->mItemList.last(); setCurrentItem( aItem ); break; case Key_Prior: // PageUp { // QListView: "Make the item above the top visible and current" // TODO if contentsY(), pick the top item of the leftmost visible column if ( contentsX() <= 0 ) return; int cw = columnWidth(); int theCol = ( QMAX( 0, ( contentsX()/cw) * cw ) ) + d->mItemSpacing; aItem = itemAt( QPoint( theCol + 1, d->mItemSpacing + 1 ) ); if ( aItem ) setCurrentItem( aItem ); } break; case Key_Next: // PageDown { // QListView: "Make the item below the bottom visible and current" // find the first not fully visible column. // TODO: consider if a partly visible (or even hidden) item at the // bottom of the rightmost column exists int cw = columnWidth(); int theCol = ( (( contentsX() + visibleWidth() )/cw) * cw ) + d->mItemSpacing + 1; // if separators are on, we may need to we may be one column further right if only the spacing/sep is hidden if ( d->mDrawSeparators && cw - (( contentsX() + visibleWidth() )%cw) <= int( d->mItemSpacing + d->mSepWidth ) ) theCol += cw; // make sure this is not too far right while ( theCol > contentsWidth() ) theCol -= columnWidth(); aItem = itemAt( QPoint( theCol, d->mItemSpacing + 1 ) ); if ( aItem ) setCurrentItem( aItem ); } break; case Key_Space: setSelected( d->mCurrentItem, !d->mCurrentItem->isSelected() ); emit selectionChanged(); break; case Key_Return: case Key_Enter: { emit returnPressed( d->mCurrentItem ); emit executed( d->mCurrentItem ); } break; default: if ( (e->state() & ControlButton) && e->key() == Key_A ) { // select all selectAll( true ); break; } // if we have a string, do autosearch else if ( ! e->text().isEmpty() && e->text()[0].isPrint() ) { } break; } // handle selection if ( aItem ) { if ( d->mSelectionMode == CardView::Extended ) { if ( (e->state() & ShiftButton) ) { // shift button: toggle range // if control button is pressed, leave all items // and toggle selection current->old current // otherwise, ?????? bool s = ! aItem->isSelected(); int from, to, a, b; a = d->mItemList.findRef( aItem ); b = d->mItemList.findRef( old ); from = a < b ? a : b; to = a > b ? a : b; if ( to - from > 1 ) { bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); } //kdDebug()<<"selecting items "<<from<<" - "<<to<<" ( "<<s<<" )"<<endl; CardViewItem *item; for ( ; from <= to; from++ ) { item = d->mItemList.at( from ); item->setSelected( s ); repaintItem( item ); } emit selectionChanged(); } else if ( (e->state() & ControlButton) ) { // control button: do nothing } else { // no button: move selection to this item bool b = signalsBlocked(); blockSignals(true); selectAll(false); blockSignals(b); setSelected( aItem, true ); emit selectionChanged(); } } } } void CardView::contentsWheelEvent( QWheelEvent * e ) { scrollBy(2*e->delta()/-3, 0); } void CardView::setLayoutDirty(bool dirty) { if (d->mLayoutDirty != dirty) { d->mLayoutDirty = dirty; repaint(); } } void CardView::setDrawCardBorder(bool enabled) { if (enabled != d->mDrawCardBorder) { d->mDrawCardBorder = enabled; repaint(); } } bool CardView::drawCardBorder() const { return d->mDrawCardBorder; } void CardView::setDrawColSeparators(bool enabled) { if (enabled != d->mDrawSeparators) { d->mDrawSeparators = enabled; setLayoutDirty(true); } } bool CardView::drawColSeparators() const { return d->mDrawSeparators; } void CardView::setDrawFieldLabels(bool enabled) { if (enabled != d->mDrawFieldLabels) { d->mDrawFieldLabels = enabled; repaint(); } } bool CardView::drawFieldLabels() const { return d->mDrawFieldLabels; } void CardView::setShowEmptyFields(bool show) { if (show != d->mShowEmptyFields) { d->mShowEmptyFields = show; setLayoutDirty(true); } } bool CardView::showEmptyFields() const { return d->mShowEmptyFields; } void CardView::startDrag() { // The default implementation is a no-op. It must be // reimplemented in a subclass to be useful } void CardView::tryShowFullText() { d->mTimer->stop(); // if we have an item QPoint cpos = viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ); CardViewItem *item = itemAt( cpos ); if ( item ) { // query it for a value to display //QString s = item ? item->caption() : "(no item)"; //kdDebug()<<"MOUSE REST: "<<s<<endl; QPoint ipos = cpos - itemRect( item ).topLeft(); item->showFullString( ipos, d->mTip ); } } void CardView::drawRubberBands( int pos ) { if ( pos && ((pos-d->firstX)/d->span) - d->colspace - d->mSepWidth < MIN_ITEM_WIDTH ) return; int tmpcw = (d->mRubberBandAnchor-d->firstX)/d->span; int x = d->firstX + tmpcw - d->mSepWidth - contentsX(); int h = visibleHeight(); QPainter p( viewport() ); p.setRasterOp( XorROP ); p.setPen( gray ); p.setBrush( gray ); uint n = d->first; // erase if ( d->mRubberBandAnchor ) do { p.drawRect( x, 0, 2, h ); x += tmpcw; n++; } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); // paint new if ( ! pos ) return; tmpcw = (pos - d->firstX)/d->span; n = d->first; x = d->firstX + tmpcw - d->mSepWidth - contentsX(); do { p.drawRect( x, 0, 2, h ); x += tmpcw; n++; } while ( x < visibleWidth() && n < d->mSeparatorList.count() ); d->mRubberBandAnchor = pos; } int CardView::itemWidth() const { return d->mItemWidth; } void CardView::setItemWidth( int w ) { if ( w == d->mItemWidth ) return; if ( w < MIN_ITEM_WIDTH ) w = MIN_ITEM_WIDTH; d->mItemWidth = w; setLayoutDirty( true ); #ifndef KAB_EMBEDDED updateContents(); #else //KAB_EMBEDDED //US updateContents( d->contentsX(), d->contentsY(), visibleWidth(), visibleHeight() ); qDebug("CardView::setItemWidth has to be verified"); updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); #endif //KAB_EMBEDDED } void CardView::setHeaderFont( const QFont &fnt ) { d->mHeaderFont = fnt; delete d->mBFm; d->mBFm = new QFontMetrics( fnt ); } QFont CardView::headerFont() const { return d->mHeaderFont; } void CardView::setFont( const QFont &fnt ) { QScrollView::setFont( fnt ); delete d->mFm; d->mFm = new QFontMetrics( fnt ); } int CardView::separatorWidth() { return d->mSepWidth; } void CardView::setSeparatorWidth( int width ) { d->mSepWidth = width; setLayoutDirty( true ); // hmm, actually I could just adjust the x'es... } int CardView::maxFieldLines() const { return d->mMaxFieldLines; } void CardView::setMaxFieldLines( int howmany ) { d->mMaxFieldLines = howmany ? howmany : INT_MAX; // FIXME update, forcing the items to recalc height!! } //END Cardview #ifndef KAB_EMBEDDED #include "cardview.moc" #endif //KAB_EMBEDDED |