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