diff --git a/src/kpagedialog.cpp b/src/kpagedialog.cpp index a5977c1..c424917 100644 --- a/src/kpagedialog.cpp +++ b/src/kpagedialog.cpp @@ -1,182 +1,181 @@ /* * 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 #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)); - //d_func()->mPageWidget->setFaceType(KPageView::Plain); } 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 0650c0f..dfed941 100644 --- a/src/kpagedialog_p.h +++ b/src/kpagedialog_p.h @@ -1,74 +1,72 @@ /* 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 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(); - q->setContentsMargins(0, 0, 0, 0); QVBoxLayout *layout = new QVBoxLayout; - layout->setContentsMargins(0, 0, 6, 0); q->setLayout(layout); 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); } } }; #endif // PAGED_KPAGEDIALOG_P_H diff --git a/src/kpageview.cpp b/src/kpageview.cpp index 91e8c17..48cd468 100644 --- a/src/kpageview.cpp +++ b/src/kpageview.cpp @@ -1,513 +1,505 @@ /* 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 #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); } } - view->setFrameShape(QFrame::NoFrame); - view->setContentsMargins(0, 0, 0, 0); - view->viewport()->setContentsMargins(0, 0, 0, 0); - view->setAutoFillBackground(true); - view->setBackgroundRole(QPalette::Base); - view->viewport()->setAutoFillBackground(true); - view->viewport()->setBackgroundRole(QPalette::Base); - if (faceType == KPageView::Tabbed) { stack->setVisible(false); layout->removeWidget(stack); } else { layout->addWidget(stack, 2, 1); stack->setVisible(true); } titleWidget->setVisible(q->showPageHeader()); 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); } else if (alignment & Qt::AlignBottom) { layout->addWidget(view, 4, 1); } else if (alignment & Qt::AlignLeft) { layout->addWidget(view, 1, 0, 2, 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); 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(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); } } 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(); } } 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"