• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kontact

iconsidepane.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of KDE Kontact.
00003 
00004   Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
00005   Copyright (C) 2008 Rafael Fernández López <ereslibre@kde.org>
00006 
00007   This program is free software; you can redistribute it and/or
00008   modify it under the terms of the GNU General Public
00009   License as published by the Free Software Foundation; either
00010   version 2 of the License, or (at your option) any later version.
00011 
00012   This program is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with this program; see the file COPYING.  If not, write to
00019   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020   Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "iconsidepane.h"
00024 #include "mainwindow.h"
00025 #include "plugin.h"
00026 #include "prefs.h"
00027 
00028 #include <QtCore/QTimer>
00029 #include <QtGui/QStringListModel>
00030 #include <QtGui/QSortFilterProxyModel>
00031 #include <QtGui/QDragEnterEvent>
00032 #include <QtGui/QDragMoveEvent>
00033 #include <QtGui/QStyledItemDelegate>
00034 #include <QtGui/QScrollBar>
00035 
00036 #include <KLocalizedString>
00037 #include <KStringHandler>
00038 #include <KDialog>
00039 #include <KIcon>
00040 
00041 namespace Kontact
00042 {
00043 
00044 class Navigator;
00045 
00046 class SelectionModel : public QItemSelectionModel
00047 {
00048   public:
00049     SelectionModel( QAbstractItemModel *model, QObject *parent )
00050       : QItemSelectionModel( model, parent )
00051     {
00052     }
00053 
00054   public slots:
00055     virtual void clear()
00056     {
00057       // Don't allow the current selection to be cleared. QListView doesn't call to this method
00058       // nowadays, but just to cover of future change of implementation, since QTreeView does call
00059       // to this one when clearing the selection.
00060     }
00061 
00062     virtual void select( const QModelIndex &index, QItemSelectionModel::SelectionFlags command )
00063     {
00064       // Don't allow the current selection to be cleared
00065       if ( !index.isValid() && ( command & QItemSelectionModel::Clear ) ) {
00066         return;
00067       }
00068       QItemSelectionModel::select( index, command );
00069     }
00070 
00071     virtual void select( const QItemSelection &selection,
00072                          QItemSelectionModel::SelectionFlags command )
00073     {
00074       // Don't allow the current selection to be cleared
00075       if ( !selection.count() && ( command & QItemSelectionModel::Clear ) ) {
00076         return;
00077       }
00078       QItemSelectionModel::select( selection, command );
00079     }
00080 };
00081 
00082 class Model : public QStringListModel
00083 {
00084   public:
00085     enum SpecialRoles {
00086       PluginName = Qt::UserRole
00087     };
00088 
00089     Model( Navigator *parentNavigator = 0 )
00090       : QStringListModel( parentNavigator ), mNavigator(parentNavigator)
00091     {
00092     }
00093 
00094     void emitLayoutChanged()
00095     {
00096         emit layoutChanged();
00097     }
00098 
00099     void setPluginList( const QList<Kontact::Plugin*> &list ) {
00100       pluginList = list;
00101     }
00102 
00103     virtual Qt::ItemFlags flags( const QModelIndex &index ) const
00104     {
00105       Qt::ItemFlags flags = QStringListModel::flags( index );
00106 
00107       flags &= ~Qt::ItemIsEditable;
00108 
00109       if ( index.isValid() ) {
00110         if ( static_cast<Kontact::Plugin*>( index.internalPointer() )->disabled() ) {
00111           flags &= ~Qt::ItemIsEnabled;
00112           flags &= ~Qt::ItemIsSelectable;
00113           flags &= ~Qt::ItemIsDropEnabled;
00114         } else {
00115           flags |= Qt::ItemIsDropEnabled;
00116         }
00117       } else {
00118         flags &= ~Qt::ItemIsDropEnabled;
00119       }
00120 
00121       return flags;
00122     }
00123 
00124     virtual QModelIndex index( int row, int column,
00125                                const QModelIndex &parent = QModelIndex() ) const
00126     {
00127       Q_UNUSED( parent );
00128       if ( row < 0 || row >= pluginList.count() ) {
00129         return QModelIndex();
00130       }
00131       return createIndex( row, column, pluginList[row] );
00132     }
00133 
00134     virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const
00135     {
00136       if ( !index.isValid() || !index.internalPointer() ) {
00137         return QVariant();
00138       }
00139 
00140       if ( role == Qt::DisplayRole ) {
00141         if ( !mNavigator->showText() ) {
00142           return QVariant();
00143         }
00144         return static_cast<Kontact::Plugin*>( index.internalPointer() )->title();
00145       } else if ( role == Qt::DecorationRole ) {
00146         if ( !mNavigator->showIcons() ) {
00147           return QVariant();
00148         }
00149         return KIcon( static_cast<Kontact::Plugin*>( index.internalPointer() )->icon() );
00150       } else if ( role == Qt::TextAlignmentRole ) {
00151         return Qt::AlignCenter;
00152       } else if ( role == Qt::ToolTipRole ) {
00153         if ( !mNavigator->showText() ) {
00154           return static_cast<Kontact::Plugin*>( index.internalPointer() )->title();
00155         }
00156         return QVariant();
00157       } else if ( role == PluginName ) {
00158         return static_cast<Kontact::Plugin*>( index.internalPointer() )->identifier();
00159       }
00160       return QStringListModel::data( index, role );
00161     }
00162 
00163   private:
00164     QList<Kontact::Plugin*> pluginList;
00165     Navigator *mNavigator;
00166 };
00167 
00168 class SortFilterProxyModel
00169   : public QSortFilterProxyModel
00170 {
00171   public:
00172     SortFilterProxyModel( QObject *parent = 0 ): QSortFilterProxyModel( parent )
00173     {
00174       setDynamicSortFilter( true );
00175       sort ( 0 );
00176     }
00177   protected:
00178     bool lessThan( const QModelIndex &left, const QModelIndex &right ) const
00179     {
00180       Kontact::Plugin *leftPlugin = static_cast<Kontact::Plugin*>( left.internalPointer() );
00181       Kontact::Plugin *rightPlugin = static_cast<Kontact::Plugin*>( right.internalPointer() );
00182 
00183       if ( leftPlugin->weight() == rightPlugin->weight() ) {
00184         return KStringHandler::naturalCompare( leftPlugin->title(), rightPlugin->title() ) < 0;
00185       }
00186 
00187       return leftPlugin->weight() < rightPlugin->weight();
00188     }
00189 };
00190 
00191 class Delegate : public QStyledItemDelegate
00192 {
00193   public:
00194     Delegate( Navigator *parentNavigator = 0 )
00195       : QStyledItemDelegate( parentNavigator ), mNavigator( parentNavigator )
00196     {
00197     }
00198 
00199     void paint( QPainter *painter, const QStyleOptionViewItem &option,
00200                 const QModelIndex &index ) const
00201     {
00202       if ( !index.isValid() || !index.internalPointer() ) {
00203         return;
00204       }
00205 
00206       QStyleOptionViewItemV4 optionCopy( *static_cast<const QStyleOptionViewItemV4*>( &option ) );
00207       optionCopy.decorationPosition = QStyleOptionViewItem::Top;
00208       optionCopy.decorationSize = QSize( mNavigator->iconSize(), mNavigator->iconSize() );
00209       optionCopy.textElideMode = Qt::ElideNone;
00210       QStyledItemDelegate::paint( painter, optionCopy, index );
00211     }
00212 
00213     QSize sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
00214     {
00215       if ( !index.isValid() || !index.internalPointer() ) {
00216         return QSize();
00217       }
00218 
00219       QStyleOptionViewItemV4 optionCopy( *static_cast<const QStyleOptionViewItemV4*>( &option ) );
00220       optionCopy.decorationPosition = QStyleOptionViewItem::Top;
00221       optionCopy.decorationSize =
00222         mNavigator->showIcons() ? QSize( mNavigator->iconSize(), mNavigator->iconSize() ) : QSize();
00223       optionCopy.textElideMode = Qt::ElideNone;
00224       return QStyledItemDelegate::sizeHint( optionCopy, index );
00225     }
00226 
00227   private:
00228     Navigator *mNavigator;
00229 };
00230 
00231 Navigator::Navigator( SidePaneBase *parent )
00232   : QListView( parent ), mSidePane( parent )
00233 {
00234   setViewport( new QWidget( this ) );
00235 
00236   setVerticalScrollMode( ScrollPerPixel );
00237   setHorizontalScrollMode( ScrollPerPixel );
00238 
00239   mIconSize = Prefs::self()->sidePaneIconSize();
00240   mShowIcons = Prefs::self()->sidePaneShowIcons();
00241   mShowText = Prefs::self()->sidePaneShowText();
00242 
00243   QActionGroup *viewMode = new QActionGroup( this );
00244 
00245   mShowIconsAction = new KAction( i18n( "Show Icons Only" ), this );
00246   mShowIconsAction->setCheckable( true );
00247   mShowIconsAction->setActionGroup( viewMode );
00248   mShowIconsAction->setChecked( !mShowText && mShowIcons );
00249   connect( mShowIconsAction, SIGNAL(triggered(bool)), this, SLOT(slotActionTriggered(bool)) );
00250 
00251   mShowTextAction = new KAction( i18n( "Show Text Only" ), this );
00252   mShowTextAction->setCheckable( true );
00253   mShowTextAction->setActionGroup( viewMode );
00254   mShowTextAction->setChecked( mShowText && !mShowIcons );
00255   connect( mShowTextAction, SIGNAL(triggered(bool)), this, SLOT(slotActionTriggered(bool)) );
00256 
00257   mShowBothAction = new KAction( i18n( "Show Icons and Text" ), this );
00258   mShowBothAction->setCheckable( true );
00259   mShowBothAction->setActionGroup( viewMode );
00260   mShowBothAction->setChecked( mShowText && mShowIcons );
00261   connect( mShowBothAction, SIGNAL(triggered(bool)), this, SLOT(slotActionTriggered(bool)) );
00262 
00263   KAction *sep = new KAction( this );
00264   sep->setSeparator( true );
00265 
00266   QActionGroup *iconSize = new QActionGroup( this );
00267 
00268   mBigIconsAction = new KAction( i18n( "Big Icons" ), this );
00269   mBigIconsAction->setCheckable( iconSize );
00270   mBigIconsAction->setActionGroup( iconSize );
00271   mBigIconsAction->setChecked( mIconSize == KIconLoader::SizeLarge );
00272   connect( mBigIconsAction, SIGNAL(triggered(bool)), this, SLOT(slotActionTriggered(bool)) );
00273 
00274   mNormalIconsAction = new KAction( i18n( "Normal Icons" ), this );
00275   mNormalIconsAction->setCheckable( true );
00276   mNormalIconsAction->setActionGroup( iconSize );
00277   mNormalIconsAction->setChecked( mIconSize == KIconLoader::SizeMedium );
00278   connect( mNormalIconsAction, SIGNAL(triggered(bool)), this, SLOT(slotActionTriggered(bool)) );
00279 
00280   mSmallIconsAction = new KAction( i18n( "Small Icons" ), this );
00281   mSmallIconsAction->setCheckable( true );
00282   mSmallIconsAction->setActionGroup( iconSize );
00283   mSmallIconsAction->setChecked( mIconSize == KIconLoader::SizeSmallMedium );
00284   connect( mSmallIconsAction, SIGNAL(triggered(bool)), this, SLOT(slotActionTriggered(bool)) );
00285 
00286   QList<QAction*> actionList;
00287   actionList << mShowIconsAction << mShowTextAction << mShowBothAction << sep
00288              << mBigIconsAction << mNormalIconsAction << mSmallIconsAction;
00289 
00290   insertActions( 0, actionList );
00291 
00292   setContextMenuPolicy( Qt::ActionsContextMenu );
00293   setViewMode( ListMode );
00294   setItemDelegate( new Delegate( this ) );
00295   mModel = new Model( this );
00296   SortFilterProxyModel *sortFilterProxyModel = new SortFilterProxyModel;
00297   sortFilterProxyModel->setSourceModel( mModel );
00298   setModel( sortFilterProxyModel );
00299   setSelectionModel( new SelectionModel( sortFilterProxyModel, this ) );
00300 
00301   setDragDropMode( DropOnly );
00302   viewport()->setAcceptDrops( true );
00303   setDropIndicatorShown( true );
00304 
00305   connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
00306            this, SLOT(slotCurrentChanged(QModelIndex)) );
00307 }
00308 
00309 void Navigator::updatePlugins( QList<Kontact::Plugin*> plugins_ )
00310 {
00311   QString currentPlugin;
00312   if ( currentIndex().isValid() ) {
00313     currentPlugin = currentIndex().model()->data( currentIndex(), Model::PluginName ).toString();
00314   }
00315 
00316   QList<Kontact::Plugin*> pluginsToShow;
00317   foreach ( Kontact::Plugin *plugin, plugins_ ) {
00318     if ( plugin->showInSideBar() ) {
00319       pluginsToShow << plugin;
00320     }
00321   }
00322 
00323   mModel->setPluginList( pluginsToShow );
00324 
00325   mModel->removeRows( 0, mModel->rowCount() );
00326   mModel->insertRows( 0, pluginsToShow.count() );
00327 
00328   // Restore the previous selected index, if any
00329   if ( !currentPlugin.isEmpty() ) {
00330     setCurrentPlugin( currentPlugin );
00331   }
00332 }
00333 
00334 void Navigator::setCurrentPlugin( const QString &plugin )
00335 {
00336   for ( int i = 0; i < model()->rowCount(); i++ ) {
00337     const QModelIndex index = model()->index( i, 0 );
00338     const QString pluginName = model()->data( index, Model::PluginName ).toString();
00339 
00340     if ( plugin == pluginName ) {
00341       selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
00342       break;
00343     }
00344   }
00345 }
00346 
00347 QSize Navigator::sizeHint() const
00348 {
00349   //### TODO: We can cache this value, so this reply is faster. Since here we won't
00350   //          have too many elements, it is not that important. When caching this value
00351   //          make sure it is updated correctly when new rows have been added or
00352   //          removed. (ereslibre)
00353 
00354   int maxWidth = 0;
00355   for ( int i = 0; i < model()->rowCount(); i++ ) {
00356     const QModelIndex index = model()->index( i, 0 );
00357     maxWidth = qMax( maxWidth, sizeHintForIndex( index ).width() );
00358   }
00359 
00360   int viewHeight = QListView::sizeHint().height();
00361 
00362   return QSize( maxWidth + rect().width() - contentsRect().width(), viewHeight );
00363 }
00364 
00365 void Navigator::dragEnterEvent( QDragEnterEvent *event )
00366 {
00367   if ( event->proposedAction() == Qt::IgnoreAction ) {
00368     return;
00369   }
00370   event->acceptProposedAction();
00371 }
00372 
00373 void Navigator::dragMoveEvent( QDragMoveEvent *event )
00374 {
00375   if ( event->proposedAction() == Qt::IgnoreAction ) {
00376     return;
00377   }
00378 
00379   const QModelIndex dropIndex = indexAt( event->pos() );
00380 
00381   if ( !dropIndex.isValid() ||
00382        !( dropIndex.model()->flags( dropIndex ) & Qt::ItemIsEnabled ) ) {
00383     event->setAccepted( false );
00384     return;
00385   } else {
00386     const QModelIndex sourceIndex =
00387       static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( dropIndex );
00388     Kontact::Plugin *plugin =
00389       static_cast<Kontact::Plugin*>( sourceIndex.internalPointer() );
00390     if ( !plugin->canDecodeMimeData( event->mimeData() ) ) {
00391       event->setAccepted( false );
00392       return;
00393     }
00394   }
00395 
00396   event->acceptProposedAction();
00397 }
00398 
00399 void Navigator::dropEvent( QDropEvent *event )
00400 {
00401   if ( event->proposedAction() == Qt::IgnoreAction ) {
00402     return;
00403   }
00404 
00405   const QModelIndex dropIndex = indexAt( event->pos() );
00406 
00407   if ( !dropIndex.isValid() ) {
00408     return;
00409   } else {
00410     const QModelIndex sourceIndex =
00411       static_cast<const QSortFilterProxyModel*>( model() )->mapToSource( dropIndex );
00412     Kontact::Plugin *plugin =
00413       static_cast<Kontact::Plugin*>( sourceIndex.internalPointer() );
00414     plugin->processDropEvent( event );
00415   }
00416 }
00417 
00418 void Navigator::showEvent( QShowEvent *event )
00419 {
00420   parentWidget()->setMaximumWidth( sizeHint().width() );
00421   parentWidget()->setMinimumWidth( sizeHint().width() );
00422 
00423   QListView::showEvent( event );
00424 }
00425 
00426 void Navigator::slotCurrentChanged( const QModelIndex &current )
00427 {
00428   if ( !current.isValid() || !current.internalPointer() ||
00429        !( current.model()->flags( current ) & Qt::ItemIsEnabled ) ) {
00430     return;
00431   }
00432 
00433   QModelIndex source =
00434     static_cast<const QSortFilterProxyModel*>( current.model() )->mapToSource( current );
00435 
00436   emit pluginActivated( static_cast<Kontact::Plugin*>( source.internalPointer() ) );
00437 }
00438 
00439 void Navigator::slotActionTriggered( bool checked )
00440 {
00441   QObject *object = sender();
00442 
00443   if ( object == mShowIconsAction ) {
00444     mShowIcons = checked;
00445     mShowText = !checked;
00446   } else if ( object == mShowTextAction ) {
00447     mShowIcons = !checked;
00448     mShowText = checked;
00449   } else if ( object == mShowBothAction ) {
00450     mShowIcons = checked;
00451     mShowText = checked;
00452   } else if ( object == mBigIconsAction ) {
00453     mIconSize = KIconLoader::SizeLarge;
00454   } else if ( object == mNormalIconsAction ) {
00455     mIconSize = KIconLoader::SizeMedium;
00456   } else if ( object == mSmallIconsAction ) {
00457     mIconSize = KIconLoader::SizeSmallMedium;
00458   }
00459 
00460   Prefs::self()->setSidePaneIconSize( mIconSize );
00461   Prefs::self()->setSidePaneShowIcons( mShowIcons );
00462   Prefs::self()->setSidePaneShowText( mShowText );
00463 
00464   mModel->emitLayoutChanged();
00465 
00466   QTimer::singleShot( 0, this, SLOT(updateNavigatorSize()) );
00467 }
00468 
00469 void Navigator::updateNavigatorSize()
00470 {
00471   parentWidget()->setMaximumWidth( sizeHint().width() );
00472   parentWidget()->setMinimumWidth( sizeHint().width() );
00473 }
00474 
00475 IconSidePane::IconSidePane( Core *core, QWidget *parent )
00476   : SidePaneBase( core, parent )
00477 {
00478   mNavigator = new Navigator( this );
00479   mNavigator->setFocusPolicy( Qt::NoFocus );
00480   connect( mNavigator, SIGNAL(pluginActivated(Kontact::Plugin*)),
00481            SIGNAL(pluginSelected(Kontact::Plugin*)) );
00482 }
00483 
00484 IconSidePane::~IconSidePane()
00485 {
00486 }
00487 
00488 void IconSidePane::setCurrentPlugin( const QString &plugin )
00489 {
00490   mNavigator->setCurrentPlugin( plugin );
00491 }
00492 
00493 void IconSidePane::updatePlugins()
00494 {
00495   mNavigator->updatePlugins( core()->pluginList() );
00496 }
00497 
00498 void IconSidePane::resizeEvent( QResizeEvent *event )
00499 {
00500   Q_UNUSED( event );
00501   setMaximumWidth( mNavigator->sizeHint().width() );
00502   setMinimumWidth( mNavigator->sizeHint().width() );
00503 }
00504 
00505 }
00506 
00507 #include "iconsidepane.moc"
00508 
00509 // vim: sw=2 sts=2 et tw=80

kontact

Skip menu "kontact"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal