• Skip to content
  • Skip to link menu
KDE 4.2 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 
00032 #include <QAbstractItemView>
00033 #include <QGridLayout>
00034 #include <QLabel>
00035 #include <QSize>
00036 #include <QStackedWidget>
00037 #include <QTimer>
00038 
00039 void KPageViewPrivate::_k_rebuildGui()
00040 {
00041   // clean up old view
00042     Q_Q(KPageView);
00043 
00044   QModelIndex currentLastIndex;
00045   if ( view && view->selectionModel() ) {
00046         QObject::disconnect(view->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
00047                 q, SLOT(_k_pageSelected(const QModelIndex &, const QModelIndex &)));
00048         currentLastIndex = view->selectionModel()->currentIndex();
00049   }
00050 
00051   delete view;
00052     view = q->createView();
00053 
00054   Q_ASSERT( view );
00055 
00056   view->setSelectionBehavior( QAbstractItemView::SelectItems );
00057   view->setSelectionMode( QAbstractItemView::SingleSelection );
00058 
00059   if ( model ) {
00060     view->setModel( model );
00061   }
00062 
00063   // setup new view
00064   if ( view->selectionModel() ) {
00065     QObject::connect(view->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), q, SLOT(_k_pageSelected(const QModelIndex &, const QModelIndex &)));
00066 
00067     if ( currentLastIndex.isValid() )
00068       view->selectionModel()->setCurrentIndex( currentLastIndex, QItemSelectionModel::Select );
00069     else if ( model )
00070       view->selectionModel()->setCurrentIndex( model->index( 0, 0 ), QItemSelectionModel::Select );
00071   }
00072 
00073   if (faceType == KPageView::Tabbed) {
00074     stack->setVisible(false);
00075     layout->removeWidget( stack );
00076   } else {
00077     layout->addWidget( stack, 2, 1 );
00078     stack->setVisible(true);
00079   }
00080 
00081     titleWidget->setVisible(q->showPageHeader());
00082 
00083     Qt::Alignment alignment = q->viewPosition();
00084   if ( alignment & Qt::AlignTop )
00085     layout->addWidget( view, 2, 1 );
00086   else if ( alignment & Qt::AlignRight )
00087     layout->addWidget( view, 1, 2, 2, 1 );
00088   else if ( alignment & Qt::AlignBottom )
00089     layout->addWidget( view, 4, 1 );
00090   else if ( alignment & Qt::AlignLeft )
00091     layout->addWidget( view, 1, 0, 2, 1 );
00092 }
00093 
00094 void KPageViewPrivate::updateSelection()
00095 {
00100   if ( !model )
00101     return;
00102 
00103   if ( !view || !view->selectionModel() )
00104     return;
00105 
00106   const QModelIndex index = view->selectionModel()->currentIndex();
00107   if ( !index.isValid() )
00108     view->selectionModel()->setCurrentIndex( model->index( 0, 0 ), QItemSelectionModel::Select );
00109 }
00110 
00111 void KPageViewPrivate::cleanupPages()
00112 {
00117   const QList<QWidget*> widgets = collectPages();
00118 
00119   for ( int i = 0; i < stack->count(); ++i ) {
00120     QWidget *page = stack->widget( i );
00121 
00122     bool found = false;
00123     for ( int j = 0; j < widgets.count(); ++j ) {
00124       if ( widgets[ j ] == page )
00125         found = true;
00126     }
00127 
00128     if ( !found )
00129       stack->removeWidget( page );
00130   }
00131 }
00132 
00133 QList<QWidget *> KPageViewPrivate::collectPages(const QModelIndex &parentIndex)
00134 {
00139   QList<QWidget*> retval;
00140 
00141   int rows = model->rowCount( parentIndex );
00142   for ( int j = 0; j < rows; ++j ) {
00143     const QModelIndex index = model->index( j, 0, parentIndex );
00144     retval.append( qvariant_cast<QWidget*>( model->data( index, KPageModel::WidgetRole ) ) );
00145 
00146     if ( model->rowCount( index ) > 0 ) {
00147       retval += collectPages( index );
00148     }
00149   }
00150 
00151   return retval;
00152 }
00153 
00154 KPageView::FaceType KPageViewPrivate::detectAutoFace() const
00155 {
00156   if ( !model )
00157     return KPageView::Plain;
00158 
00162   bool hasSubPages = false;
00163   const int count = model->rowCount();
00164   for ( int i = 0; i < count; ++i ) {
00165     if ( model->rowCount( model->index( i, 0 ) ) > 0 ) {
00166       hasSubPages = true;
00167       break;
00168     }
00169   }
00170 
00171   if ( hasSubPages )
00172     return KPageView::Tree;
00173 
00174   if ( model->rowCount() > 1 )
00175     return KPageView::List;
00176 
00177   return KPageView::Plain;
00178 }
00179 
00180 void KPageViewPrivate::_k_modelChanged()
00181 {
00182   if ( !model )
00183     return;
00184 
00189     if (faceType == KPageView::Auto) {
00190         _k_rebuildGui();
00191         // If you discover some crashes use the line below instead...
00192         //QTimer::singleShot(0, q, SLOT(_k_rebuildGui()));
00193     }
00194 
00198   QSize size = stack->size();
00199   const QList<QWidget*> widgets = collectPages();
00200   for ( int i = 0; i < widgets.count(); ++i ) {
00201     const QWidget *widget = widgets[ i ];
00202     if ( widget )
00203       size = size.expandedTo( widget->minimumSizeHint() );
00204   }
00205   stack->setMinimumSize( size );
00206 
00207   updateSelection();
00208 }
00209 
00210 void KPageViewPrivate::_k_pageSelected(const QModelIndex &index, const QModelIndex &previous)
00211 {
00212   if ( !model )
00213     return;
00214 
00215   if ( !index.isValid() )
00216     return;
00217 
00218   if (faceType != KPageView::Tabbed) {
00219   QWidget *widget = qvariant_cast<QWidget*>( model->data( index, KPageModel::WidgetRole ) );
00220 
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     QString header = model->data( index, KPageModel::HeaderRole ).toString();
00243     if ( header.isNull() ) { //TODO KDE5 remove that ugly logic, see also doxy-comments in KPageWidgetItem::setHeader()
00244         header = model->data( index, Qt::DisplayRole ).toString();
00245     }
00246 
00247     titleWidget->setText( header );
00248 
00249     const QIcon icon = model->data( index, Qt::DecorationRole ).value<QIcon>();
00250     titleWidget->setPixmap( icon.pixmap( 22, 22 ) );
00251     titleWidget->setVisible(q->showPageHeader());
00252 }
00253 
00254 void KPageViewPrivate::_k_dataChanged(const QModelIndex &, const QModelIndex &)
00255 {
00260   if ( !view )
00261     return;
00262 
00263   QModelIndex index = view->selectionModel()->currentIndex();
00264   if ( !index.isValid() )
00265     return;
00266 
00267   updateTitleWidget( index );
00268 }
00269 
00270 KPageViewPrivate::KPageViewPrivate(KPageView *_parent)
00271     : q_ptr(_parent), model(0), faceType(KPageView::Auto),
00272     layout(0), stack(0), titleWidget(0), view(0)
00273 {
00274 }
00275 
00276 void KPageViewPrivate::init()
00277 {
00278     Q_Q(KPageView);
00279     layout = new QGridLayout(q);
00280     stack = new KPageStackedWidget(q);
00281     titleWidget = new KTitleWidget(q);
00282     QPixmap emptyPixmap(22, 22);
00283     emptyPixmap.fill(Qt::transparent);
00284     titleWidget->setPixmap(emptyPixmap);
00285     layout->addWidget(titleWidget, 1, 1);
00286     layout->addWidget(stack, 2, 1);
00287 
00288     defaultWidget = new QWidget(q);
00289     stack->addWidget(defaultWidget);
00290 
00291     // stack should use most space
00292     layout->setColumnStretch(1, 1);
00293     layout->setRowStretch(2, 1);
00294 }
00295 
00299 KPageView::KPageView( QWidget *parent )
00300     : QWidget(parent), d_ptr(new KPageViewPrivate(this))
00301 {
00302     d_ptr->init();
00303 }
00304 
00305 KPageView::KPageView(KPageViewPrivate &dd, QWidget *parent)
00306     : QWidget(parent), d_ptr(&dd)
00307 {
00308     d_ptr->init();
00309 }
00310 
00311 KPageView::~KPageView()
00312 {
00313     delete d_ptr;
00314 }
00315 
00316 void KPageView::setModel(QAbstractItemModel *model)
00317 {
00318     Q_D(KPageView);
00319   // clean up old model
00320   if ( d->model ) {
00321         disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
00322         disconnect(d->model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00323                 this, SLOT(_k_dataChanged(const QModelIndex &, const QModelIndex &)));
00324   }
00325 
00326   d->model = model;
00327 
00328   if ( d->model ) {
00329         connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
00330         connect(d->model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00331                 this, SLOT(_k_dataChanged(const QModelIndex &, const QModelIndex &)));
00332 
00333     // set new model in navigation view
00334     if ( d->view )
00335       d->view->setModel( model );
00336   }
00337 
00338     d->_k_rebuildGui();
00339 }
00340 
00341 QAbstractItemModel* KPageView::model() const
00342 {
00343     return d_func()->model;
00344 }
00345 
00346 void KPageView::setFaceType( FaceType faceType )
00347 {
00348     Q_D(KPageView);
00349   d->faceType = faceType;
00350 
00351     d->_k_rebuildGui();
00352 }
00353 
00354 KPageView::FaceType KPageView::faceType() const
00355 {
00356     return d_func()->faceType;
00357 }
00358 
00359 void KPageView::setCurrentPage( const QModelIndex &index )
00360 {
00361     Q_D(KPageView);
00362   if ( !d->view || !d->view->selectionModel() )
00363     return;
00364 
00365   d->view->selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
00366 }
00367 
00368 QModelIndex KPageView::currentPage() const
00369 {
00370     Q_D(const KPageView);
00371   if ( !d->view || !d->view->selectionModel() )
00372     return QModelIndex();
00373 
00374   return d->view->selectionModel()->currentIndex();
00375 }
00376 
00377 void KPageView::setItemDelegate( QAbstractItemDelegate *delegate )
00378 {
00379     Q_D(KPageView);
00380   if ( d->view )
00381     d->view->setItemDelegate( delegate );
00382 }
00383 
00384 QAbstractItemDelegate* KPageView::itemDelegate() const
00385 {
00386     Q_D(const KPageView);
00387   if ( d->view )
00388     return d->view->itemDelegate();
00389   else
00390     return 0;
00391 }
00392 
00393 void KPageView::setDefaultWidget( QWidget *widget )
00394 {
00395     Q_D(KPageView);
00396 
00397     Q_ASSERT(widget);
00398 
00399     bool isCurrent = (d->stack->currentIndex() == d->stack->indexOf( d->defaultWidget ));
00400 
00401     // remove old default widget
00402     d->stack->removeWidget( d->defaultWidget );
00403     delete d->defaultWidget;
00404 
00405     // add new default widget
00406     d->defaultWidget = widget;
00407     d->stack->addWidget(d->defaultWidget);
00408 
00409     if (isCurrent)
00410         d->stack->setCurrentWidget(d->defaultWidget);
00411 }
00412 
00413 QAbstractItemView* KPageView::createView()
00414 {
00415     Q_D(KPageView);
00416   if ( d->faceType == Auto ) {
00417     const FaceType faceType = d->detectAutoFace();
00418 
00419     if ( faceType == Plain )
00420       return new KDEPrivate::KPagePlainView( this );
00421     else if ( faceType == List )
00422       return new KDEPrivate::KPageListView( this );
00423     else if ( faceType == Tree )
00424       return new KDEPrivate::KPageTreeView( this );
00425     else // should never happen
00426       return 0;
00427   } else if ( d->faceType == Plain )
00428     return new KDEPrivate::KPagePlainView( this );
00429   else if ( d->faceType == List )
00430     return new KDEPrivate::KPageListView( this );
00431   else if ( d->faceType == Tree )
00432     return new KDEPrivate::KPageTreeView( this );
00433   else if ( d->faceType == Tabbed )
00434     return new KDEPrivate::KPageTabbedView( this );
00435   else
00436     return 0;
00437 }
00438 
00439 bool KPageView::showPageHeader() const
00440 {
00441     Q_D(const KPageView);
00442   FaceType faceType = d->faceType;
00443 
00444   if ( faceType == Auto )
00445     faceType = d->detectAutoFace();
00446 
00447   if ( faceType == Tabbed ) {
00448     return false;
00449   } else {
00450     return !d->titleWidget->text().isEmpty();
00451   }
00452 }
00453 
00454 Qt::Alignment KPageView::viewPosition() const
00455 {
00456     Q_D(const KPageView);
00457   FaceType faceType = d->faceType;
00458 
00459   if ( faceType == Auto )
00460     faceType = d->detectAutoFace();
00461 
00462   if ( faceType == Plain || faceType == Tabbed )
00463     return Qt::AlignTop;
00464   else
00465     return Qt::AlignLeft;
00466 }
00467 
00468 #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
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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