00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
00193
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 ) {
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() ) {
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
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
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
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
00403 d->stack->removeWidget( d->defaultWidget );
00404 delete d->defaultWidget;
00405
00406
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
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"