summaryrefslogtreecommitdiffstats
path: root/gui/pagedialog
diff options
context:
space:
mode:
Diffstat (limited to 'gui/pagedialog')
-rw-r--r--gui/pagedialog/PageDialog.cpp154
-rw-r--r--gui/pagedialog/PageDialog.h50
-rw-r--r--gui/pagedialog/PageDialog_p.h106
3 files changed, 310 insertions, 0 deletions
diff --git a/gui/pagedialog/PageDialog.cpp b/gui/pagedialog/PageDialog.cpp
new file mode 100644
index 00000000..0dda7c1f
--- /dev/null
+++ b/gui/pagedialog/PageDialog.cpp
@@ -0,0 +1,154 @@
+/* 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 "PageDialog.h"
+#include "gui/Platform.h"
+#include <QStackedLayout>
+#include <QPushButton>
+#include <QSortFilterProxyModel>
+#include "MultiMC.h"
+#include <QStyledItemDelegate>
+#include <QListView>
+#include <QLineEdit>
+#include <QLabel>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+
+#include "PageDialog_p.h"
+#include <gui/widgets/IconLabel.h>
+
+class PageEntryFilterModel : public QSortFilterProxyModel
+{
+public:
+ explicit PageEntryFilterModel(QObject *parent = 0) : QSortFilterProxyModel(parent)
+ {
+ }
+
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+ {
+ // Regular contents check, then check page-filter.
+ if (QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent))
+ return true;
+
+ const QString pattern = filterRegExp().pattern();
+ const auto model = static_cast<PageModel *>(sourceModel());
+ const auto page = model->pages().at(sourceRow);
+ return page->shouldDisplay();
+ }
+};
+
+PageDialog::PageDialog(BasePageProviderPtr pageProvider, QWidget *parent) : QDialog(parent)
+{
+ MultiMCPlatform::fixWM_CLASS(this);
+ createUI();
+ setWindowTitle(pageProvider->dialogTitle());
+
+ m_model = new PageModel(this);
+ m_proxyModel = new PageEntryFilterModel(this);
+ int firstIndex = -1;
+ auto pages = pageProvider->getPages();
+ for(auto page: pages)
+ {
+ page->index = m_pageStack->addWidget(dynamic_cast<QWidget *>(page));
+ if(firstIndex == -1)
+ {
+ firstIndex = page->index;
+ }
+ }
+ 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();
+}
+
+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::fromTheme("bug"), 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));
+
+ QDialogButtonBox *buttons = new QDialogButtonBox(
+ QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel);
+ buttons->button(QDialogButtonBox::Ok)->setDefault(true);
+ connect(buttons->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
+ connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
+
+ 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)
+{
+ auto page = m_model->pages().at(row);
+ m_pageStack->setCurrentIndex(page->index);
+ m_header->setText(page->displayName());
+ m_iconHeader->setIcon(page->icon());
+}
+
+void PageDialog::currentChanged(const QModelIndex &current)
+{
+ if (current.isValid())
+ {
+ showPage(m_proxyModel->mapToSource(current).row());
+ }
+ else
+ {
+ m_pageStack->setCurrentIndex(0);
+ m_header->setText(QString());
+ m_iconHeader->setIcon(QIcon::fromTheme("bug"));
+ }
+}
+
+void PageDialog::apply()
+{
+}
diff --git a/gui/pagedialog/PageDialog.h b/gui/pagedialog/PageDialog.h
new file mode 100644
index 00000000..880b7df4
--- /dev/null
+++ b/gui/pagedialog/PageDialog.h
@@ -0,0 +1,50 @@
+/* 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 <QDialog>
+#include <QModelIndex>
+#include <gui/pages/BasePageProvider.h>
+
+class IconLabel;
+class QSortFilterProxyModel;
+class PageModel;
+class QLabel;
+class QListView;
+class QLineEdit;
+class QStackedLayout;
+
+class PageDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit PageDialog(BasePageProviderPtr pageProvider, QWidget *parent = 0);
+ virtual ~PageDialog() {};
+private:
+ void createUI();
+private slots:
+ void apply();
+ void currentChanged(const QModelIndex &current);
+ void showPage(int row);
+
+private:
+ QSortFilterProxyModel *m_proxyModel;
+ PageModel *m_model;
+ QStackedLayout *m_pageStack;
+ QLineEdit *m_filter;
+ QListView *m_pageList;
+ QLabel *m_header;
+ IconLabel *m_iconHeader;
+};
diff --git a/gui/pagedialog/PageDialog_p.h b/gui/pagedialog/PageDialog_p.h
new file mode 100644
index 00000000..36e641e3
--- /dev/null
+++ b/gui/pagedialog/PageDialog_p.h
@@ -0,0 +1,106 @@
+#pragma once
+#include <QListView>
+#include <QStyledItemDelegate>
+#include <QEvent>
+#include <QScrollBar>
+
+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<BasePage *> &pages)
+ {
+ beginResetModel();
+ m_pages = pages;
+ endResetModel();
+ }
+ const QList<BasePage *> &pages() const
+ {
+ return m_pages;
+ }
+
+private:
+ BasePage * findPageEntryById(QString id)
+ {
+ for(auto page: m_pages)
+ {
+ if (page->id() == id)
+ return page;
+ }
+ return nullptr;
+ }
+
+ QList<BasePage *> 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);
+ }
+};