• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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(selectionChanged(const QItemSelection &, const QItemSelection &)),
00047                 q, SLOT(_k_pageSelected(const QItemSelection &, const QItemSelection &)));
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(selectionChanged(const QItemSelection &, const QItemSelection &)), q, SLOT(_k_pageSelected(const QItemSelection &, const QItemSelection &)));
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 QItemSelection &index, const QItemSelection &previous)
00211 {
00212   if ( !model )
00213     return;
00214 
00215   // Return if the current Index is not valid
00216   if ( index.indexes().size() != 1 ) {
00217     return;
00218   }
00219   QModelIndex currentIndex = index.indexes().first();
00220 
00221   QModelIndex previousIndex;
00222   // The previous index can be invalid
00223   if ( previous.indexes().size() == 1 ) {
00224     previousIndex = previous.indexes().first();
00225   }
00226 
00227   if (faceType != KPageView::Tabbed) {
00228   QWidget *widget = qvariant_cast<QWidget*>( model->data( currentIndex, KPageModel::WidgetRole ) );
00229 
00230   if ( widget ) {
00231     if ( stack->indexOf( widget ) == -1 ) { // not included yet
00232       stack->addWidget( widget );
00233     }
00234 
00235     stack->setCurrentWidget( widget );
00236   } else {
00237     stack->setCurrentWidget( defaultWidget );
00238   }
00239 
00240   updateTitleWidget(currentIndex);
00241   }
00242 
00243   Q_Q(KPageView);
00244   emit q->currentPageChanged(currentIndex, previousIndex);
00245 }
00246 
00247 void KPageViewPrivate::updateTitleWidget(const QModelIndex& index)
00248 {
00249     Q_Q(KPageView);
00250 
00251     QString header = model->data( index, KPageModel::HeaderRole ).toString();
00252     if ( header.isNull() ) { //TODO KDE5 remove that ugly logic, see also doxy-comments in KPageWidgetItem::setHeader()
00253         header = model->data( index, Qt::DisplayRole ).toString();
00254     }
00255 
00256     const QIcon icon = model->data( index, Qt::DecorationRole ).value<QIcon>();
00257     titleWidget->setPixmap( icon.pixmap( 22, 22 ) );
00258     titleWidget->setText( header );
00259 
00260     titleWidget->setVisible(q->showPageHeader());
00261 }
00262 
00263 void KPageViewPrivate::_k_dataChanged(const QModelIndex &, const QModelIndex &)
00264 {
00269   if ( !view )
00270     return;
00271 
00272   QModelIndex index = view->selectionModel()->currentIndex();
00273   if ( !index.isValid() )
00274     return;
00275 
00276   updateTitleWidget( index );
00277 }
00278 
00279 KPageViewPrivate::KPageViewPrivate(KPageView *_parent)
00280     : q_ptr(_parent), model(0), faceType(KPageView::Auto),
00281     layout(0), stack(0), titleWidget(0), view(0)
00282 {
00283 }
00284 
00285 void KPageViewPrivate::init()
00286 {
00287     Q_Q(KPageView);
00288     layout = new QGridLayout(q);
00289     stack = new KPageStackedWidget(q);
00290     titleWidget = new KTitleWidget(q);
00291     QPixmap emptyPixmap(22, 22);
00292     emptyPixmap.fill(Qt::transparent);
00293     titleWidget->setPixmap(emptyPixmap);
00294     layout->addWidget(titleWidget, 1, 1);
00295     layout->addWidget(stack, 2, 1);
00296 
00297     defaultWidget = new QWidget(q);
00298     stack->addWidget(defaultWidget);
00299 
00300     // stack should use most space
00301     layout->setColumnStretch(1, 1);
00302     layout->setRowStretch(2, 1);
00303 }
00304 
00308 KPageView::KPageView( QWidget *parent )
00309     : QWidget(parent), d_ptr(new KPageViewPrivate(this))
00310 {
00311     d_ptr->init();
00312 }
00313 
00314 KPageView::KPageView(KPageViewPrivate &dd, QWidget *parent)
00315     : QWidget(parent), d_ptr(&dd)
00316 {
00317     d_ptr->init();
00318 }
00319 
00320 KPageView::~KPageView()
00321 {
00322     delete d_ptr;
00323 }
00324 
00325 void KPageView::setModel(QAbstractItemModel *model)
00326 {
00327     Q_D(KPageView);
00328   // clean up old model
00329   if ( d->model ) {
00330         disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
00331         disconnect(d->model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00332                 this, SLOT(_k_dataChanged(const QModelIndex &, const QModelIndex &)));
00333   }
00334 
00335   d->model = model;
00336 
00337   if ( d->model ) {
00338         connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
00339         connect(d->model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00340                 this, SLOT(_k_dataChanged(const QModelIndex &, const QModelIndex &)));
00341 
00342     // set new model in navigation view
00343     if ( d->view )
00344       d->view->setModel( model );
00345   }
00346 
00347     d->_k_rebuildGui();
00348 }
00349 
00350 QAbstractItemModel* KPageView::model() const
00351 {
00352     return d_func()->model;
00353 }
00354 
00355 void KPageView::setFaceType( FaceType faceType )
00356 {
00357     Q_D(KPageView);
00358   d->faceType = faceType;
00359 
00360     d->_k_rebuildGui();
00361 }
00362 
00363 KPageView::FaceType KPageView::faceType() const
00364 {
00365     return d_func()->faceType;
00366 }
00367 
00368 void KPageView::setCurrentPage( const QModelIndex &index )
00369 {
00370     Q_D(KPageView);
00371   if ( !d->view || !d->view->selectionModel() )
00372     return;
00373 
00374   d->view->selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
00375 }
00376 
00377 QModelIndex KPageView::currentPage() const
00378 {
00379     Q_D(const KPageView);
00380   if ( !d->view || !d->view->selectionModel() )
00381     return QModelIndex();
00382 
00383   return d->view->selectionModel()->currentIndex();
00384 }
00385 
00386 void KPageView::setItemDelegate( QAbstractItemDelegate *delegate )
00387 {
00388     Q_D(KPageView);
00389   if ( d->view )
00390     d->view->setItemDelegate( delegate );
00391 }
00392 
00393 QAbstractItemDelegate* KPageView::itemDelegate() const
00394 {
00395     Q_D(const KPageView);
00396   if ( d->view )
00397     return d->view->itemDelegate();
00398   else
00399     return 0;
00400 }
00401 
00402 void KPageView::setDefaultWidget( QWidget *widget )
00403 {
00404     Q_D(KPageView);
00405 
00406     Q_ASSERT(widget);
00407 
00408     bool isCurrent = (d->stack->currentIndex() == d->stack->indexOf( d->defaultWidget ));
00409 
00410     // remove old default widget
00411     d->stack->removeWidget( d->defaultWidget );
00412     delete d->defaultWidget;
00413 
00414     // add new default widget
00415     d->defaultWidget = widget;
00416     d->stack->addWidget(d->defaultWidget);
00417 
00418     if (isCurrent)
00419         d->stack->setCurrentWidget(d->defaultWidget);
00420 }
00421 
00422 QAbstractItemView* KPageView::createView()
00423 {
00424     Q_D(KPageView);
00425   if ( d->faceType == Auto ) {
00426     const FaceType faceType = d->detectAutoFace();
00427 
00428     if ( faceType == Plain )
00429       return new KDEPrivate::KPagePlainView( this );
00430     else if ( faceType == List )
00431       return new KDEPrivate::KPageListView( this );
00432     else if ( faceType == Tree )
00433       return new KDEPrivate::KPageTreeView( this );
00434     else // should never happen
00435       return 0;
00436   } else if ( d->faceType == Plain )
00437     return new KDEPrivate::KPagePlainView( this );
00438   else if ( d->faceType == List )
00439     return new KDEPrivate::KPageListView( this );
00440   else if ( d->faceType == Tree )
00441     return new KDEPrivate::KPageTreeView( this );
00442   else if ( d->faceType == Tabbed )
00443     return new KDEPrivate::KPageTabbedView( this );
00444   else
00445     return 0;
00446 }
00447 
00448 bool KPageView::showPageHeader() const
00449 {
00450     Q_D(const KPageView);
00451   FaceType faceType = d->faceType;
00452 
00453   if ( faceType == Auto )
00454     faceType = d->detectAutoFace();
00455 
00456   if ( faceType == Tabbed ) {
00457     return false;
00458   } else {
00459     return !d->titleWidget->text().isEmpty();
00460   }
00461 }
00462 
00463 Qt::Alignment KPageView::viewPosition() const
00464 {
00465     Q_D(const KPageView);
00466   FaceType faceType = d->faceType;
00467 
00468   if ( faceType == Auto )
00469     faceType = d->detectAutoFace();
00470 
00471   if ( faceType == Plain || faceType == Tabbed )
00472     return Qt::AlignTop;
00473   else
00474     return Qt::AlignLeft;
00475 }
00476 
00477 #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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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