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
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
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
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
00192
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 ) {
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() ) {
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
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
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
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
00402 d->stack->removeWidget( d->defaultWidget );
00403 delete d->defaultWidget;
00404
00405
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
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"