25 using namespace Kontact;
 
   27 #include <KontactInterface/Core> 
   28 #include <KontactInterface/Plugin> 
   33 #include <KStringHandler> 
   35 #include <QDragEnterEvent> 
   36 #include <QDragMoveEvent> 
   38 #include <QSortFilterProxyModel> 
   39 #include <QStringListModel> 
   40 #include <QStyledItemDelegate> 
   45 class SelectionModel : 
public QItemSelectionModel
 
   48     SelectionModel( QAbstractItemModel *model, 
QObject *parent )
 
   49       : QItemSelectionModel( model, parent )
 
   61     void select( 
const QModelIndex &index, QItemSelectionModel::SelectionFlags command )
 
   64       if ( !index.isValid() && ( command & QItemSelectionModel::Clear ) ) {
 
   67       QItemSelectionModel::select( index, command );
 
   70     void select( 
const QItemSelection &selection,
 
   71                          QItemSelectionModel::SelectionFlags command )
 
   74       if ( !selection.count() && ( command & QItemSelectionModel::Clear ) ) {
 
   77       QItemSelectionModel::select( selection, command );
 
   81 class Model : 
public QStringListModel
 
   85       PluginName = Qt::UserRole
 
   89       : QStringListModel( parentNavigator ), mNavigator(parentNavigator)
 
  102     Qt::ItemFlags flags( 
const QModelIndex &index )
 const 
  104       Qt::ItemFlags flags = QStringListModel::flags( index );
 
  106       flags &= ~Qt::ItemIsEditable;
 
  108       if ( index.isValid() ) {
 
  109         if ( static_cast<KontactInterface::Plugin*>( index.internalPointer() )->disabled() ) {
 
  110           flags &= ~Qt::ItemIsEnabled;
 
  111           flags &= ~Qt::ItemIsSelectable;
 
  112           flags &= ~Qt::ItemIsDropEnabled;
 
  114           flags |= Qt::ItemIsDropEnabled;
 
  117         flags &= ~Qt::ItemIsDropEnabled;
 
  123     QModelIndex index( 
int row, 
int column,
 
  124                                const QModelIndex &parent = QModelIndex() )
 const 
  127       if ( row < 0 || row >= pluginList.count() ) {
 
  128         return QModelIndex();
 
  130       return createIndex( row, column, pluginList[row] );
 
  133     QVariant data( 
const QModelIndex &index, 
int role = Qt::DisplayRole )
 const 
  135       if ( !index.isValid() || !index.internalPointer() ) {
 
  139       if ( role == Qt::DisplayRole ) {
 
  140         if ( !mNavigator->showText() ) {
 
  143         return static_cast<KontactInterface::Plugin*
>( index.internalPointer() )->title();
 
  144       } 
else if ( role == Qt::DecorationRole ) {
 
  145         if ( !mNavigator->showIcons() ) {
 
  148         return KIcon( static_cast<KontactInterface::Plugin*>( index.internalPointer() )->icon() );
 
  149       } 
else if ( role == Qt::TextAlignmentRole ) {
 
  150         return Qt::AlignCenter;
 
  151       } 
else if ( role == Qt::ToolTipRole ) {
 
  152         if ( !mNavigator->showText() ) {
 
  153           return static_cast<KontactInterface::Plugin*
>( index.internalPointer() )->title();
 
  156       } 
else if ( role == PluginName ) {
 
  157         return static_cast<KontactInterface::Plugin*
>( index.internalPointer() )->identifier();
 
  159       return QStringListModel::data( index, role );
 
  167 class SortFilterProxyModel
 
  168   : 
public QSortFilterProxyModel
 
  171     SortFilterProxyModel( 
QObject *parent = 0 ): QSortFilterProxyModel( parent )
 
  173       setDynamicSortFilter( 
true );
 
  177     bool lessThan( 
const QModelIndex &left, 
const QModelIndex &right )
 const 
  179       KontactInterface::Plugin *leftPlugin =
 
  180         static_cast<KontactInterface::Plugin*
>( left.internalPointer() );
 
  181       KontactInterface::Plugin *rightPlugin =
 
  182         static_cast<KontactInterface::Plugin*
>( right.internalPointer() );
 
  184       if ( leftPlugin->weight() == rightPlugin->weight() ) {
 
  185         return KStringHandler::naturalCompare( leftPlugin->title(), rightPlugin->title() ) < 0;
 
  188       return leftPlugin->weight() < rightPlugin->weight();
 
  195     Delegate( 
Navigator *parentNavigator = 0 )
 
  200     void paint( QPainter *painter, 
const QStyleOptionViewItem &option,
 
  201                 const QModelIndex &index )
 const 
  203       if ( !index.isValid() || !index.internalPointer() ) {
 
  207       QStyleOptionViewItemV4 optionCopy( *static_cast<const QStyleOptionViewItemV4*>( &option ) );
 
  208       optionCopy.decorationPosition = QStyleOptionViewItem::Top;
 
  209       optionCopy.decorationSize = QSize( mNavigator->iconSize(), mNavigator->iconSize() );
 
  210       optionCopy.textElideMode = Qt::ElideNone;
 
  211       QStyledItemDelegate::paint( painter, optionCopy, index );
 
  214     QSize sizeHint( 
const QStyleOptionViewItem &option, 
const QModelIndex &index )
 const 
  216       if ( !index.isValid() || !index.internalPointer() ) {
 
  220       QStyleOptionViewItemV4 optionCopy( *static_cast<const QStyleOptionViewItemV4*>( &option ) );
 
  221       optionCopy.decorationPosition = QStyleOptionViewItem::Top;
 
  222       optionCopy.decorationSize =
 
  223         mNavigator->showIcons() ? QSize( mNavigator->iconSize(), mNavigator->iconSize() ) : QSize();
 
  224       optionCopy.textElideMode = Qt::ElideNone;
 
  225       return QStyledItemDelegate::sizeHint( optionCopy, index );
 
  235   : 
QListView( parent ), mSidePane( parent )
 
  237   setViewport( 
new QWidget( 
this ) );
 
  239   setVerticalScrollMode( ScrollPerPixel );
 
  240   setHorizontalScrollMode( ScrollPerPixel );
 
  246   QActionGroup *viewMode = 
new QActionGroup( 
this );
 
  248   mShowIconsAction = 
new KAction( i18nc( 
"@action:inmenu", 
"Show Icons Only" ), 
this );
 
  249   mShowIconsAction->setCheckable( 
true );
 
  250   mShowIconsAction->setActionGroup( viewMode );
 
  251   mShowIconsAction->setChecked( !mShowText && mShowIcons );
 
  252   mShowIconsAction->setHelpText(
 
  253     i18nc( 
"@info:status",
 
  254            "Show sidebar items with icons and without text" ) );
 
  255   mShowIconsAction->setWhatsThis(
 
  256     i18nc( 
"@info:whatsthis",
 
  257            "Choose this option if you want the sidebar items to have icons without text." ) );
 
  258   connect( mShowIconsAction, SIGNAL(triggered(
bool)), 
this, SLOT(slotActionTriggered(
bool)) );
 
  260   mShowTextAction = 
new KAction( i18nc( 
"@action:inmenu", 
"Show Text Only" ), 
this );
 
  261   mShowTextAction->setCheckable( 
true );
 
  262   mShowTextAction->setActionGroup( viewMode );
 
  263   mShowTextAction->setChecked( mShowText && !mShowIcons );
 
  264   mShowTextAction->setHelpText(
 
  265     i18nc( 
"@info:status",
 
  266            "Show sidebar items with text and without icons" ) );
 
  267   mShowTextAction->setWhatsThis(
 
  268     i18nc( 
"@info:whatsthis",
 
  269            "Choose this option if you want the sidebar items to have text without icons." ) );
 
  270   connect( mShowTextAction, SIGNAL(triggered(
bool)), 
this, SLOT(slotActionTriggered(
bool)) );
 
  272   mShowBothAction = 
new KAction( i18nc( 
"@action:inmenu", 
"Show Icons && Text" ), 
this );
 
  273   mShowBothAction->setCheckable( 
true );
 
  274   mShowBothAction->setActionGroup( viewMode );
 
  275   mShowBothAction->setChecked( mShowText && mShowIcons );
 
  276   mShowBothAction->setHelpText(
 
  277     i18nc( 
"@info:status",
 
  278            "Show sidebar items with icons and text" ) );
 
  279   mShowBothAction->setWhatsThis(
 
  280     i18nc( 
"@info:whatsthis",
 
  281            "Choose this option if you want the sidebar items to have icons and text." ) );
 
  282   connect( mShowBothAction, SIGNAL(triggered(
bool)), 
this, SLOT(slotActionTriggered(
bool)) );
 
  284   KAction *sep = 
new KAction( 
this );
 
  285   sep->setSeparator( 
true );
 
  287   QActionGroup *
iconSize = 
new QActionGroup( 
this );
 
  289   mBigIconsAction = 
new KAction( i18nc( 
"@action:inmenu", 
"Big Icons" ), 
this );
 
  290   mBigIconsAction->setCheckable( iconSize );
 
  291   mBigIconsAction->setActionGroup( iconSize );
 
  292   mBigIconsAction->setChecked( mIconSize == KIconLoader::SizeLarge );
 
  293   mBigIconsAction->setHelpText(
 
  294     i18nc( 
"@info:status",
 
  295            "Show large size sidebar icons" ) );
 
  296   mBigIconsAction->setWhatsThis(
 
  297     i18nc( 
"@info:whatsthis",
 
  298            "Choose this option if you want the sidebar icons to be extra big." ) );
 
  299   connect( mBigIconsAction, SIGNAL(triggered(
bool)), 
this, SLOT(slotActionTriggered(
bool)) );
 
  301   mNormalIconsAction = 
new KAction( i18nc( 
"@action:inmenu", 
"Normal Icons" ), 
this );
 
  302   mNormalIconsAction->setCheckable( 
true );
 
  303   mNormalIconsAction->setActionGroup( iconSize );
 
  304   mNormalIconsAction->setChecked( mIconSize == KIconLoader::SizeMedium );
 
  305   mNormalIconsAction->setHelpText(
 
  306     i18nc( 
"@info:status",
 
  307            "Show normal size sidebar icons" ) );
 
  308   mNormalIconsAction->setWhatsThis(
 
  309     i18nc( 
"@info:whatsthis",
 
  310            "Choose this option if you want the sidebar icons to be normal size." ) );
 
  311   connect( mNormalIconsAction, SIGNAL(triggered(
bool)), 
this, SLOT(slotActionTriggered(
bool)) );
 
  313   mSmallIconsAction = 
new KAction( i18nc( 
"@action:inmenu", 
"Small Icons" ), 
this );
 
  314   mSmallIconsAction->setCheckable( 
true );
 
  315   mSmallIconsAction->setActionGroup( iconSize );
 
  316   mSmallIconsAction->setChecked( mIconSize == KIconLoader::SizeSmallMedium );
 
  317   mSmallIconsAction->setHelpText(
 
  318     i18nc( 
"@info:status",
 
  319            "Show small size sidebar icons" ) );
 
  320   mSmallIconsAction->setWhatsThis(
 
  321     i18nc( 
"@info:whatsthis",
 
  322            "Choose this option if you want the sidebar icons to be extra small." ) );
 
  323   connect( mSmallIconsAction, SIGNAL(triggered(
bool)), 
this, SLOT(slotActionTriggered(
bool)) );
 
  326   actionList << mShowIconsAction << mShowTextAction << mShowBothAction << sep
 
  327              << mBigIconsAction << mNormalIconsAction << mSmallIconsAction;
 
  329   insertActions( 0, actionList );
 
  331   setContextMenuPolicy( Qt::ActionsContextMenu );
 
  332   setViewMode( ListMode );
 
  333   setItemDelegate( 
new Delegate( 
this ) );
 
  334   mModel = 
new Model( 
this );
 
  335   SortFilterProxyModel *sortFilterProxyModel = 
new SortFilterProxyModel;
 
  336   sortFilterProxyModel->setSourceModel( mModel );
 
  337   setModel( sortFilterProxyModel );
 
  338   setSelectionModel( 
new SelectionModel( sortFilterProxyModel, 
this ) );
 
  340   setDragDropMode( DropOnly );
 
  341   viewport()->setAcceptDrops( 
true );
 
  342   setDropIndicatorShown( 
true );
 
  344   connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
 
  345            this, SLOT(slotCurrentChanged(QModelIndex)) );
 
  350   QString currentPlugin;
 
  351   if ( currentIndex().isValid() ) {
 
  352     currentPlugin = currentIndex().model()->data( currentIndex(), Model::PluginName ).toString();
 
  356   foreach ( KontactInterface::Plugin *plugin, plugins_ ) {
 
  357     if ( plugin->showInSideBar() ) {
 
  358       pluginsToShow << plugin;
 
  362   mModel->setPluginList( pluginsToShow );
 
  364   mModel->removeRows( 0, mModel->rowCount() );
 
  365   mModel->insertRows( 0, pluginsToShow.count() );
 
  368   if ( !currentPlugin.isEmpty() ) {
 
  375   const int numberOfRows( model()->rowCount() );
 
  376   for ( 
int i = 0; i < numberOfRows; ++i ) {
 
  377     const QModelIndex index = model()->index( i, 0 );
 
  378     const QString pluginName = model()->data( index, Model::PluginName ).toString();
 
  380     if ( plugin == pluginName ) {
 
  381       selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
 
  395   const int numberOfRows( model()->rowCount() );
 
  396   for ( 
int i = 0; i < numberOfRows; ++i ) {
 
  397     const QModelIndex index = model()->index( i, 0 );
 
  398     maxWidth = qMax( maxWidth, sizeHintForIndex( index ).width() );
 
  401   int viewHeight = QListView::sizeHint().height();
 
  403   return QSize( maxWidth + rect().width() - contentsRect().width(), viewHeight );
 
  408   if ( event->proposedAction() == Qt::IgnoreAction ) {
 
  411   event->acceptProposedAction();
 
  416   if ( event->proposedAction() == Qt::IgnoreAction ) {
 
  420   const QModelIndex dropIndex = indexAt( event->pos() );
 
  422   if ( !dropIndex.isValid() ||
 
  423        !( dropIndex.model()->flags( dropIndex ) & Qt::ItemIsEnabled ) ) {
 
  424     event->setAccepted( 
false );
 
  427     const QModelIndex sourceIndex =
 
  428       static_cast<const QSortFilterProxyModel*
>( model() )->mapToSource( dropIndex );
 
  429     KontactInterface::Plugin *plugin =
 
  430       static_cast<KontactInterface::Plugin*
>( sourceIndex.internalPointer() );
 
  431     if ( !plugin->canDecodeMimeData( event->mimeData() ) ) {
 
  432       event->setAccepted( 
false );
 
  437   event->acceptProposedAction();
 
  442   if ( event->proposedAction() == Qt::IgnoreAction ) {
 
  446   const QModelIndex dropIndex = indexAt( event->pos() );
 
  448   if ( !dropIndex.isValid() ) {
 
  451     const QModelIndex sourceIndex =
 
  452       static_cast<const QSortFilterProxyModel*
>( model() )->mapToSource( dropIndex );
 
  453     KontactInterface::Plugin *plugin =
 
  454       static_cast<KontactInterface::Plugin*
>( sourceIndex.internalPointer() );
 
  455     plugin->processDropEvent( event );
 
  461   parentWidget()->setMaximumWidth( 
sizeHint().width() );
 
  462   parentWidget()->setMinimumWidth( 
sizeHint().width() );
 
  464   QListView::showEvent( event );
 
  467 void Navigator::slotCurrentChanged( 
const QModelIndex ¤t )
 
  469   if ( !current.isValid() || !current.internalPointer() ||
 
  470        !( current.model()->flags( current ) & Qt::ItemIsEnabled ) ) {
 
  475     static_cast<const QSortFilterProxyModel*
>( current.model() )->mapToSource( current );
 
  477   emit 
pluginActivated( static_cast<KontactInterface::Plugin*>( source.internalPointer() ) );
 
  480 void Navigator::slotActionTriggered( 
bool checked )
 
  484   if ( 
object == mShowIconsAction ) {
 
  485     mShowIcons = checked;
 
  486     mShowText = !checked;
 
  487   } 
else if ( 
object == mShowTextAction ) {
 
  488     mShowIcons = !checked;
 
  490   } 
else if ( 
object == mShowBothAction ) {
 
  491     mShowIcons = checked;
 
  493   } 
else if ( 
object == mBigIconsAction ) {
 
  494     mIconSize = KIconLoader::SizeLarge;
 
  495   } 
else if ( 
object == mNormalIconsAction ) {
 
  496     mIconSize = KIconLoader::SizeMedium;
 
  497   } 
else if ( 
object == mSmallIconsAction ) {
 
  498     mIconSize = KIconLoader::SizeSmallMedium;
 
  507   QTimer::singleShot( 0, 
this, SLOT(updateNavigatorSize()) );
 
  510 void Navigator::updateNavigatorSize()
 
  512   parentWidget()->setMaximumWidth( 
sizeHint().width() );
 
  513   parentWidget()->setMinimumWidth( 
sizeHint().width() );
 
  520   mNavigator->setFocusPolicy( Qt::NoFocus );
 
  521   connect( mNavigator, SIGNAL(pluginActivated(KontactInterface::Plugin*)),
 
  542   setMaximumWidth( mNavigator->
sizeHint().width() );
 
  543   setMinimumWidth( mNavigator->
sizeHint().width() );
 
  546 #include "iconsidepane.moc" 
virtual void showEvent(QShowEvent *event)
 
IconSidePane(KontactInterface::Core *core, QWidget *parent)
 
void setCurrentPlugin(const QString &plugin)
 
virtual void dragMoveEvent(QDragMoveEvent *event)
 
static void setSidePaneIconSize(int v)
Set SidePaneIconSize. 
 
void pluginSelected(KontactInterface::Plugin *)
 
void resizeEvent(QResizeEvent *event)
 
static void setSidePaneShowText(bool v)
Set SidePaneShowText. 
 
void pluginActivated(KontactInterface::Plugin *plugin)
 
static bool sidePaneShowText()
Get SidePaneShowText. 
 
virtual void dropEvent(QDropEvent *event)
 
static int sidePaneIconSize()
Get SidePaneIconSize. 
 
void setCurrentPlugin(const QString &plugin)
 
virtual void updatePlugins()
 
virtual QSize sizeHint() const 
 
static void setSidePaneShowIcons(bool v)
Set SidePaneShowIcons. 
 
Navigator(SidePaneBase *parent=0)
 
static bool sidePaneShowIcons()
Get SidePaneShowIcons. 
 
void updatePlugins(QList< KontactInterface::Plugin * > plugins)
 
KontactInterface::Core * core() const 
 
virtual void dragEnterEvent(QDragEnterEvent *event)