kaddressbook Library API Documentation

viewmanager.cpp

00001 /*
00002     This file is part of KAddressBook.
00003     Copyright (c) 2002 Mike Pilone <mpilone@slac.com>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 #include <qlayout.h>
00025 #include <qwidgetstack.h>
00026 
00027 #include <libkdepim/kvcarddrag.h>
00028 #include <kabc/addressbook.h>
00029 #include <kabc/vcardconverter.h>
00030 #include <kactionclasses.h>
00031 #include <kconfig.h>
00032 #include <kdebug.h>
00033 #include <kdeversion.h>
00034 #include <kiconloader.h>
00035 #include <klocale.h>
00036 #include <kmessagebox.h>
00037 #include <kmultipledrag.h>
00038 #include <ktrader.h>
00039 #include <kurldrag.h>
00040 
00041 #include "addviewdialog.h"
00042 #include "addresseeutil.h"
00043 #include "core.h"
00044 #include "filtereditdialog.h"
00045 #include "filterselectionwidget.h"
00046 #include "kabprefs.h"
00047 
00048 #include "viewmanager.h"
00049 
00050 ViewManager::ViewManager( KAB::Core *core, QWidget *parent, const char *name )
00051   : QWidget( parent, name ), mCore( core ), mActiveView( 0 ),
00052     mFilterSelectionWidget( 0 )
00053 {
00054   initGUI();
00055   initActions();
00056 
00057   mViewDict.setAutoDelete( true );
00058 
00059   createViewFactories();
00060 }
00061 
00062 ViewManager::~ViewManager()
00063 {
00064   unloadViews();
00065   mViewFactoryDict.clear();
00066 }
00067 
00068 void ViewManager::restoreSettings()
00069 {
00070   mViewNameList = KABPrefs::instance()->mViewNames;
00071   QString activeViewName = KABPrefs::instance()->mCurrentView;
00072 
00073   mActionSelectView->setItems( mViewNameList );
00074 
00075   // Filter
00076   mFilterList = Filter::restore( mCore->config(), "Filter" );
00077   mFilterSelectionWidget->setItems( filterNames() );
00078   mFilterSelectionWidget->setCurrentItem( KABPrefs::instance()->mCurrentFilter );
00079 
00080   // Tell the views to reread their config, since they may have
00081   // been modified by global settings
00082   QDictIterator<KAddressBookView> it( mViewDict );
00083   for ( it.toFirst(); it.current(); ++it ) {
00084     KConfigGroupSaver saver( mCore->config(), it.currentKey() );
00085     it.current()->readConfig( mCore->config() );
00086   }
00087 
00088   setActiveView( activeViewName );
00089 
00090   mActionDeleteView->setEnabled( mViewNameList.count() > 1 );
00091 }
00092 
00093 void ViewManager::saveSettings()
00094 {
00095   QDictIterator<KAddressBookView> it( mViewDict );
00096   for ( it.toFirst(); it.current(); ++it ) {
00097     KConfigGroupSaver saver( mCore->config(), it.currentKey() );
00098     (*it)->writeConfig( mCore->config() );
00099   }
00100 
00101   Filter::save( mCore->config(), "Filter", mFilterList );
00102   KABPrefs::instance()->mCurrentFilter = mFilterSelectionWidget->currentItem();
00103 
00104   // write the view name list
00105   KABPrefs::instance()->mViewNames = mViewNameList;
00106   KABPrefs::instance()->mCurrentView = mActiveView->caption();
00107 }
00108 
00109 QStringList ViewManager::selectedUids() const
00110 {
00111   if ( mActiveView )
00112     return mActiveView->selectedUids();
00113   else
00114     return QStringList();
00115 }
00116 
00117 QStringList ViewManager::selectedEmails() const
00118 {
00119   if ( mActiveView )
00120     return mActiveView->selectedEmails();
00121   else
00122     return QStringList();
00123 }
00124 
00125 KABC::Addressee::List ViewManager::selectedAddressees() const
00126 {
00127   KABC::Addressee::List list;
00128   if ( mActiveView ) {
00129     QStringList uids = mActiveView->selectedUids();
00130     QStringList::Iterator it;
00131     for ( it = uids.begin(); it != uids.end(); ++it ) {
00132       KABC::Addressee addr = mCore->addressBook()->findByUid( *it );
00133       if ( !addr.isEmpty() )
00134         list.append( addr );
00135     }
00136   }
00137 
00138   return list;
00139 }
00140 
00141 void ViewManager::setFilterSelectionWidget( FilterSelectionWidget *wdg )
00142 {
00143   mFilterSelectionWidget = wdg;
00144 }
00145 
00146 KABC::Field *ViewManager::currentSortField() const
00147 {
00148   if ( mActiveView )
00149     return mActiveView->sortField();
00150   else
00151     return 0;
00152 }
00153 
00154 void ViewManager::setSelected( const QString &uid, bool selected )
00155 {
00156   if ( mActiveView )
00157     mActiveView->setSelected( uid, selected );
00158 }
00159 
00160 void ViewManager::unloadViews()
00161 {
00162   mViewDict.clear();
00163   mActiveView = 0;
00164 }
00165 
00166 void ViewManager::setActiveView( const QString &name )
00167 {
00168   KAddressBookView *view = 0;
00169 
00170   // Check that this isn't the same as the current active view
00171   if ( mActiveView && ( mActiveView->caption() == name ) )
00172     return;
00173 
00174   // At this point we know the view that should be active is not
00175   // currently active. We will try to find the new on in the list. If
00176   // we can't find it, it means it hasn't been instantiated, so we will
00177   // create it on demand.
00178 
00179   view = mViewDict.find( name );
00180 
00181   // Check if we found the view. If we didn't, then we need to create it
00182   if ( view == 0 ) {
00183     KConfig *config = mCore->config();
00184     KConfigGroupSaver saver( config, name );
00185     QString type = config->readEntry( "Type", "Table" );
00186 
00187     kdDebug(5720) << "ViewManager::setActiveView: creating view - " << name << endl;
00188 
00189     ViewFactory *factory = mViewFactoryDict.find( type );
00190     if ( factory )
00191       view = factory->view( mCore, mViewWidgetStack );
00192 
00193     if ( view ) {
00194       view->setCaption( name );
00195       mViewDict.insert( name, view );
00196       mViewWidgetStack->addWidget( view );
00197       view->readConfig( config );
00198 
00199       // The manager just relays the signals
00200       connect( view, SIGNAL( selected( const QString& ) ),
00201                SIGNAL( selected( const QString & ) ) );
00202       connect( view, SIGNAL( executed( const QString& ) ),
00203                SIGNAL( executed( const QString& ) ) );
00204       connect( view, SIGNAL( modified() ), SIGNAL( modified() ) );
00205       connect( view, SIGNAL( dropped( QDropEvent* ) ),
00206                SLOT( dropped( QDropEvent* ) ) );
00207       connect( view, SIGNAL( startDrag() ), SLOT( startDrag() ) );
00208       connect( view, SIGNAL( sortFieldChanged() ), SIGNAL( sortFieldChanged() ) );
00209     }
00210   }
00211 
00212   // If we found or created the view, raise it and refresh it
00213   if ( view ) {
00214     mActiveView = view;
00215     mViewWidgetStack->raiseWidget( view );
00216     // Set the proper filter in the view. By setting the combo
00217     // box, the activated slot will be called, which will push
00218     // the filter to the view and refresh it.
00219     if ( view->defaultFilterType() == KAddressBookView::None ) {
00220       mFilterSelectionWidget->setCurrentItem( 0 );
00221       setActiveFilter( 0 );
00222     } else if ( view->defaultFilterType() == KAddressBookView::Active ) {
00223       setActiveFilter( mFilterSelectionWidget->currentItem() );
00224     } else {
00225       uint pos = filterPosition( view->defaultFilterName() );
00226       mFilterSelectionWidget->setCurrentItem( pos );
00227       setActiveFilter( pos );
00228     }
00229 
00230     // Update the inc search widget to show the fields in the new active
00231     // view.
00232     mCore->setSearchFields( mActiveView->fields() );
00233     mActiveView->refresh();
00234 
00235   } else
00236     kdDebug(5720) << "ViewManager::setActiveView: unable to find view\n";
00237 }
00238 
00239 void ViewManager::refreshView( const QString &uid )
00240 {
00241   if ( mActiveView )
00242     mActiveView->refresh( uid );
00243 }
00244 
00245 void ViewManager::editView()
00246 {
00247   if ( !mActiveView )
00248     return;
00249 
00250   ViewFactory *factory = mViewFactoryDict.find( mActiveView->type() );
00251   ViewConfigureWidget *wdg = 0;
00252 
00253   if ( factory ) {
00254     // Save the filters so the dialog has the latest set
00255     Filter::save( mCore->config(), "Filter", mFilterList );
00256 
00257     wdg = factory->configureWidget( mCore->addressBook(), 0 );
00258   }
00259 
00260   if ( wdg ) {
00261     ViewConfigureDialog dlg( wdg, mActiveView->caption(), this );
00262 
00263     KConfigGroupSaver saver( mCore->config(), mActiveView->caption() );
00264     dlg.restoreSettings( mCore->config() );
00265 
00266     if ( dlg.exec() ) {
00267       dlg.saveSettings( mCore->config() );
00268       mActiveView->readConfig( mCore->config() );
00269 
00270       // Set the proper filter in the view. By setting the combo
00271       // box, the activated slot will be called, which will push
00272       // the filter to the view and refresh it.
00273       if ( mActiveView->defaultFilterType() == KAddressBookView::None ) {
00274         mFilterSelectionWidget->setCurrentItem( 0 );
00275         setActiveFilter( 0 );
00276       } else if ( mActiveView->defaultFilterType() == KAddressBookView::Active ) {
00277         setActiveFilter( mFilterSelectionWidget->currentItem() );
00278       } else {
00279         uint pos = filterPosition( mActiveView->defaultFilterName() );
00280         mFilterSelectionWidget->setCurrentItem( pos );
00281         setActiveFilter( pos );
00282       }
00283 
00284       mCore->setSearchFields( mActiveView->fields() );
00285       mActiveView->refresh();
00286     }
00287   }
00288 }
00289 
00290 void ViewManager::deleteView()
00291 {
00292   QString text = i18n( "<qt>Are you sure that you want to delete the view <b>%1</b>?</qt>" )
00293                      .arg( mActiveView->caption() );
00294   QString caption = i18n( "Confirm Delete" );
00295 
00296   if ( KMessageBox::questionYesNo( this, text, caption ) == KMessageBox::Yes ) {
00297     mViewNameList.remove( mActiveView->caption() );
00298 
00299     // remove the view from the config file
00300     KConfig *config = mCore->config();
00301     config->deleteGroup( mActiveView->caption() );
00302 
00303     mViewDict.remove( mActiveView->caption() );
00304     mActiveView = 0;
00305 
00306     // we are in an invalid state now, but that should be fixed after
00307     // we emit the signal
00308     mActionSelectView->setItems( mViewNameList );
00309     if ( mViewNameList.count() > 0 ) {
00310       mActionSelectView->setCurrentItem( 0 );
00311       setActiveView( mViewNameList[ 0 ] );
00312     }
00313     mActionDeleteView->setEnabled( mViewNameList.count() > 1 );
00314   }
00315 }
00316 
00317 void ViewManager::addView()
00318 {
00319   AddViewDialog dialog( &mViewFactoryDict, this );
00320 
00321   if ( dialog.exec() ) {
00322     QString newName = dialog.viewName();
00323     QString type = dialog.viewType();
00324 
00325     // Check for name conflicts
00326     bool firstConflict = true;
00327     int numTries = 1;
00328     while ( mViewNameList.contains( newName ) > 0 ) {
00329       if ( !firstConflict ) {
00330         newName = newName.left( newName.length() - 4 );
00331         firstConflict = false;
00332       }
00333 
00334       newName = QString( "%1 <%2>" ).arg( newName ).arg( numTries );
00335       numTries++;
00336     }
00337 
00338     // Add the new one to the list
00339     mViewNameList.append( newName );
00340 
00341     // write the view to the config file,
00342     KConfig *config = mCore->config();
00343     config->deleteGroup( newName );
00344     KConfigGroupSaver saver( config, newName );
00345     config->writeEntry( "Type", type );
00346 
00347     // try to set the active view
00348     mActionSelectView->setItems( mViewNameList );
00349     mActionSelectView->setCurrentItem( mViewNameList.findIndex( newName ) );
00350     setActiveView( newName );
00351 
00352     editView();
00353 
00354     mActionDeleteView->setEnabled( mViewNameList.count() > 1 );
00355   }
00356 }
00357 
00358 void ViewManager::createViewFactories()
00359 {
00360   KTrader::OfferList plugins = KTrader::self()->query( "KAddressBook/View" );
00361   KTrader::OfferList::ConstIterator it;
00362   for ( it = plugins.begin(); it != plugins.end(); ++it ) {
00363     if ( !(*it)->hasServiceType( "KAddressBook/View" ) )
00364       continue;
00365 
00366     KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().latin1() );
00367 
00368     if ( !factory ) {
00369       kdDebug(5720) << "ViewManager::createViewFactories(): Factory creation failed" << endl;
00370       continue;
00371     }
00372 
00373     ViewFactory *viewFactory = static_cast<ViewFactory*>( factory );
00374 
00375     if ( !viewFactory ) {
00376       kdDebug(5720) << "ViewManager::createViewFactories(): Cast failed" << endl;
00377       continue;
00378     }
00379 
00380     mViewFactoryDict.insert( viewFactory->type(), viewFactory );
00381   }
00382 }
00383 
00384 void ViewManager::dropped( QDropEvent *e )
00385 {
00386   kdDebug(5720) << "ViewManager::dropped: got a drop event" << endl;
00387 
00388   QString clipText, vcards;
00389   KURL::List urls;
00390 
00391   if ( KURLDrag::decode( e, urls) ) {
00392     KURL::List::Iterator it = urls.begin();
00393     int c = urls.count();
00394     if ( c > 1 ) {
00395       QString questionString = i18n( "Import one contact into your addressbook?", "Import %n contacts into your addressbook?", c );
00396       if ( KMessageBox::questionYesNo( this, questionString, i18n( "Import Contacts?" ) ) == KMessageBox::Yes ) {
00397         for ( ; it != urls.end(); ++it )
00398           emit urlDropped( *it );
00399       }
00400     } else if ( c == 1 )
00401       emit urlDropped( *it );
00402   } else if ( KVCardDrag::decode( e, vcards ) ) {
00403     KABC::VCardConverter converter;
00404 
00405     KABC::Addressee::List list = converter.parseVCards( vcards );
00406     KABC::Addressee::List::Iterator it;
00407     for ( it = list.begin(); it != list.end(); ++it ) {
00408       KABC::Addressee a = mCore->addressBook()->findByUid( (*it).uid() );
00409       if ( a.isEmpty() ) { // not yet in address book
00410         mCore->addressBook()->insertAddressee( *it );
00411         emit modified();
00412       }
00413     }
00414 
00415     mActiveView->refresh();
00416   }
00417 }
00418 
00419 void ViewManager::startDrag()
00420 {
00421   // Get the list of all the selected addressees
00422   KABC::Addressee::List addrList;
00423   QStringList uidList = selectedUids();
00424   if (  uidList.isEmpty() )
00425       return;
00426   kdDebug(5720) << "ViewManager::startDrag: starting to drag" << endl;
00427 
00428   QStringList::Iterator it;
00429   for ( it = uidList.begin(); it != uidList.end(); ++it )
00430     addrList.append( mCore->addressBook()->findByUid( *it ) );
00431 
00432   KMultipleDrag *drag = new KMultipleDrag( this );
00433   drag->addDragObject( new QTextDrag( AddresseeUtil::addresseesToEmails( addrList ), this ) );
00434 
00435   KABC::VCardConverter converter;
00436   QString vcards = converter.createVCards( addrList );
00437   drag->addDragObject( new KVCardDrag( vcards, this ) );
00438 
00439   drag->setPixmap( KGlobal::iconLoader()->loadIcon( "vcard", KIcon::Desktop ) );
00440   drag->dragCopy();
00441 }
00442 
00443 void ViewManager::setActiveFilter( int index )
00444 {
00445   Filter currentFilter;
00446 
00447   if ( ( index - 1 ) < 0 )
00448     currentFilter = Filter();
00449   else
00450     currentFilter = mFilterList[ index - 1 ];
00451 
00452   // Check if we have a view. Since the filter combo is created before
00453   // the view, this slot could be called before there is a valid view.
00454   if ( mActiveView ) {
00455     mActiveView->setFilter( currentFilter );
00456     mActiveView->refresh();
00457     emit selected( QString::null );
00458   }
00459 }
00460 
00461 void ViewManager::configureFilters()
00462 {
00463   FilterDialog dlg( this );
00464 
00465   dlg.setFilters( mFilterList );
00466 
00467   if ( dlg.exec() )
00468     mFilterList = dlg.filters();
00469 
00470   uint pos = mFilterSelectionWidget->currentItem();
00471   mFilterSelectionWidget->setItems( filterNames() );
00472   mFilterSelectionWidget->setCurrentItem( pos );
00473   setActiveFilter( pos );
00474 }
00475 
00476 QStringList ViewManager::filterNames() const
00477 {
00478   QStringList names( i18n( "None" ) );
00479 
00480   Filter::List::ConstIterator it;
00481   for ( it = mFilterList.begin(); it != mFilterList.end(); ++it )
00482     names.append( (*it).name() );
00483 
00484   return names;
00485 }
00486 
00487 int ViewManager::filterPosition( const QString &name ) const
00488 {
00489   int pos = 0;
00490 
00491   Filter::List::ConstIterator it;
00492   for ( it = mFilterList.begin(); it != mFilterList.end(); ++it, ++pos )
00493     if ( name == (*it).name() )
00494       return pos + 1;
00495 
00496   return 0;
00497 }
00498 
00499 void ViewManager::initActions()
00500 {
00501   mActionSelectView = new KSelectAction( i18n( "Select View" ), 0, mCore->actionCollection(), "select_view" );
00502 #if KDE_VERSION >= 309
00503   mActionSelectView->setMenuAccelsEnabled( false );
00504 #endif
00505   connect( mActionSelectView, SIGNAL( activated( const QString& ) ),
00506            SLOT( setActiveView( const QString& ) ) );
00507 
00508   KAction *action;
00509 
00510   action = new KAction( i18n( "Modify View..." ), "configure", 0, this,
00511                         SLOT( editView() ), mCore->actionCollection(),
00512                         "view_modify" );
00513   action->setWhatsThis( i18n( "By pressing this button a dialog opens that allows you to modify the view of the addressbook. There you can add or remove fields that you want to be shown or hidden in the addressbook like the name for example." ) );
00514 
00515   action = new KAction( i18n( "Add View..." ), "window_new", 0, this,
00516                         SLOT( addView() ), mCore->actionCollection(),
00517                         "view_add" );
00518   action->setWhatsThis( i18n( "You can add a new view by choosing one of the dialog that appears after pressing the button. You have to give the view a name, so that you can distinguish between the different views." ) );
00519 
00520   mActionDeleteView = new KAction( i18n( "Delete View" ), "view_remove", 0,
00521                                    this, SLOT( deleteView() ),
00522                                    mCore->actionCollection(), "view_delete" );
00523   mActionDeleteView->setWhatsThis( i18n( "By pressing this button you can delete the actual view, which you have added before." ) );
00524 
00525   action = new KAction( i18n( "Refresh View" ), "reload", 0, this,
00526                SLOT( refreshView() ), mCore->actionCollection(),
00527                "view_refresh" );
00528   action->setWhatsThis( i18n( "The view will be refreshed by pressing this button." ) );
00529 
00530   action = new KAction( i18n( "Edit &Filters..." ), "filter", 0, this,
00531                SLOT( configureFilters() ), mCore->actionCollection(),
00532                "options_edit_filters" );
00533   action->setWhatsThis( i18n( "Edit the contact filters<p>You will be presented with a dialog, where you can add, remove and edit filters." ) );
00534 }
00535 
00536 void ViewManager::initGUI()
00537 {
00538   QHBoxLayout *layout = new QHBoxLayout( this );
00539   mViewWidgetStack = new QWidgetStack( this );
00540   layout->addWidget( mViewWidgetStack );
00541 }
00542 
00543 #include "viewmanager.moc"
KDE Logo
This file is part of the documentation for kaddressbook Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:38:53 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003