From 5179aed3a066dfc9885a75d36a0e64c48aa448f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Sun, 29 Jun 2014 19:59:08 +0200 Subject: Separate page dialog into a page container and a dialog. --- gui/pagedialog/PageDialog.cpp | 178 ++++----------------------------------- gui/pagedialog/PageDialog.h | 25 +----- gui/pagedialog/PageDialog_p.h | 106 ----------------------- gui/widgets/PageContainer.cpp | 190 ++++++++++++++++++++++++++++++++++++++++++ gui/widgets/PageContainer.h | 59 +++++++++++++ gui/widgets/PageContainer_p.h | 106 +++++++++++++++++++++++ 6 files changed, 375 insertions(+), 289 deletions(-) delete mode 100644 gui/pagedialog/PageDialog_p.h create mode 100644 gui/widgets/PageContainer.cpp create mode 100644 gui/widgets/PageContainer.h create mode 100644 gui/widgets/PageContainer_p.h (limited to 'gui') diff --git a/gui/pagedialog/PageDialog.cpp b/gui/pagedialog/PageDialog.cpp index 56bdfd14..07027a84 100644 --- a/gui/pagedialog/PageDialog.cpp +++ b/gui/pagedialog/PageDialog.cpp @@ -15,184 +15,42 @@ #include "PageDialog.h" #include "gui/Platform.h" -#include -#include -#include -#include #include "MultiMC.h" -#include -#include -#include -#include -#include -#include -#include #include -#include "PageDialog_p.h" #include - -class PageEntryFilterModel : public QSortFilterProxyModel -{ -public: - explicit PageEntryFilterModel(QObject *parent = 0) : QSortFilterProxyModel(parent) - { - } - -protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const - { - const QString pattern = filterRegExp().pattern(); - const auto model = static_cast(sourceModel()); - const auto page = model->pages().at(sourceRow); - if(!page->shouldDisplay()) - return false; - // Regular contents check, then check page-filter. - return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); - } -}; +#include +#include +#include +#include +#include PageDialog::PageDialog(BasePageProviderPtr pageProvider, QString defaultId, QWidget *parent) : QDialog(parent) { MultiMCPlatform::fixWM_CLASS(this); - createUI(); setWindowTitle(pageProvider->dialogTitle()); - restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray())); - - m_model = new PageModel(this); - m_proxyModel = new PageEntryFilterModel(this); - int firstIndex = -1; - int counter = 0; - auto pages = pageProvider->getPages(); - for(auto page: pages) - { - page->stackIndex = m_pageStack->addWidget(dynamic_cast(page)); - page->listIndex = counter; - counter++; - if(firstIndex == -1) - { - firstIndex = page->stackIndex; - } - } - m_model->setPages(pages); - - m_proxyModel->setSourceModel(m_model); - m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - - m_pageList->setIconSize(QSize(pageIconSize, pageIconSize)); - m_pageList->setSelectionMode(QAbstractItemView::SingleSelection); - m_pageList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); - m_pageList->setModel(m_proxyModel); - connect(m_pageList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), - this, SLOT(currentChanged(QModelIndex))); - m_pageStack->setStackingMode(QStackedLayout::StackOne); - m_pageList->setFocus(); - // now find what we want to have selected... - auto page = m_model->findPageEntryById(defaultId); - QModelIndex index; - if(page) - { - index = m_proxyModel->mapFromSource(m_model->index(page->listIndex)); - } - else - { - index = m_proxyModel->index(0,0); - } - if(index.isValid()) - m_pageList->setCurrentIndex(index); -} - -void PageDialog::createUI() -{ - m_pageStack = new QStackedLayout; - m_filter = new QLineEdit; - m_pageList = new PageView; - m_header = new QLabel(); - m_iconHeader = new IconLabel(this, QIcon(), QSize(24,24)); - - QFont headerLabelFont = m_header->font(); - headerLabelFont.setBold(true); - const int pointSize = headerLabelFont.pointSize(); - if (pointSize > 0) - headerLabelFont.setPointSize(pointSize + 2); - m_header->setFont(headerLabelFont); - - QHBoxLayout *headerHLayout = new QHBoxLayout; - const int leftMargin = MMC->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); - headerHLayout->addSpacerItem( - new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); - headerHLayout->addWidget(m_header); - headerHLayout->addSpacerItem( - new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); - headerHLayout->addWidget(m_iconHeader); - - m_pageStack->setMargin(0); - m_pageStack->addWidget(new QWidget(this)); - + m_container = new PageContainer(pageProvider, defaultId, this); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(m_container); + mainLayout->setSpacing(0); + mainLayout->setContentsMargins(0,0,0,0); + setLayout(mainLayout); + QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close); buttons->button(QDialogButtonBox::Close)->setDefault(true); - connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close())); - connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), this, SLOT(help())); + m_container->addButtons(buttons); - QGridLayout *mainGridLayout = new QGridLayout; - mainGridLayout->addLayout(headerHLayout, 0, 1, 1, 1); - mainGridLayout->addWidget(m_pageList, 0, 0, 2, 1); - mainGridLayout->addLayout(m_pageStack, 1, 1, 1, 1); - mainGridLayout->addWidget(buttons, 2, 0, 1, 2); - mainGridLayout->setColumnStretch(1, 4); - setLayout(mainGridLayout); -} - -void PageDialog::showPage(int row) -{ - if(row != -1) - { - m_currentPage = m_model->pages().at(row); - } - else - { - m_currentPage = nullptr; - } - if(m_currentPage) - { - m_pageStack->setCurrentIndex(m_currentPage->stackIndex); - m_header->setText(m_currentPage->displayName()); - m_iconHeader->setIcon(m_currentPage->icon()); - m_currentPage->opened(); - } - else - { - m_pageStack->setCurrentIndex(0); - m_header->setText(QString()); - m_iconHeader->setIcon(QIcon::fromTheme("bug")); - } -} - -void PageDialog::help() -{ - if(m_currentPage) - { - QString pageId = m_currentPage->helpPage(); - if(pageId.isEmpty()) - return; - QDesktopServices::openUrl(QUrl("https://github.com/MultiMC/MultiMC5/wiki/" + pageId)); - } -} + connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close())); + connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), m_container, SLOT(help())); -void PageDialog::currentChanged(const QModelIndex ¤t) -{ - showPage(current.isValid() ? m_proxyModel->mapToSource(current).row() : -1); + restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray())); } void PageDialog::closeEvent(QCloseEvent * event) { - bool accepted = true; - for(auto page: m_model->pages()) - { - accepted &= page->apply(); - } - if(accepted) + if(m_container->requestClose(event)) { MMC->settings()->set("PagedGeometry", saveGeometry().toBase64()); QDialog::closeEvent(event); diff --git a/gui/pagedialog/PageDialog.h b/gui/pagedialog/PageDialog.h index 88926ef1..097eac64 100644 --- a/gui/pagedialog/PageDialog.h +++ b/gui/pagedialog/PageDialog.h @@ -15,17 +15,9 @@ #pragma once #include -#include #include -class IconLabel; -class QSortFilterProxyModel; -class PageModel; -class QLabel; -class QListView; -class QLineEdit; -class QStackedLayout; - +class PageContainer; class PageDialog : public QDialog { Q_OBJECT @@ -34,23 +26,10 @@ public: QWidget *parent = 0); virtual ~PageDialog() {}; -private: - void createUI(); private slots: - void currentChanged(const QModelIndex ¤t); - void showPage(int row); - void help(); virtual void closeEvent(QCloseEvent *event); - private: - BasePage * m_currentPage; - QSortFilterProxyModel *m_proxyModel; - PageModel *m_model; - QStackedLayout *m_pageStack; - QLineEdit *m_filter; - QListView *m_pageList; - QLabel *m_header; - IconLabel *m_iconHeader; + PageContainer * m_container; }; diff --git a/gui/pagedialog/PageDialog_p.h b/gui/pagedialog/PageDialog_p.h deleted file mode 100644 index f10e8f2c..00000000 --- a/gui/pagedialog/PageDialog_p.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once -#include -#include -#include -#include - -class BasePage; -const int pageIconSize = 24; - -class PageViewDelegate : public QStyledItemDelegate -{ -public: - PageViewDelegate(QObject *parent) : QStyledItemDelegate(parent) - { - } - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const - { - QSize size = QStyledItemDelegate::sizeHint(option, index); - size.setHeight(qMax(size.height(), 32)); - return size; - } -}; - -class PageModel : public QAbstractListModel -{ -public: - PageModel(QObject *parent = 0) : QAbstractListModel(parent) - { - QPixmap empty(pageIconSize, pageIconSize); - empty.fill(Qt::transparent); - m_emptyIcon = QIcon(empty); - } - virtual ~PageModel() {}; - - int rowCount(const QModelIndex &parent = QModelIndex()) const - { - return parent.isValid() ? 0 : m_pages.size(); - } - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const - { - switch (role) - { - case Qt::DisplayRole: - return m_pages.at(index.row())->displayName(); - case Qt::DecorationRole: - { - QIcon icon = m_pages.at(index.row())->icon(); - if (icon.isNull()) - icon = m_emptyIcon; - return icon; - } - } - return QVariant(); - } - - void setPages(const QList &pages) - { - beginResetModel(); - m_pages = pages; - endResetModel(); - } - const QList &pages() const - { - return m_pages; - } - - BasePage * findPageEntryById(QString id) - { - for(auto page: m_pages) - { - if (page->id() == id) - return page; - } - return nullptr; - } - - QList m_pages; - QIcon m_emptyIcon; -}; - -class PageView : public QListView -{ -public: - PageView(QWidget *parent = 0) : QListView(parent) - { - setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); - setItemDelegate(new PageViewDelegate(this)); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - } - - virtual QSize sizeHint() const - { - int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; - if (verticalScrollBar()->isVisible()) - width += verticalScrollBar()->width(); - return QSize(width, 100); - } - - virtual bool eventFilter(QObject *obj, QEvent *event) - { - if (obj == verticalScrollBar() && - (event->type() == QEvent::Show || event->type() == QEvent::Hide)) - updateGeometry(); - return QListView::eventFilter(obj, event); - } -}; diff --git a/gui/widgets/PageContainer.cpp b/gui/widgets/PageContainer.cpp new file mode 100644 index 00000000..fd2a1e28 --- /dev/null +++ b/gui/widgets/PageContainer.cpp @@ -0,0 +1,190 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PageContainer.h" +#include "gui/Platform.h" +#include +#include +#include +#include +#include "MultiMC.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PageContainer_p.h" +#include + +class PageEntryFilterModel : public QSortFilterProxyModel +{ +public: + explicit PageEntryFilterModel(QObject *parent = 0) : QSortFilterProxyModel(parent) + { + } + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const + { + const QString pattern = filterRegExp().pattern(); + const auto model = static_cast(sourceModel()); + const auto page = model->pages().at(sourceRow); + if(!page->shouldDisplay()) + return false; + // Regular contents check, then check page-filter. + return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); + } +}; + +PageContainer::PageContainer(BasePageProviderPtr pageProvider, QString defaultId, QWidget *parent) : QWidget(parent) +{ + createUI(); + m_model = new PageModel(this); + m_proxyModel = new PageEntryFilterModel(this); + int firstIndex = -1; + int counter = 0; + auto pages = pageProvider->getPages(); + for(auto page: pages) + { + page->stackIndex = m_pageStack->addWidget(dynamic_cast(page)); + page->listIndex = counter; + counter++; + if(firstIndex == -1) + { + firstIndex = page->stackIndex; + } + } + m_model->setPages(pages); + + m_proxyModel->setSourceModel(m_model); + m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + + m_pageList->setIconSize(QSize(pageIconSize, pageIconSize)); + m_pageList->setSelectionMode(QAbstractItemView::SingleSelection); + m_pageList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + m_pageList->setModel(m_proxyModel); + connect(m_pageList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), + this, SLOT(currentChanged(QModelIndex))); + m_pageStack->setStackingMode(QStackedLayout::StackOne); + m_pageList->setFocus(); + // now find what we want to have selected... + auto page = m_model->findPageEntryById(defaultId); + QModelIndex index; + if(page) + { + index = m_proxyModel->mapFromSource(m_model->index(page->listIndex)); + } + else + { + index = m_proxyModel->index(0,0); + } + if(index.isValid()) + m_pageList->setCurrentIndex(index); +} + +void PageContainer::createUI() +{ + m_pageStack = new QStackedLayout; + m_filter = new QLineEdit; + m_pageList = new PageView; + m_header = new QLabel(); + m_iconHeader = new IconLabel(this, QIcon(), QSize(24,24)); + + QFont headerLabelFont = m_header->font(); + headerLabelFont.setBold(true); + const int pointSize = headerLabelFont.pointSize(); + if (pointSize > 0) + headerLabelFont.setPointSize(pointSize + 2); + m_header->setFont(headerLabelFont); + + QHBoxLayout *headerHLayout = new QHBoxLayout; + const int leftMargin = MMC->style()->pixelMetric(QStyle::PM_LayoutLeftMargin); + headerHLayout->addSpacerItem( + new QSpacerItem(leftMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); + headerHLayout->addWidget(m_header); + headerHLayout->addSpacerItem( + new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); + headerHLayout->addWidget(m_iconHeader); + + m_pageStack->setMargin(0); + m_pageStack->addWidget(new QWidget(this)); + + m_layout = new QGridLayout; + m_layout->addLayout(headerHLayout, 0, 1, 1, 1); + m_layout->addWidget(m_pageList, 0, 0, 2, 1); + m_layout->addLayout(m_pageStack, 1, 1, 1, 1); + m_layout->setColumnStretch(1, 4); + setLayout(m_layout); +} + +void PageContainer::addButtons(QWidget *buttons) +{ + m_layout->addWidget(buttons, 2, 0, 1, 2); +} + +void PageContainer::showPage(int row) +{ + if(row != -1) + { + m_currentPage = m_model->pages().at(row); + } + else + { + m_currentPage = nullptr; + } + if(m_currentPage) + { + m_pageStack->setCurrentIndex(m_currentPage->stackIndex); + m_header->setText(m_currentPage->displayName()); + m_iconHeader->setIcon(m_currentPage->icon()); + m_currentPage->opened(); + } + else + { + m_pageStack->setCurrentIndex(0); + m_header->setText(QString()); + m_iconHeader->setIcon(QIcon::fromTheme("bug")); + } +} + +void PageContainer::help() +{ + if(m_currentPage) + { + QString pageId = m_currentPage->helpPage(); + if(pageId.isEmpty()) + return; + QDesktopServices::openUrl(QUrl("https://github.com/MultiMC/MultiMC5/wiki/" + pageId)); + } +} + +void PageContainer::currentChanged(const QModelIndex ¤t) +{ + showPage(current.isValid() ? m_proxyModel->mapToSource(current).row() : -1); +} + +bool PageContainer::requestClose(QCloseEvent * event) +{ + for(auto page: m_model->pages()) + { + if(!page->apply()) + return false; + } + return true; +} diff --git a/gui/widgets/PageContainer.h b/gui/widgets/PageContainer.h new file mode 100644 index 00000000..d56c6bff --- /dev/null +++ b/gui/widgets/PageContainer.h @@ -0,0 +1,59 @@ +/* Copyright 2014 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once +#include +#include +#include + +class IconLabel; +class QSortFilterProxyModel; +class PageModel; +class QLabel; +class QListView; +class QLineEdit; +class QStackedLayout; +class QGridLayout; + +class PageContainer : public QWidget +{ + Q_OBJECT +public: + explicit PageContainer(BasePageProviderPtr pageProvider, QString defaultId = QString(), + QWidget *parent = 0); + virtual ~PageContainer() {}; + + void addButtons(QWidget * buttons); + bool requestClose(QCloseEvent *event); + +private: + void createUI(); +private +slots: + void currentChanged(const QModelIndex ¤t); + void showPage(int row); + void help(); + +private: + BasePage * m_currentPage; + QSortFilterProxyModel *m_proxyModel; + PageModel *m_model; + QStackedLayout *m_pageStack; + QLineEdit *m_filter; + QListView *m_pageList; + QLabel *m_header; + IconLabel *m_iconHeader; + QGridLayout *m_layout; +}; diff --git a/gui/widgets/PageContainer_p.h b/gui/widgets/PageContainer_p.h new file mode 100644 index 00000000..f10e8f2c --- /dev/null +++ b/gui/widgets/PageContainer_p.h @@ -0,0 +1,106 @@ +#pragma once +#include +#include +#include +#include + +class BasePage; +const int pageIconSize = 24; + +class PageViewDelegate : public QStyledItemDelegate +{ +public: + PageViewDelegate(QObject *parent) : QStyledItemDelegate(parent) + { + } + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const + { + QSize size = QStyledItemDelegate::sizeHint(option, index); + size.setHeight(qMax(size.height(), 32)); + return size; + } +}; + +class PageModel : public QAbstractListModel +{ +public: + PageModel(QObject *parent = 0) : QAbstractListModel(parent) + { + QPixmap empty(pageIconSize, pageIconSize); + empty.fill(Qt::transparent); + m_emptyIcon = QIcon(empty); + } + virtual ~PageModel() {}; + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + return parent.isValid() ? 0 : m_pages.size(); + } + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + switch (role) + { + case Qt::DisplayRole: + return m_pages.at(index.row())->displayName(); + case Qt::DecorationRole: + { + QIcon icon = m_pages.at(index.row())->icon(); + if (icon.isNull()) + icon = m_emptyIcon; + return icon; + } + } + return QVariant(); + } + + void setPages(const QList &pages) + { + beginResetModel(); + m_pages = pages; + endResetModel(); + } + const QList &pages() const + { + return m_pages; + } + + BasePage * findPageEntryById(QString id) + { + for(auto page: m_pages) + { + if (page->id() == id) + return page; + } + return nullptr; + } + + QList m_pages; + QIcon m_emptyIcon; +}; + +class PageView : public QListView +{ +public: + PageView(QWidget *parent = 0) : QListView(parent) + { + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + setItemDelegate(new PageViewDelegate(this)); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + } + + virtual QSize sizeHint() const + { + int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; + if (verticalScrollBar()->isVisible()) + width += verticalScrollBar()->width(); + return QSize(width, 100); + } + + virtual bool eventFilter(QObject *obj, QEvent *event) + { + if (obj == verticalScrollBar() && + (event->type() == QEvent::Show || event->type() == QEvent::Hide)) + updateGeometry(); + return QListView::eventFilter(obj, event); + } +}; -- cgit v1.2.3