• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kpageview.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of the KDE Libraries
00003 
00004     Copyright (C) 2006 Tobias Koenig (tokoe@kde.org)
00005     Copyright (C) 2007 Rafael Fernández López (ereslibre@kde.org)
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library 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 library 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     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB. 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 "kpageview.h"
00024 #include "kpageview_p.h"
00025 
00026 #include "kpagemodel.h"
00027 
00028 #include <kdialog.h>
00029 #include <kiconloader.h>
00030 #include <ktitlewidget.h>
00031 #include <kfadewidgeteffect.h>
00032 
00033 #include <QAbstractItemView>
00034 #include <QGridLayout>
00035 #include <QLabel>
00036 #include <QSize>
00037 #include <QStackedWidget>
00038 #include <QTimer>
00039 
00040 void KPageViewPrivate::_k_rebuildGui()
00041 {
00042   // clean up old view
00043     Q_Q(KPageView);
00044 
00045   QModelIndex currentLastIndex;
00046   if ( view && view->selectionModel() ) {
00047         QObject::disconnect(view->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
00048                 q, SLOT(_k_pageSelected(const QModelIndex &, const QModelIndex &)));
00049         currentLastIndex = view->selectionModel()->currentIndex();
00050   }
00051 
00052   delete view;
00053     view = q->createView();
00054 
00055   Q_ASSERT( view );
00056 
00057   view->setSelectionBehavior( QAbstractItemView::SelectItems );
00058   view->setSelectionMode( QAbstractItemView::SingleSelection );
00059 
00060   if ( model ) {
00061     view->setModel( model );
00062   }
00063 
00064   // setup new view
00065   if ( view->selectionModel() ) {
00066     QObject::connect(view->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), q, SLOT(_k_pageSelected(const QModelIndex &, const QModelIndex &)));
00067 
00068     if ( currentLastIndex.isValid() )
00069       view->selectionModel()->setCurrentIndex( currentLastIndex, QItemSelectionModel::Select );
00070     else if ( model )
00071       view->selectionModel()->setCurrentIndex( model->index( 0, 0 ), QItemSelectionModel::Select );
00072   }
00073 
00074   if (faceType == KPageView::Tabbed) {
00075     stack->setVisible(false);
00076     layout->removeWidget( stack );
00077   } else {
00078     layout->addWidget( stack, 2, 1 );
00079     stack->setVisible(true);
00080   }
00081 
00082     titleWidget->setVisible(q->showPageHeader());
00083 
00084     Qt::Alignment alignment = q->viewPosition();
00085   if ( alignment & Qt::AlignTop )
00086     layout->addWidget( view, 2, 1 );
00087   else if ( alignment & Qt::AlignRight )
00088     layout->addWidget( view, 1, 2, 2, 1 );
00089   else if ( alignment & Qt::AlignBottom )
00090     layout->addWidget( view, 4, 1 );
00091   else if ( alignment & Qt::AlignLeft )
00092     layout->addWidget( view, 1, 0, 2, 1 );
00093 }
00094 
00095 void KPageViewPrivate::updateSelection()
00096 {
00101   if ( !model )
00102     return;
00103 
00104   if ( !view || !view->selectionModel() )
00105     return;
00106 
00107   const QModelIndex index = view->selectionModel()->currentIndex();
00108   if ( !index.isValid() )
00109     view->selectionModel()->setCurrentIndex( model->index( 0, 0 ), QItemSelectionModel::Select );
00110 }
00111 
00112 void KPageViewPrivate::cleanupPages()
00113 {
00118   const QList<QWidget*> widgets = collectPages();
00119 
00120   for ( int i = 0; i < stack->count(); ++i ) {
00121     QWidget *page = stack->widget( i );
00122 
00123     bool found = false;
00124     for ( int j = 0; j < widgets.count(); ++j ) {
00125       if ( widgets[ j ] == page )
00126         found = true;
00127     }
00128 
00129     if ( !found )
00130       stack->removeWidget( page );
00131   }
00132 }
00133 
00134 QList<QWidget *> KPageViewPrivate::collectPages(const QModelIndex &parentIndex)
00135 {
00140   QList<QWidget*> retval;
00141 
00142   int rows = model->rowCount( parentIndex );
00143   for ( int j = 0; j < rows; ++j ) {
00144     const QModelIndex index = model->index( j, 0, parentIndex );
00145     retval.append( qvariant_cast<QWidget*>( model->data( index, KPageModel::WidgetRole ) ) );
00146 
00147     if ( model->rowCount( index ) > 0 ) {
00148       retval += collectPages( index );
00149     }
00150   }
00151 
00152   return retval;
00153 }
00154 
00155 KPageView::FaceType KPageViewPrivate::detectAutoFace() const
00156 {
00157   if ( !model )
00158     return KPageView::Plain;
00159 
00163   bool hasSubPages = false;
00164   const int count = model->rowCount();
00165   for ( int i = 0; i < count; ++i ) {
00166     if ( model->rowCount( model->index( i, 0 ) ) > 0 ) {
00167       hasSubPages = true;
00168       break;
00169     }
00170   }
00171 
00172   if ( hasSubPages )
00173     return KPageView::Tree;
00174 
00175   if ( model->rowCount() > 1 )
00176     return KPageView::List;
00177 
00178   return KPageView::Plain;
00179 }
00180 
00181 void KPageViewPrivate::_k_modelChanged()
00182 {
00183   if ( !model )
00184     return;
00185 
00190     if (faceType == KPageView::Auto) {
00191         _k_rebuildGui();
00192         // If you discover some crashes use the line below instead...
00193         //QTimer::singleShot(0, q, SLOT(_k_rebuildGui()));
00194     }
00195 
00199   QSize size = stack->size();
00200   const QList<QWidget*> widgets = collectPages();
00201   for ( int i = 0; i < widgets.count(); ++i ) {
00202     const QWidget *widget = widgets[ i ];
00203     if ( widget )
00204       size = size.expandedTo( widget->minimumSizeHint() );
00205   }
00206   stack->setMinimumSize( size );
00207 
00208   updateSelection();
00209 }
00210 
00211 void KPageViewPrivate::_k_pageSelected(const QModelIndex &index, const QModelIndex &previous)
00212 {
00213   if ( !model )
00214     return;
00215 
00216   if ( !index.isValid() )
00217     return;
00218 
00219   if (faceType != KPageView::Tabbed) {
00220   QWidget *widget = qvariant_cast<QWidget*>( model->data( index, KPageModel::WidgetRole ) );
00221   if ( widget ) {
00222     if ( stack->indexOf( widget ) == -1 ) { // not included yet
00223       stack->addWidget( widget );
00224     }
00225 
00226     stack->setCurrentWidget( widget );
00227   } else {
00228     stack->setCurrentWidget( defaultWidget );
00229   }
00230 
00231   updateTitleWidget(index);
00232   }
00233 
00234   Q_Q(KPageView);
00235   emit q->currentPageChanged(index, previous);
00236 }
00237 
00238 void KPageViewPrivate::updateTitleWidget(const QModelIndex& index)
00239 {
00240     Q_Q(KPageView);
00241 
00242     KFadeWidgetEffect *effect = new KFadeWidgetEffect( titleWidget );
00243 
00244     QString header = model->data( index, KPageModel::HeaderRole ).toString();
00245     if ( header.isNull() ) { //TODO KDE5 remove that ugly logic, see also doxy-comments in KPageWidgetItem::setHeader()
00246         header = model->data( index, Qt::DisplayRole ).toString();
00247     }
00248 
00249     titleWidget->setText( header );
00250 
00251     const QIcon icon = model->data( index, Qt::DecorationRole ).value<QIcon>();
00252     titleWidget->setPixmap( icon.pixmap( 22, 22 ) );
00253     titleWidget->setVisible(q->showPageHeader());
00254 
00255     effect->start();
00256 }
00257 
00258 void KPageViewPrivate::_k_dataChanged(const QModelIndex &, const QModelIndex &)
00259 {
00264   if ( !view )
00265     return;
00266 
00267   QModelIndex index = view->selectionModel()->currentIndex();
00268   if ( !index.isValid() )
00269     return;
00270 
00271   updateTitleWidget( index );
00272 }
00273 
00274 KPageViewPrivate::KPageViewPrivate(KPageView *_parent)
00275     : q_ptr(_parent), model(0), faceType(KPageView::Auto),
00276     layout(0), stack(0), titleWidget(0), view(0)
00277 {
00278 }
00279 
00280 void KPageViewPrivate::init()
00281 {
00282     Q_Q(KPageView);
00283     layout = new QGridLayout(q);
00284     stack = new KPageStackedWidget(q);
00285     titleWidget = new KTitleWidget(q);
00286     layout->addWidget(titleWidget, 1, 1);
00287     layout->addWidget(stack, 2, 1);
00288 
00289     defaultWidget = new QWidget(q);
00290     stack->addWidget(defaultWidget);
00291 
00292     // stack should use most space
00293     layout->setColumnStretch(1, 1);
00294     layout->setRowStretch(2, 1);
00295 }
00296 
00300 KPageView::KPageView( QWidget *parent )
00301     : QWidget(parent), d_ptr(new KPageViewPrivate(this))
00302 {
00303     d_ptr->init();
00304 }
00305 
00306 KPageView::KPageView(KPageViewPrivate &dd, QWidget *parent)
00307     : QWidget(parent), d_ptr(&dd)
00308 {
00309     d_ptr->init();
00310 }
00311 
00312 KPageView::~KPageView()
00313 {
00314     delete d_ptr;
00315 }
00316 
00317 void KPageView::setModel(QAbstractItemModel *model)
00318 {
00319     Q_D(KPageView);
00320   // clean up old model
00321   if ( d->model ) {
00322         disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
00323         disconnect(d->model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00324                 this, SLOT(_k_dataChanged(const QModelIndex &, const QModelIndex &)));
00325   }
00326 
00327   d->model = model;
00328 
00329   if ( d->model ) {
00330         connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
00331         connect(d->model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00332                 this, SLOT(_k_dataChanged(const QModelIndex &, const QModelIndex &)));
00333 
00334     // set new model in navigation view
00335     if ( d->view )
00336       d->view->setModel( model );
00337   }
00338 
00339     d->_k_rebuildGui();
00340 }
00341 
00342 QAbstractItemModel* KPageView::model() const
00343 {
00344     return d_func()->model;
00345 }
00346 
00347 void KPageView::setFaceType( FaceType faceType )
00348 {
00349     Q_D(KPageView);
00350   d->faceType = faceType;
00351 
00352     d->_k_rebuildGui();
00353 }
00354 
00355 KPageView::FaceType KPageView::faceType() const
00356 {
00357     return d_func()->faceType;
00358 }
00359 
00360 void KPageView::setCurrentPage( const QModelIndex &index )
00361 {
00362     Q_D(KPageView);
00363   if ( !d->view || !d->view->selectionModel() )
00364     return;
00365 
00366   d->view->selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
00367 }
00368 
00369 QModelIndex KPageView::currentPage() const
00370 {
00371     Q_D(const KPageView);
00372   if ( !d->view || !d->view->selectionModel() )
00373     return QModelIndex();
00374 
00375   return d->view->selectionModel()->currentIndex();
00376 }
00377 
00378 void KPageView::setItemDelegate( QAbstractItemDelegate *delegate )
00379 {
00380     Q_D(KPageView);
00381   if ( d->view )
00382     d->view->setItemDelegate( delegate );
00383 }
00384 
00385 QAbstractItemDelegate* KPageView::itemDelegate() const
00386 {
00387     Q_D(const KPageView);
00388   if ( d->view )
00389     return d->view->itemDelegate();
00390   else
00391     return 0;
00392 }
00393 
00394 void KPageView::setDefaultWidget( QWidget *widget )
00395 {
00396     Q_D(KPageView);
00397 
00398     Q_ASSERT(widget);
00399 
00400     bool isCurrent = (d->stack->currentIndex() == d->stack->indexOf( d->defaultWidget ));
00401 
00402     // remove old default widget
00403     d->stack->removeWidget( d->defaultWidget );
00404     delete d->defaultWidget;
00405 
00406     // add new default widget
00407     d->defaultWidget = widget;
00408     d->stack->addWidget(d->defaultWidget);
00409 
00410     if (isCurrent)
00411         d->stack->setCurrentWidget(d->defaultWidget);
00412 }
00413 
00414 QAbstractItemView* KPageView::createView()
00415 {
00416     Q_D(KPageView);
00417   if ( d->faceType == Auto ) {
00418     const FaceType faceType = d->detectAutoFace();
00419 
00420     if ( faceType == Plain )
00421       return new KDEPrivate::KPagePlainView( this );
00422     else if ( faceType == List )
00423       return new KDEPrivate::KPageListView( this );
00424     else if ( faceType == Tree )
00425       return new KDEPrivate::KPageTreeView( this );
00426     else // should never happen
00427       return 0;
00428   } else if ( d->faceType == Plain )
00429     return new KDEPrivate::KPagePlainView( this );
00430   else if ( d->faceType == List )
00431     return new KDEPrivate::KPageListView( this );
00432   else if ( d->faceType == Tree )
00433     return new KDEPrivate::KPageTreeView( this );
00434   else if ( d->faceType == Tabbed )
00435     return new KDEPrivate::KPageTabbedView( this );
00436   else
00437     return 0;
00438 }
00439 
00440 bool KPageView::showPageHeader() const
00441 {
00442     Q_D(const KPageView);
00443   FaceType faceType = d->faceType;
00444 
00445   if ( faceType == Auto )
00446     faceType = d->detectAutoFace();
00447 
00448   if ( faceType == Tabbed ) {
00449     return false;
00450   } else {
00451     return !d->titleWidget->text().isEmpty();
00452   }
00453 }
00454 
00455 Qt::Alignment KPageView::viewPosition() const
00456 {
00457     Q_D(const KPageView);
00458   FaceType faceType = d->faceType;
00459 
00460   if ( faceType == Auto )
00461     faceType = d->detectAutoFace();
00462 
00463   if ( faceType == Plain || faceType == Tabbed )
00464     return Qt::AlignTop;
00465   else
00466     return Qt::AlignLeft;
00467 }
00468 
00469 #include "kpageview.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs 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