diff --git a/src/kpagedialog.cpp b/src/kpagedialog.cpp index 55147d8..d3420d4 100644 --- a/src/kpagedialog.cpp +++ b/src/kpagedialog.cpp @@ -1,180 +1,186 @@ /* * This file is part of the KDE Libraries * Copyright (C) 1999-2001 Mirko Boehm (mirko@kde.org) and * Espen Sand (espen@kde.org) * Holger Freyther * 2005-2006 Olivier Goffart * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "kpagedialog.h" #include "kpagedialog_p.h" #include KPageDialog::KPageDialog(QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags), d_ptr(new KPageDialogPrivate(this)) { Q_D(KPageDialog); d->mPageWidget = new KPageWidget(this); d->mPageWidget->layout()->setContentsMargins(0, 0, 0, 0); d->mButtonBox = new QDialogButtonBox(this); d->mButtonBox->setObjectName(QStringLiteral("buttonbox")); d->mButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); d->init(); } KPageDialog::KPageDialog(KPageWidget *widget, QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags), d_ptr(new KPageDialogPrivate(this)) { Q_D(KPageDialog); Q_ASSERT(widget); widget->setParent(this); d->mPageWidget = widget; d->mButtonBox = new QDialogButtonBox(this); d->mButtonBox->setObjectName(QStringLiteral("buttonbox")); d->mButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); d->init(); } KPageDialog::KPageDialog(KPageDialogPrivate &dd, KPageWidget *widget, QWidget *parent, Qt::WindowFlags flags) : QDialog(parent, flags), d_ptr(&dd) { Q_D(KPageDialog); if (widget) { widget->setParent(this); d->mPageWidget = widget; } else { d->mPageWidget = new KPageWidget(this); } d->mButtonBox = new QDialogButtonBox(this); d->mButtonBox->setObjectName(QStringLiteral("buttonbox")); d->mButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); d->init(); } KPageDialog::~KPageDialog() { delete d_ptr; } void KPageDialog::setFaceType(FaceType faceType) { d_func()->mPageWidget->setFaceType(static_cast(faceType)); + + if (faceType == Tabbed) { + layout()->setContentsMargins(6, 6, 6, 6); + } else { + layout()->setContentsMargins(0, 0, 0, 0); + } } KPageWidgetItem *KPageDialog::addPage(QWidget *widget, const QString &name) { return d_func()->mPageWidget->addPage(widget, name); } void KPageDialog::addPage(KPageWidgetItem *item) { d_func()->mPageWidget->addPage(item); } KPageWidgetItem *KPageDialog::insertPage(KPageWidgetItem *before, QWidget *widget, const QString &name) { return d_func()->mPageWidget->insertPage(before, widget, name); } void KPageDialog::insertPage(KPageWidgetItem *before, KPageWidgetItem *item) { d_func()->mPageWidget->insertPage(before, item); } KPageWidgetItem *KPageDialog::addSubPage(KPageWidgetItem *parent, QWidget *widget, const QString &name) { return d_func()->mPageWidget->addSubPage(parent, widget, name); } void KPageDialog::addSubPage(KPageWidgetItem *parent, KPageWidgetItem *item) { d_func()->mPageWidget->addSubPage(parent, item); } void KPageDialog::removePage(KPageWidgetItem *item) { d_func()->mPageWidget->removePage(item); } void KPageDialog::setCurrentPage(KPageWidgetItem *item) { d_func()->mPageWidget->setCurrentPage(item); } KPageWidgetItem *KPageDialog::currentPage() const { return d_func()->mPageWidget->currentPage(); } void KPageDialog::setStandardButtons(QDialogButtonBox::StandardButtons buttons) { d_func()->mButtonBox->setStandardButtons(buttons); } QPushButton *KPageDialog::button(QDialogButtonBox::StandardButton which) const { return d_func()->mButtonBox->button(which); } void KPageDialog::addActionButton(QAbstractButton *button) { d_func()->mButtonBox->addButton(button, QDialogButtonBox::ActionRole); } KPageWidget *KPageDialog::pageWidget() { return d_func()->mPageWidget; } void KPageDialog::setPageWidget(KPageWidget *widget) { delete d_func()->mPageWidget; d_func()->mPageWidget = widget; d_func()->init(); } const KPageWidget *KPageDialog::pageWidget() const { return d_func()->mPageWidget; } QDialogButtonBox *KPageDialog::buttonBox() { return d_func()->mButtonBox; } const QDialogButtonBox *KPageDialog::buttonBox() const { return d_func()->mButtonBox; } void KPageDialog::setButtonBox(QDialogButtonBox *box) { delete d_func()->mButtonBox; d_func()->mButtonBox = box; d_func()->init(); } diff --git a/src/kpagedialog_p.h b/src/kpagedialog_p.h index dfed941..ca6aa4e 100644 --- a/src/kpagedialog_p.h +++ b/src/kpagedialog_p.h @@ -1,72 +1,78 @@ /* This file is part of the KDE project Copyright (C) 2007 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef PAGED_KPAGEDIALOG_P_H #define PAGED_KPAGEDIALOG_P_H #include "kpagedialog.h" #include #include +#include class KPageDialogPrivate { Q_DECLARE_PUBLIC(KPageDialog) protected: KPageDialogPrivate(KPageDialog *parent) : q_ptr(parent), mPageWidget(nullptr), mButtonBox(nullptr) { } virtual ~KPageDialogPrivate() { } KPageDialog *const q_ptr; KPageWidget *mPageWidget; QDialogButtonBox *mButtonBox; void init() { Q_Q(KPageDialog); delete q->layout(); QVBoxLayout *layout = new QVBoxLayout; q->setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); if (mPageWidget) { q->connect(mPageWidget, &KPageWidget::currentPageChanged, q, &KPageDialog::currentPageChanged); q->connect(mPageWidget, &KPageWidget::pageRemoved, q, &KPageDialog::pageRemoved); layout->addWidget(mPageWidget); } else { layout->addStretch(); } if (mButtonBox) { q->connect(mButtonBox, &QDialogButtonBox::accepted, q, &QDialog::accept); q->connect(mButtonBox, &QDialogButtonBox::rejected, q, &QDialog::reject); - layout->addWidget(mButtonBox); + if (mPageWidget) { + mPageWidget->setPageFooter(mButtonBox); + } else { + layout->addWidget(mButtonBox); + } } } }; #endif // PAGED_KPAGEDIALOG_P_H diff --git a/src/kpageview.cpp b/src/kpageview.cpp index e0a2c25..38defc3 100644 --- a/src/kpageview.cpp +++ b/src/kpageview.cpp @@ -1,503 +1,577 @@ /* This file is part of the KDE Libraries Copyright (C) 2006 Tobias Koenig (tokoe@kde.org) Copyright (C) 2007 Rafael Fernández López (ereslibre@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kpageview.h" #include "kpageview_p.h" #include "kpagemodel.h" #include "loggingcategory.h" #include #include #include #include #include void KPageViewPrivate::_k_rebuildGui() { // clean up old view Q_Q(KPageView); QModelIndex currentLastIndex; if (view && view->selectionModel()) { QObject::disconnect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), q, SLOT(_k_pageSelected(QItemSelection,QItemSelection))); currentLastIndex = view->selectionModel()->currentIndex(); } delete view; view = q->createView(); Q_ASSERT(view); view->setSelectionBehavior(QAbstractItemView::SelectItems); view->setSelectionMode(QAbstractItemView::SingleSelection); if (model) { view->setModel(model); } // setup new view if (view->selectionModel()) { QObject::connect(view->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), q, SLOT(_k_pageSelected(QItemSelection,QItemSelection))); if (currentLastIndex.isValid()) { view->selectionModel()->setCurrentIndex(currentLastIndex, QItemSelectionModel::Select); } else if (model) { view->selectionModel()->setCurrentIndex(model->index(0, 0), QItemSelectionModel::Select); } } if (faceType == KPageView::Tabbed) { stack->setVisible(false); layout->removeWidget(stack); } else { layout->addWidget(stack, 2, 1); stack->setVisible(true); } - titleWidget->setVisible(q->showPageHeader()); + layout->removeWidget(titleWidget); + + if (pageHeader) { + layout->removeWidget(pageHeader); + pageHeader->setVisible(q->showPageHeader()); + titleWidget->setVisible(false); + + if (faceType == KPageView::Tabbed) { + layout->addWidget(pageHeader, 1, 1); + } else { + layout->addWidget(pageHeader, 1, 1, 1, 2); + } + } else { + titleWidget->setVisible(q->showPageHeader()); + if (faceType == KPageView::Tabbed) { + layout->addWidget(titleWidget, 1, 1); + } else { + layout->addWidget(titleWidget, 1, 1, 1, 2); + } + } Qt::Alignment alignment = q->viewPosition(); if (alignment & Qt::AlignTop) { layout->addWidget(view, 2, 1); } else if (alignment & Qt::AlignRight) { - layout->addWidget(view, 1, 2, 2, 1); + layout->addWidget(view, 1, 2, 4, 1); } else if (alignment & Qt::AlignBottom) { layout->addWidget(view, 4, 1); } else if (alignment & Qt::AlignLeft) { - layout->addWidget(view, 1, 0, 2, 1); + layout->addWidget(view, 1, 0, 4, 1); } } void KPageViewPrivate::updateSelection() { /** * Select the first item in the view if not done yet. */ if (!model) { return; } if (!view || !view->selectionModel()) { return; } const QModelIndex index = view->selectionModel()->currentIndex(); if (!index.isValid()) { view->selectionModel()->setCurrentIndex(model->index(0, 0), QItemSelectionModel::Select); } } void KPageViewPrivate::cleanupPages() { /** * Remove all orphan pages from the stacked widget. */ const QList widgets = collectPages(); for (int i = 0; i < stack->count(); ++i) { QWidget *page = stack->widget(i); bool found = false; for (int j = 0; j < widgets.count(); ++j) { if (widgets[ j ] == page) { found = true; } } if (!found) { stack->removeWidget(page); } } } QList KPageViewPrivate::collectPages(const QModelIndex &parentIndex) { /** * Traverse through the model recursive and collect all widgets in * a list. */ QList retval; int rows = model->rowCount(parentIndex); for (int j = 0; j < rows; ++j) { const QModelIndex index = model->index(j, 0, parentIndex); retval.append(qvariant_cast(model->data(index, KPageModel::WidgetRole))); if (model->rowCount(index) > 0) { retval += collectPages(index); } } return retval; } KPageView::FaceType KPageViewPrivate::detectAutoFace() const { if (!model) { return KPageView::Plain; } /** * Check whether the model has sub pages. */ bool hasSubPages = false; const int count = model->rowCount(); for (int i = 0; i < count; ++i) { if (model->rowCount(model->index(i, 0)) > 0) { hasSubPages = true; break; } } if (hasSubPages) { return KPageView::Tree; } if (model->rowCount() > 1) { return KPageView::List; } return KPageView::Plain; } void KPageViewPrivate::_k_modelChanged() { if (!model) { return; } /** * If the face type is Auto, we rebuild the GUI whenever the layout * of the model changes. */ if (faceType == KPageView::Auto) { _k_rebuildGui(); // If you discover some crashes use the line below instead... //QTimer::singleShot(0, q, SLOT(_k_rebuildGui())); } /** * Set the stack to the minimum size of the largest widget. */ QSize size = stack->size(); const QList widgets = collectPages(); for (int i = 0; i < widgets.count(); ++i) { const QWidget *widget = widgets[ i ]; if (widget) { size = size.expandedTo(widget->minimumSizeHint()); } } stack->setMinimumSize(size); updateSelection(); } void KPageViewPrivate::_k_pageSelected(const QItemSelection &index, const QItemSelection &previous) { if (!model) { return; } // Return if the current Index is not valid if (index.indexes().size() != 1) { return; } QModelIndex currentIndex = index.indexes().first(); QModelIndex previousIndex; // The previous index can be invalid if (previous.indexes().size() == 1) { previousIndex = previous.indexes().first(); } if (faceType != KPageView::Tabbed) { QWidget *widget = qvariant_cast(model->data(currentIndex, KPageModel::WidgetRole)); if (widget) { if (stack->indexOf(widget) == -1) { // not included yet stack->addWidget(widget); } stack->setCurrentWidget(widget); } else { stack->setCurrentWidget(defaultWidget); } updateTitleWidget(currentIndex); } Q_Q(KPageView); emit q->currentPageChanged(currentIndex, previousIndex); } void KPageViewPrivate::updateTitleWidget(const QModelIndex &index) { Q_Q(KPageView); const bool headerVisible = model->data(index, KPageModel::HeaderVisibleRole).toBool(); if (!headerVisible) { titleWidget->setVisible(false); return; } QString header = model->data(index, KPageModel::HeaderRole).toString(); if (header.isNull()) { //TODO KDE5 remove that ugly logic, see also doxy-comments in KPageWidgetItem::setHeader() header = model->data(index, Qt::DisplayRole).toString(); } titleWidget->setText(header); titleWidget->setVisible(q->showPageHeader()); } void KPageViewPrivate::_k_dataChanged(const QModelIndex &, const QModelIndex &) { /** * When data has changed we update the header and icon for the currently selected * page. */ if (!view) { return; } QModelIndex index = view->selectionModel()->currentIndex(); if (!index.isValid()) { return; } updateTitleWidget(index); } KPageViewPrivate::KPageViewPrivate(KPageView *_parent) : q_ptr(_parent), model(nullptr), faceType(KPageView::Auto), layout(nullptr), stack(nullptr), titleWidget(nullptr), view(nullptr) { } void KPageViewPrivate::init() { Q_Q(KPageView); layout = new QGridLayout(q); + layout->setContentsMargins(0, 0, 0, 0); stack = new KPageStackedWidget(q); titleWidget = new KTitleWidget(q); QPixmap emptyPixmap(22, 22); emptyPixmap.fill(Qt::transparent); titleWidget->setPixmap(emptyPixmap); - layout->addWidget(titleWidget, 1, 1); + layout->addWidget(titleWidget, 1, 1, 1, 2); layout->addWidget(stack, 2, 1); defaultWidget = new QWidget(q); stack->addWidget(defaultWidget); // stack should use most space layout->setColumnStretch(1, 1); layout->setRowStretch(2, 1); } /** * KPageView Implementation */ KPageView::KPageView(QWidget *parent) : QWidget(parent), d_ptr(new KPageViewPrivate(this)) { d_ptr->init(); } KPageView::KPageView(KPageViewPrivate &dd, QWidget *parent) : QWidget(parent), d_ptr(&dd) { d_ptr->init(); } KPageView::~KPageView() { delete d_ptr; } void KPageView::setModel(QAbstractItemModel *model) { Q_D(KPageView); // clean up old model if (d->model) { disconnect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged())); disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(_k_dataChanged(QModelIndex,QModelIndex))); } d->model = model; if (d->model) { connect(d->model, SIGNAL(layoutChanged()), this, SLOT(_k_modelChanged())); connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(_k_dataChanged(QModelIndex,QModelIndex))); // set new model in navigation view if (d->view) { d->view->setModel(model); } } d->_k_rebuildGui(); } QAbstractItemModel *KPageView::model() const { return d_func()->model; } void KPageView::setFaceType(FaceType faceType) { Q_D(KPageView); d->faceType = faceType; d->_k_rebuildGui(); } KPageView::FaceType KPageView::faceType() const { return d_func()->faceType; } void KPageView::setCurrentPage(const QModelIndex &index) { Q_D(KPageView); if (!d->view || !d->view->selectionModel()) { return; } d->view->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent); } QModelIndex KPageView::currentPage() const { Q_D(const KPageView); if (!d->view || !d->view->selectionModel()) { return QModelIndex(); } return d->view->selectionModel()->currentIndex(); } void KPageView::setItemDelegate(QAbstractItemDelegate *delegate) { Q_D(KPageView); if (d->view) { d->view->setItemDelegate(delegate); } } QAbstractItemDelegate *KPageView::itemDelegate() const { Q_D(const KPageView); if (d->view) { return d->view->itemDelegate(); } else { return nullptr; } } void KPageView::setDefaultWidget(QWidget *widget) { Q_D(KPageView); Q_ASSERT(widget); bool isCurrent = (d->stack->currentIndex() == d->stack->indexOf(d->defaultWidget)); // remove old default widget d->stack->removeWidget(d->defaultWidget); delete d->defaultWidget; // add new default widget d->defaultWidget = widget; d->stack->addWidget(d->defaultWidget); if (isCurrent) { d->stack->setCurrentWidget(d->defaultWidget); } } +void KPageView::setPageHeader(QWidget *header) +{ + Q_D(KPageView); + if (d->pageHeader == header) { + return; + } + + if (d->pageHeader) { + d->layout->removeWidget(d->pageHeader); + } + d->layout->removeWidget(d->titleWidget); + + d->pageHeader = header; + + // Give it a colSpan of 2 to add a margin to the right + if (d->pageHeader) { + d->layout->addWidget(d->pageHeader, 1, 1, 1, 2); + d->pageHeader->setVisible(showPageHeader()); + } else { + d->layout->addWidget(d->titleWidget, 1, 1, 1, 2); + d->titleWidget->setVisible(showPageHeader()); + } +} + +QWidget *KPageView::pageHeader() const +{ + Q_D(const KPageView); + return d->pageHeader; +} + +void KPageView::setPageFooter(QWidget *footer) +{ + Q_D(KPageView); + if (d->pageFooter == footer) { + return; + } + + if (d->pageFooter) { + d->layout->removeWidget(d->pageFooter); + } + + d->pageFooter = footer; + + if (footer) { + d->layout->addWidget(d->pageFooter, 3, 1); + } +} + +QWidget *KPageView::pageFooter() const +{ + Q_D(const KPageView); + return d->pageFooter; +} + QAbstractItemView *KPageView::createView() { Q_D(KPageView); if (d->faceType == Auto) { const FaceType faceType = d->detectAutoFace(); if (faceType == Plain) { return new KDEPrivate::KPagePlainView(this); } else if (faceType == List) { return new KDEPrivate::KPageListView(this); } else if (faceType == Tree) { return new KDEPrivate::KPageTreeView(this); } else { // should never happen return nullptr; } } else if (d->faceType == Plain) { return new KDEPrivate::KPagePlainView(this); } else if (d->faceType == List) { return new KDEPrivate::KPageListView(this); } else if (d->faceType == Tree) { return new KDEPrivate::KPageTreeView(this); } else if (d->faceType == Tabbed) { return new KDEPrivate::KPageTabbedView(this); } else { return nullptr; } } bool KPageView::showPageHeader() const { Q_D(const KPageView); FaceType faceType = d->faceType; if (faceType == Auto) { faceType = d->detectAutoFace(); } if (faceType == Tabbed) { return false; } else { - return !d->titleWidget->text().isEmpty(); + return d->pageHeader || !d->titleWidget->text().isEmpty(); } } Qt::Alignment KPageView::viewPosition() const { Q_D(const KPageView); FaceType faceType = d->faceType; if (faceType == Auto) { faceType = d->detectAutoFace(); } if (faceType == Plain || faceType == Tabbed) { return Qt::AlignTop; } else { return Qt::AlignLeft; } } #include "moc_kpageview.cpp" diff --git a/src/kpageview.h b/src/kpageview.h index baad8bf..8644078 100644 --- a/src/kpageview.h +++ b/src/kpageview.h @@ -1,206 +1,231 @@ /* This file is part of the KDE Libraries Copyright (C) 2006 Tobias Koenig (tokoe@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPAGEVIEW_H #define KPAGEVIEW_H #include #include class KPageModel; class QAbstractItemDelegate; class QAbstractItemView; class QModelIndex; class KPageViewPrivate; class QAbstractItemModel; /** * @class KPageView kpageview.h KPageView * * @short A base class which can handle multiple pages. * * This class provides a widget base class which handles multiple * pages and allows the user to switch between these pages in * different ways. * * Currently, @p Auto, @p Plain, @p List, @p Tree and @p Tabbed face * types are available (cmp. KPageWidget). * * Example:\n * * \code * KPageModel *model = new MyPageModel(); * * KPageView *view = new KPageView( this ); * view->setModel( model ); * * view->setFaceType( KPageView::List ); * \endcode * * @author Tobias Koenig (tokoe@kde.org) */ class KWIDGETSADDONS_EXPORT KPageView : public QWidget { Q_OBJECT Q_PROPERTY(FaceType faceType READ faceType WRITE setFaceType) Q_DECLARE_PRIVATE(KPageView) public: /** * This enum is used to decide which type of navigation view * shall be used in the page view. */ enum FaceType { /** * Depending on the number of pages in the model, * the @c Plain (one page), the @c List (several pages) * or the @c Tree face (nested pages) will be used. * This is the default face type. */ Auto, /** * No navigation view will be visible and only the * first page of the model will be shown. */ Plain, /** * An icon list is used as navigation view */ List, /** * A tree list is used as navigation view */ Tree, /** * A tab widget is used as navigation view */ Tabbed }; Q_ENUM(FaceType) /** * Creates a page view with given parent. */ explicit KPageView(QWidget *parent = nullptr); /** * Destroys the page view. */ virtual ~KPageView(); /** * Sets the @p model of the page view. * * The model has to provide data for the roles defined in KPageModel::Role. */ void setModel(QAbstractItemModel *model); /** * Returns the model of the page view. */ QAbstractItemModel *model() const; /** * Sets the face type of the page view. */ void setFaceType(FaceType faceType); /** * Returns the face type of the page view. */ FaceType faceType() const; /** * Sets the page with @param index to be the current page and emits * the signal currentPageChanged. */ void setCurrentPage(const QModelIndex &index); /** * Returns the index for the current page or an invalid index * if no current page exists. */ QModelIndex currentPage() const; /** * Sets the item @param delegate which can be used customize * the page view. */ void setItemDelegate(QAbstractItemDelegate *delegate); /** * Returns the item delegate of the page view. */ QAbstractItemDelegate *itemDelegate() const; /** * Sets the @p widget which will be shown when a page is selected * that has no own widget set. */ void setDefaultWidget(QWidget *widget); + /** + * Set a widget as the header for this Page view + * It will replace the standard page title + * @since 5.60 + */ + void setPageHeader(QWidget *header); + + /** + * Widget of the header for this page view + * @since 5.60 + */ + QWidget *pageHeader() const; + + /** + * Set a widget as the footer for this Page view + * @since 5.60 + */ + void setPageFooter(QWidget *footer); + + /** + * Widget of the footer for this page view + * @since 5.60 + */ + QWidget *pageFooter() const; + Q_SIGNALS: /** * This signal is emitted whenever the current page changes. * The previous page index is replaced by the current index. */ void currentPageChanged(const QModelIndex ¤t, const QModelIndex &previous); protected: /** * Returns the navigation view, depending on the current * face type. * * This method can be reimplemented to provide custom * navigation views. */ virtual QAbstractItemView *createView(); /** * Returns whether the page header should be visible. * * This method can be reimplemented for adapting custom * views. */ virtual bool showPageHeader() const; /** * Returns the position where the navigation view should be * located according to the page stack. * * This method can be reimplemented for adapting custom * views. */ virtual Qt::Alignment viewPosition() const; KPageView(KPageViewPrivate &dd, QWidget *parent); KPageViewPrivate *const d_ptr; private: Q_PRIVATE_SLOT(d_func(), void _k_rebuildGui()) Q_PRIVATE_SLOT(d_func(), void _k_modelChanged()) Q_PRIVATE_SLOT(d_func(), void _k_pageSelected(const QItemSelection &, const QItemSelection &)) Q_PRIVATE_SLOT(d_func(), void _k_dataChanged(const QModelIndex &, const QModelIndex &)) }; #endif diff --git a/src/kpageview_p.h b/src/kpageview_p.h index 7ca8205..6dc5af9 100644 --- a/src/kpageview_p.h +++ b/src/kpageview_p.h @@ -1,245 +1,249 @@ /* This file is part of the KDE Libraries Copyright (C) 2006 Tobias Koenig (tokoe@kde.org) Copyright (C) 2007 Rafael Fernández López (ereslibre@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPAGEVIEW_P_H #define KPAGEVIEW_P_H #include "kpageview.h" #include #include #include #include #include #include #include +#include class KPageStackedWidget : public QStackedWidget { Q_OBJECT public: explicit KPageStackedWidget(QWidget *parent = nullptr) : QStackedWidget(parent) { } void setMinimumSize(const QSize &size) { mMinimumSize = size; } QSize minimumSizeHint() const override { return mMinimumSize.expandedTo(QStackedWidget::minimumSizeHint()); } private: QSize mMinimumSize; }; class KPageViewPrivate { Q_DECLARE_PUBLIC(KPageView) protected: KPageViewPrivate(KPageView *); KPageView *q_ptr; // data QAbstractItemModel *model; KPageView::FaceType faceType; // gui QGridLayout *layout; KPageStackedWidget *stack; KTitleWidget *titleWidget; QWidget *defaultWidget; QAbstractItemView *view; + QPointer pageHeader; + QPointer pageFooter; + void updateTitleWidget(const QModelIndex &index); void updateSelection(); void cleanupPages(); QList collectPages(const QModelIndex &parent = QModelIndex()); KPageView::FaceType detectAutoFace() const; // private slots void _k_rebuildGui(); void _k_modelChanged(); void _k_dataChanged(const QModelIndex &, const QModelIndex &); void _k_pageSelected(const QItemSelection &, const QItemSelection &); private: void init(); }; namespace KDEPrivate { class KPageListViewDelegate; class KPageListViewProxy; class KPagePlainView : public QAbstractItemView { Q_OBJECT public: explicit KPagePlainView(QWidget *parent = nullptr); QModelIndex indexAt(const QPoint &point) const override; void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override; QRect visualRect(const QModelIndex &index) const override; protected: QModelIndex moveCursor(QAbstractItemView::CursorAction, Qt::KeyboardModifiers) override; int horizontalOffset() const override; int verticalOffset() const override; bool isIndexHidden(const QModelIndex &) const override; void setSelection(const QRect &, QFlags) override; QRegion visualRegionForSelection(const QItemSelection &) const override; }; class KPageListView : public QListView { Q_OBJECT public: explicit KPageListView(QWidget *parent = nullptr); ~KPageListView() override; void setModel(QAbstractItemModel *model) override; protected: void changeEvent(QEvent *event) override; private Q_SLOTS: void updateWidth(); }; class KPageTreeView : public QTreeView { Q_OBJECT public: explicit KPageTreeView(QWidget *parent = nullptr); void setModel(QAbstractItemModel *model) override; private Q_SLOTS: void updateWidth(); private: void expandItems(const QModelIndex &index = QModelIndex()); }; class KPageTabbedView : public QAbstractItemView { Q_OBJECT public: explicit KPageTabbedView(QWidget *parent = nullptr); ~KPageTabbedView() override; void setModel(QAbstractItemModel *model) override; QModelIndex indexAt(const QPoint &point) const override; void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override; QRect visualRect(const QModelIndex &index) const override; QSize minimumSizeHint() const override; protected: QModelIndex moveCursor(QAbstractItemView::CursorAction, Qt::KeyboardModifiers) override; int horizontalOffset() const override; int verticalOffset() const override; bool isIndexHidden(const QModelIndex &) const override; void setSelection(const QRect &, QFlags) override; QRegion visualRegionForSelection(const QItemSelection &) const override; private Q_SLOTS: void currentPageChanged(int); void layoutChanged(); void dataChanged(const QModelIndex &, const QModelIndex &, const QVector &roles) override; private: QTabWidget *mTabWidget; }; class KPageListViewDelegate : public QAbstractItemDelegate { Q_OBJECT public: explicit KPageListViewDelegate(QObject *parent = nullptr); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; private: void drawFocus(QPainter *, const QStyleOptionViewItem &, const QRect &) const; }; /** * We need this proxy model to map the leaves of a tree-like model * to a one-level list model. */ class KPageListViewProxy : public QAbstractProxyModel { Q_OBJECT public: explicit KPageListViewProxy(QObject *parent = nullptr); ~KPageListViewProxy() override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &) const override; QVariant data(const QModelIndex &index, int role) const override; QModelIndex mapFromSource(const QModelIndex &index) const override; QModelIndex mapToSource(const QModelIndex &index) const override; public Q_SLOTS: void rebuildMap(); private: void addMapEntry(const QModelIndex &); QList mList; }; class SelectionModel : public QItemSelectionModel { Q_OBJECT public: SelectionModel(QAbstractItemModel *model, QObject *parent); public Q_SLOTS: void clear() override; void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) override; void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override; }; } #endif