• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • paged
kpageview.cpp
Go to the documentation of this file.
1/*
2 This file is part of the KDE Libraries
3
4 Copyright (C) 2006 Tobias Koenig (tokoe@kde.org)
5 Copyright (C) 2007 Rafael Fernández López (ereslibre@kde.org)
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23#include "kpageview.h"
24#include "kpageview_p.h"
25
26#include "kpagemodel.h"
27
28#include <kdialog.h>
29#include <kiconloader.h>
30#include <ktitlewidget.h>
31
32#include <QAbstractItemView>
33#include <QGridLayout>
34#include <QLabel>
35#include <QSize>
36#include <QStackedWidget>
37#include <QTimer>
38
39void KPageViewPrivate::_k_rebuildGui()
40{
41 // clean up old view
42 Q_Q(KPageView);
43
44 QModelIndex currentLastIndex;
45 if ( view && view->selectionModel() ) {
46 QObject::disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
47 q, SLOT(_k_pageSelected(QItemSelection,QItemSelection)));
48 currentLastIndex = view->selectionModel()->currentIndex();
49 }
50
51 delete view;
52 view = q->createView();
53
54 Q_ASSERT( view );
55
56 view->setSelectionBehavior( QAbstractItemView::SelectItems );
57 view->setSelectionMode( QAbstractItemView::SingleSelection );
58
59 if ( model ) {
60 view->setModel( model );
61 }
62
63 // setup new view
64 if ( view->selectionModel() ) {
65 QObject::connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), q, SLOT(_k_pageSelected(QItemSelection,QItemSelection)));
66
67 if ( currentLastIndex.isValid() )
68 view->selectionModel()->setCurrentIndex( currentLastIndex, QItemSelectionModel::Select );
69 else if ( model )
70 view->selectionModel()->setCurrentIndex( model->index( 0, 0 ), QItemSelectionModel::Select );
71 }
72
73 if (faceType == KPageView::Tabbed) {
74 stack->setVisible(false);
75 layout->removeWidget( stack );
76 } else {
77 layout->addWidget( stack, 2, 1 );
78 stack->setVisible(true);
79 }
80
81 titleWidget->setVisible(q->showPageHeader());
82
83 Qt::Alignment alignment = q->viewPosition();
84 if ( alignment & Qt::AlignTop )
85 layout->addWidget( view, 2, 1 );
86 else if ( alignment & Qt::AlignRight )
87 layout->addWidget( view, 1, 2, 2, 1 );
88 else if ( alignment & Qt::AlignBottom )
89 layout->addWidget( view, 4, 1 );
90 else if ( alignment & Qt::AlignLeft )
91 layout->addWidget( view, 1, 0, 2, 1 );
92}
93
94void KPageViewPrivate::updateSelection()
95{
100 if ( !model )
101 return;
102
103 if ( !view || !view->selectionModel() )
104 return;
105
106 const QModelIndex index = view->selectionModel()->currentIndex();
107 if ( !index.isValid() )
108 view->selectionModel()->setCurrentIndex( model->index( 0, 0 ), QItemSelectionModel::Select );
109}
110
111void KPageViewPrivate::cleanupPages()
112{
117 const QList<QWidget*> widgets = collectPages();
118
119 for ( int i = 0; i < stack->count(); ++i ) {
120 QWidget *page = stack->widget( i );
121
122 bool found = false;
123 for ( int j = 0; j < widgets.count(); ++j ) {
124 if ( widgets[ j ] == page )
125 found = true;
126 }
127
128 if ( !found )
129 stack->removeWidget( page );
130 }
131}
132
133QList<QWidget *> KPageViewPrivate::collectPages(const QModelIndex &parentIndex)
134{
139 QList<QWidget*> retval;
140
141 int rows = model->rowCount( parentIndex );
142 for ( int j = 0; j < rows; ++j ) {
143 const QModelIndex index = model->index( j, 0, parentIndex );
144 retval.append( qvariant_cast<QWidget*>( model->data( index, KPageModel::WidgetRole ) ) );
145
146 if ( model->rowCount( index ) > 0 ) {
147 retval += collectPages( index );
148 }
149 }
150
151 return retval;
152}
153
154KPageView::FaceType KPageViewPrivate::detectAutoFace() const
155{
156 if ( !model )
157 return KPageView::Plain;
158
162 bool hasSubPages = false;
163 const int count = model->rowCount();
164 for ( int i = 0; i < count; ++i ) {
165 if ( model->rowCount( model->index( i, 0 ) ) > 0 ) {
166 hasSubPages = true;
167 break;
168 }
169 }
170
171 if ( hasSubPages )
172 return KPageView::Tree;
173
174 if ( model->rowCount() > 1 )
175 return KPageView::List;
176
177 return KPageView::Plain;
178}
179
180void KPageViewPrivate::_k_modelChanged()
181{
182 if ( !model )
183 return;
184
189 if (faceType == KPageView::Auto) {
190 _k_rebuildGui();
191 // If you discover some crashes use the line below instead...
192 //QTimer::singleShot(0, q, SLOT(_k_rebuildGui()));
193 }
194
198 QSize size = stack->size();
199 const QList<QWidget*> widgets = collectPages();
200 for ( int i = 0; i < widgets.count(); ++i ) {
201 const QWidget *widget = widgets[ i ];
202 if ( widget )
203 size = size.expandedTo( widget->minimumSizeHint() );
204 }
205 stack->setMinimumSize( size );
206
207 updateSelection();
208}
209
210void KPageViewPrivate::_k_pageSelected(const QItemSelection &index, const QItemSelection &previous)
211{
212 if ( !model )
213 return;
214
215 // Return if the current Index is not valid
216 if ( index.indexes().size() != 1 ) {
217 return;
218 }
219 QModelIndex currentIndex = index.indexes().first();
220
221 QModelIndex previousIndex;
222 // The previous index can be invalid
223 if ( previous.indexes().size() == 1 ) {
224 previousIndex = previous.indexes().first();
225 }
226
227 if (faceType != KPageView::Tabbed) {
228 QWidget *widget = qvariant_cast<QWidget*>( model->data( currentIndex, KPageModel::WidgetRole ) );
229
230 if ( widget ) {
231 if ( stack->indexOf( widget ) == -1 ) { // not included yet
232 stack->addWidget( widget );
233 }
234
235 stack->setCurrentWidget( widget );
236 } else {
237 stack->setCurrentWidget( defaultWidget );
238 }
239
240 updateTitleWidget(currentIndex);
241 }
242
243 Q_Q(KPageView);
244 emit q->currentPageChanged(currentIndex, previousIndex);
245}
246
247void KPageViewPrivate::updateTitleWidget(const QModelIndex& index)
248{
249 Q_Q(KPageView);
250
251 QString header = model->data( index, KPageModel::HeaderRole ).toString();
252 if ( header.isNull() ) { //TODO KDE5 remove that ugly logic, see also doxy-comments in KPageWidgetItem::setHeader()
253 header = model->data( index, Qt::DisplayRole ).toString();
254 }
255
256 const QIcon icon = model->data( index, Qt::DecorationRole ).value<QIcon>();
257 titleWidget->setPixmap( icon.pixmap( 22, 22 ) );
258 titleWidget->setText( header );
259
260 titleWidget->setVisible(q->showPageHeader());
261}
262
263void KPageViewPrivate::_k_dataChanged(const QModelIndex &, const QModelIndex &)
264{
269 if ( !view )
270 return;
271
272 QModelIndex index = view->selectionModel()->currentIndex();
273 if ( !index.isValid() )
274 return;
275
276 updateTitleWidget( index );
277}
278
279KPageViewPrivate::KPageViewPrivate(KPageView *_parent)
280 : q_ptr(_parent), model(0), faceType(KPageView::Auto),
281 layout(0), stack(0), titleWidget(0), view(0)
282{
283}
284
285void KPageViewPrivate::init()
286{
287 Q_Q(KPageView);
288 layout = new QGridLayout(q);
289 stack = new KPageStackedWidget(q);
290 titleWidget = new KTitleWidget(q);
291 QPixmap emptyPixmap(22, 22);
292 emptyPixmap.fill(Qt::transparent);
293 titleWidget->setPixmap(emptyPixmap);
294 layout->addWidget(titleWidget, 1, 1);
295 layout->addWidget(stack, 2, 1);
296
297 defaultWidget = new QWidget(q);
298 stack->addWidget(defaultWidget);
299
300 // stack should use most space
301 layout->setColumnStretch(1, 1);
302 layout->setRowStretch(2, 1);
303}
304
308KPageView::KPageView( QWidget *parent )
309 : QWidget(parent), d_ptr(new KPageViewPrivate(this))
310{
311 d_ptr->init();
312}
313
314KPageView::KPageView(KPageViewPrivate &dd, QWidget *parent)
315 : QWidget(parent), d_ptr(&dd)
316{
317 d_ptr->init();
318}
319
320KPageView::~KPageView()
321{
322 delete d_ptr;
323}
324
325void KPageView::setModel(QAbstractItemModel *model)
326{
327 Q_D(KPageView);
328 // clean up old model
329 if ( d->model ) {
330 disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
331 disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
332 this, SLOT(_k_dataChanged(QModelIndex,QModelIndex)));
333 }
334
335 d->model = model;
336
337 if ( d->model ) {
338 connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged()));
339 connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
340 this, SLOT(_k_dataChanged(QModelIndex,QModelIndex)));
341
342 // set new model in navigation view
343 if ( d->view )
344 d->view->setModel( model );
345 }
346
347 d->_k_rebuildGui();
348}
349
350QAbstractItemModel* KPageView::model() const
351{
352 return d_func()->model;
353}
354
355void KPageView::setFaceType( FaceType faceType )
356{
357 Q_D(KPageView);
358 d->faceType = faceType;
359
360 d->_k_rebuildGui();
361}
362
363KPageView::FaceType KPageView::faceType() const
364{
365 return d_func()->faceType;
366}
367
368void KPageView::setCurrentPage( const QModelIndex &index )
369{
370 Q_D(KPageView);
371 if ( !d->view || !d->view->selectionModel() )
372 return;
373
374 d->view->selectionModel()->setCurrentIndex( index, QItemSelectionModel::SelectCurrent );
375}
376
377QModelIndex KPageView::currentPage() const
378{
379 Q_D(const KPageView);
380 if ( !d->view || !d->view->selectionModel() )
381 return QModelIndex();
382
383 return d->view->selectionModel()->currentIndex();
384}
385
386void KPageView::setItemDelegate( QAbstractItemDelegate *delegate )
387{
388 Q_D(KPageView);
389 if ( d->view )
390 d->view->setItemDelegate( delegate );
391}
392
393QAbstractItemDelegate* KPageView::itemDelegate() const
394{
395 Q_D(const KPageView);
396 if ( d->view )
397 return d->view->itemDelegate();
398 else
399 return 0;
400}
401
402void KPageView::setDefaultWidget( QWidget *widget )
403{
404 Q_D(KPageView);
405
406 Q_ASSERT(widget);
407
408 bool isCurrent = (d->stack->currentIndex() == d->stack->indexOf( d->defaultWidget ));
409
410 // remove old default widget
411 d->stack->removeWidget( d->defaultWidget );
412 delete d->defaultWidget;
413
414 // add new default widget
415 d->defaultWidget = widget;
416 d->stack->addWidget(d->defaultWidget);
417
418 if (isCurrent)
419 d->stack->setCurrentWidget(d->defaultWidget);
420}
421
422QAbstractItemView* KPageView::createView()
423{
424 Q_D(KPageView);
425 if ( d->faceType == Auto ) {
426 const FaceType faceType = d->detectAutoFace();
427
428 if ( faceType == Plain )
429 return new KDEPrivate::KPagePlainView( this );
430 else if ( faceType == List )
431 return new KDEPrivate::KPageListView( this );
432 else if ( faceType == Tree )
433 return new KDEPrivate::KPageTreeView( this );
434 else // should never happen
435 return 0;
436 } else if ( d->faceType == Plain )
437 return new KDEPrivate::KPagePlainView( this );
438 else if ( d->faceType == List )
439 return new KDEPrivate::KPageListView( this );
440 else if ( d->faceType == Tree )
441 return new KDEPrivate::KPageTreeView( this );
442 else if ( d->faceType == Tabbed )
443 return new KDEPrivate::KPageTabbedView( this );
444 else
445 return 0;
446}
447
448bool KPageView::showPageHeader() const
449{
450 Q_D(const KPageView);
451 FaceType faceType = d->faceType;
452
453 if ( faceType == Auto )
454 faceType = d->detectAutoFace();
455
456 if ( faceType == Tabbed ) {
457 return false;
458 } else {
459 return !d->titleWidget->text().isEmpty();
460 }
461}
462
463Qt::Alignment KPageView::viewPosition() const
464{
465 Q_D(const KPageView);
466 FaceType faceType = d->faceType;
467
468 if ( faceType == Auto )
469 faceType = d->detectAutoFace();
470
471 if ( faceType == Plain || faceType == Tabbed )
472 return Qt::AlignTop;
473 else
474 return Qt::AlignLeft;
475}
476
477#include "kpageview.moc"
KPageModel::WidgetRole
@ WidgetRole
A pointer to the page widget.
Definition: kpagemodel.h:80
KPageModel::HeaderRole
@ HeaderRole
A string to be rendered as page header.
Definition: kpagemodel.h:69
KPageView
A base class which can handle multiple pages.
Definition: kpageview.h:61
KPageView::setCurrentPage
void setCurrentPage(const QModelIndex &index)
Sets the page with.
Definition: kpageview.cpp:368
KPageView::currentPage
QModelIndex currentPage() const
Returns the index for the current page or an invalid index if no current page exists.
Definition: kpageview.cpp:377
KPageView::createView
virtual QAbstractItemView * createView()
Returns the navigation view, depending on the current face type.
Definition: kpageview.cpp:422
KPageView::viewPosition
virtual Qt::Alignment viewPosition() const
Returns the position where the navigation view should be located according to the page stack.
Definition: kpageview.cpp:463
KPageView::setFaceType
void setFaceType(FaceType faceType)
Sets the face type of the page view.
Definition: kpageview.cpp:355
KPageView::~KPageView
virtual ~KPageView()
Destroys the page view.
Definition: kpageview.cpp:320
KPageView::setModel
void setModel(QAbstractItemModel *model)
Sets the model of the page view.
Definition: kpageview.cpp:325
KPageView::itemDelegate
QAbstractItemDelegate * itemDelegate() const
Returns the item delegate of the page view.
Definition: kpageview.cpp:393
KPageView::FaceType
FaceType
This enum is used to decide which type of navigation view shall be used in the page view.
Definition: kpageview.h:86
KPageView::List
@ List
Definition: kpageview.h:89
KPageView::Auto
@ Auto
Definition: kpageview.h:87
KPageView::Tree
@ Tree
Definition: kpageview.h:90
KPageView::Plain
@ Plain
Definition: kpageview.h:88
KPageView::Tabbed
@ Tabbed
Definition: kpageview.h:91
KPageView::showPageHeader
virtual bool showPageHeader() const
Returns whether the page header should be visible.
Definition: kpageview.cpp:448
KPageView::setDefaultWidget
void setDefaultWidget(QWidget *widget)
Sets the widget which will be shown when a page is selected that has no own widget set.
Definition: kpageview.cpp:402
KPageView::faceType
FaceType faceType
Definition: kpageview.h:64
KPageView::setItemDelegate
void setItemDelegate(QAbstractItemDelegate *delegate)
Sets the item.
Definition: kpageview.cpp:386
KPageView::model
QAbstractItemModel * model() const
Returns the model of the page view.
Definition: kpageview.cpp:350
KPageView::KPageView
KPageView(QWidget *parent=0)
Creates a page view with given parent.
Definition: kpageview.cpp:308
KPageView::d_ptr
KPageViewPrivate *const d_ptr
Definition: kpageview.h:190
KTitleWidget
Standard title widget with a white background and round border.
Definition: ktitlewidget.h:62
QAbstractItemModel
QList
QWidget
header
const char header[]
kdialog.h
kiconloader.h
kpagemodel.h
kpageview.h
ktitlewidget.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal