diff options
Diffstat (limited to 'application/widgets')
| -rw-r--r-- | application/widgets/Common.cpp | 27 | ||||
| -rw-r--r-- | application/widgets/Common.h | 6 | ||||
| -rw-r--r-- | application/widgets/IconLabel.cpp | 43 | ||||
| -rw-r--r-- | application/widgets/IconLabel.h | 26 | ||||
| -rw-r--r-- | application/widgets/LabeledToolButton.cpp | 86 | ||||
| -rw-r--r-- | application/widgets/LabeledToolButton.h | 37 | ||||
| -rw-r--r-- | application/widgets/LineSeparator.cpp | 37 | ||||
| -rw-r--r-- | application/widgets/LineSeparator.h | 18 | ||||
| -rw-r--r-- | application/widgets/MCModInfoFrame.cpp | 111 | ||||
| -rw-r--r-- | application/widgets/MCModInfoFrame.h | 46 | ||||
| -rw-r--r-- | application/widgets/MCModInfoFrame.ui | 68 | ||||
| -rw-r--r-- | application/widgets/ModListView.cpp | 62 | ||||
| -rw-r--r-- | application/widgets/ModListView.h | 27 | ||||
| -rw-r--r-- | application/widgets/PageContainer.cpp | 210 | ||||
| -rw-r--r-- | application/widgets/PageContainer.h | 63 | ||||
| -rw-r--r-- | application/widgets/PageContainer_p.h | 123 | ||||
| -rw-r--r-- | application/widgets/ServerStatus.cpp | 129 | ||||
| -rw-r--r-- | application/widgets/ServerStatus.h | 37 | ||||
| -rw-r--r-- | application/widgets/VersionListView.cpp | 147 | ||||
| -rw-r--r-- | application/widgets/VersionListView.h | 43 |
20 files changed, 1346 insertions, 0 deletions
diff --git a/application/widgets/Common.cpp b/application/widgets/Common.cpp new file mode 100644 index 00000000..9b730d6c --- /dev/null +++ b/application/widgets/Common.cpp @@ -0,0 +1,27 @@ +#include "Common.h" + +// Origin: Qt +QStringList viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height, + qreal &widthUsed) +{ + QStringList lines; + height = 0; + widthUsed = 0; + textLayout.beginLayout(); + QString str = textLayout.text(); + while (true) + { + QTextLine line = textLayout.createLine(); + if (!line.isValid()) + break; + if (line.textLength() == 0) + break; + line.setLineWidth(lineWidth); + line.setPosition(QPointF(0, height)); + height += line.height(); + lines.append(str.mid(line.textStart(), line.textLength())); + widthUsed = qMax(widthUsed, line.naturalTextWidth()); + } + textLayout.endLayout(); + return lines; +} diff --git a/application/widgets/Common.h b/application/widgets/Common.h new file mode 100644 index 00000000..fc46e08f --- /dev/null +++ b/application/widgets/Common.h @@ -0,0 +1,6 @@ +#pragma once +#include <QStringList> +#include <QTextLayout> + +QStringList viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height, + qreal &widthUsed);
\ No newline at end of file diff --git a/application/widgets/IconLabel.cpp b/application/widgets/IconLabel.cpp new file mode 100644 index 00000000..86c8a431 --- /dev/null +++ b/application/widgets/IconLabel.cpp @@ -0,0 +1,43 @@ +#include "IconLabel.h" + +#include <QStyle> +#include <QStyleOption> +#include <QLayout> +#include <QPainter> +#include <QRect> + +IconLabel::IconLabel(QWidget *parent, QIcon icon, QSize size) + : QWidget(parent), m_size(size), m_icon(icon) +{ + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); +} + +QSize IconLabel::sizeHint() const +{ + return m_size; +} + +void IconLabel::setIcon(QIcon icon) +{ + m_icon = icon; + update(); +} + +void IconLabel::paintEvent(QPaintEvent *) +{ + QPainter p(this); + QRect rect = contentsRect(); + int width = rect.width(); + int height = rect.height(); + if(width < height) + { + rect.setHeight(width); + rect.translate(0, (height - width) / 2); + } + else if (width > height) + { + rect.setWidth(height); + rect.translate((width - height) / 2, 0); + } + m_icon.paint(&p, rect); +} diff --git a/application/widgets/IconLabel.h b/application/widgets/IconLabel.h new file mode 100644 index 00000000..a2f1eef3 --- /dev/null +++ b/application/widgets/IconLabel.h @@ -0,0 +1,26 @@ +#pragma once +#include <QWidget> +#include <QIcon> + +class QStyleOption; + +/** + * This is a trivial widget that paints a QIcon of the specified size. + */ +class IconLabel : public QWidget +{ + Q_OBJECT + +public: + /// Create a line separator. orientation is the orientation of the line. + explicit IconLabel(QWidget *parent, QIcon icon, QSize size); + + virtual QSize sizeHint() const; + virtual void paintEvent(QPaintEvent *); + + void setIcon(QIcon icon); + +private: + QSize m_size; + QIcon m_icon; +}; diff --git a/application/widgets/LabeledToolButton.cpp b/application/widgets/LabeledToolButton.cpp new file mode 100644 index 00000000..dfdde1bc --- /dev/null +++ b/application/widgets/LabeledToolButton.cpp @@ -0,0 +1,86 @@ +/* Copyright 2013-2015 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 <QLabel> +#include <QVBoxLayout> +#include <QResizeEvent> +#include <QStyleOption> +#include "LabeledToolButton.h" +#include <QApplication> + +/* + * + * Tool Button with a label on it, instead of the normal text rendering + * + */ + +LabeledToolButton::LabeledToolButton(QWidget * parent) + : QToolButton(parent) + , m_label(new QLabel(this)) +{ + //QToolButton::setText(" "); + m_label->setWordWrap(true); + m_label->setMouseTracking(false); + m_label->setAlignment(Qt::AlignCenter); + m_label->setTextInteractionFlags(Qt::NoTextInteraction); + // somehow, this makes word wrap work in the QLabel. yay. + m_label->setMinimumWidth(100); +} + +QString LabeledToolButton::text() const +{ + return m_label->text(); +} + +void LabeledToolButton::setText(const QString & text) +{ + m_label->setText(text); +} + +/*! + \reimp +*/ +QSize LabeledToolButton::sizeHint() const +{ + /* + Q_D(const QToolButton); + if (d->sizeHint.isValid()) + return d->sizeHint; + */ + ensurePolished(); + + int w = 0, h = 0; + QStyleOptionToolButton opt; + initStyleOption(&opt); + QSize sz =m_label->sizeHint(); + w = sz.width(); + h = sz.height(); + + opt.rect.setSize(QSize(w, h)); // PM_MenuButtonIndicator depends on the height + if (popupMode() == MenuButtonPopup) + w += style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this); + + QSize rawSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(w, h), this); + QSize sizeHint = rawSize.expandedTo(QApplication::globalStrut()); + return sizeHint; +} + + + +void LabeledToolButton::resizeEvent(QResizeEvent * event) +{ + m_label->setGeometry(QRect(4, 4, width()-8, height()-8)); + QWidget::resizeEvent(event); +} diff --git a/application/widgets/LabeledToolButton.h b/application/widgets/LabeledToolButton.h new file mode 100644 index 00000000..1b74c4ee --- /dev/null +++ b/application/widgets/LabeledToolButton.h @@ -0,0 +1,37 @@ +/* Copyright 2013-2015 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 <QPushButton> +#include <QToolButton> + +class QLabel; + +class LabeledToolButton : public QToolButton +{ + Q_OBJECT + + QLabel * m_label; + +public: + LabeledToolButton(QWidget * parent = 0); + + QString text() const; + void setText(const QString & text); + virtual QSize sizeHint() const; +protected: + void resizeEvent(QResizeEvent * event); +}; diff --git a/application/widgets/LineSeparator.cpp b/application/widgets/LineSeparator.cpp new file mode 100644 index 00000000..f4ee173d --- /dev/null +++ b/application/widgets/LineSeparator.cpp @@ -0,0 +1,37 @@ +#include "LineSeparator.h" + +#include <QStyle> +#include <QStyleOption> +#include <QLayout> +#include <QPainter> + +void LineSeparator::initStyleOption(QStyleOption *option) const +{ + option->initFrom(this); + // in a horizontal layout, the line is vertical (and vice versa) + if (m_orientation == Qt::Vertical) + option->state |= QStyle::State_Horizontal; +} + +LineSeparator::LineSeparator(QWidget *parent, Qt::Orientation orientation) + : QWidget(parent), m_orientation(orientation) +{ + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); +} + +QSize LineSeparator::sizeHint() const +{ + QStyleOption opt; + initStyleOption(&opt); + const int extent = + style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, &opt, parentWidget()); + return QSize(extent, extent); +} + +void LineSeparator::paintEvent(QPaintEvent *) +{ + QPainter p(this); + QStyleOption opt; + initStyleOption(&opt); + style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, &p, parentWidget()); +} diff --git a/application/widgets/LineSeparator.h b/application/widgets/LineSeparator.h new file mode 100644 index 00000000..9546e747 --- /dev/null +++ b/application/widgets/LineSeparator.h @@ -0,0 +1,18 @@ +#pragma once +#include <QWidget> + +class QStyleOption; + +class LineSeparator : public QWidget +{ + Q_OBJECT + +public: + /// Create a line separator. orientation is the orientation of the line. + explicit LineSeparator(QWidget *parent, Qt::Orientation orientation = Qt::Horizontal); + QSize sizeHint() const; + void paintEvent(QPaintEvent *); + void initStyleOption(QStyleOption *option) const; +private: + Qt::Orientation m_orientation = Qt::Horizontal; +}; diff --git a/application/widgets/MCModInfoFrame.cpp b/application/widgets/MCModInfoFrame.cpp new file mode 100644 index 00000000..2f859ed3 --- /dev/null +++ b/application/widgets/MCModInfoFrame.cpp @@ -0,0 +1,111 @@ +/* Copyright 2013-2015 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 <QMessageBox> +#include <QtGui> + +#include "MCModInfoFrame.h" +#include "ui_MCModInfoFrame.h" +#include "dialogs/CustomMessageBox.h" + +void MCModInfoFrame::updateWithMod(Mod &m) +{ + if(m.type() == m.MOD_FOLDER) + { + clear(); + return; + } + + QString text = ""; + QString name = ""; + if(m.name().isEmpty()) name = m.mmc_id(); + else name = m.name(); + + if(m.homeurl().isEmpty()) text = name; + else text = "<a href=\"" + m.homeurl() + "\">" + name + "</a>"; + if(!m.authors().isEmpty()) text += " by " + m.authors(); + + setModText(text); + + if(m.description().isEmpty()) + { + setModDescription(tr("No description provided in mcmod.info")); + } + else + { + setModDescription(m.description()); + } +} + +void MCModInfoFrame::clear() +{ + setModText(tr("Select a mod to view title and authors...")); + setModDescription(tr("Select a mod to view description...")); +} + +MCModInfoFrame::MCModInfoFrame(QWidget *parent) : + QFrame(parent), + ui(new Ui::MCModInfoFrame) +{ + ui->setupUi(this); +} + +MCModInfoFrame::~MCModInfoFrame() +{ + delete ui; +} + +void MCModInfoFrame::setModText(QString text) +{ + ui->label_ModText->setText(text); +} + +void MCModInfoFrame::setModDescription(QString text) +{ + ui->label_ModDescription->setToolTip(""); + QString intermediatetext = text.trimmed(); + bool prev(false); + QChar rem('\n'); + QString finaltext; + finaltext.reserve(intermediatetext.size()); + foreach(const QChar& c, intermediatetext) + { + if(c == rem && prev){ + continue; + } + prev = c == rem; + finaltext += c; + } + QString labeltext; + labeltext.reserve(300); + if(finaltext.length() > 290) + { + ui->label_ModDescription->setOpenExternalLinks(false); + ui->label_ModDescription->setTextFormat(Qt::TextFormat::RichText); + desc = text; + labeltext.append("<html><body>" + finaltext.left(287) + "<a href=\"#mod_desc\">...</a></body></html>"); + QObject::connect(ui->label_ModDescription, &QLabel::linkActivated, this, &MCModInfoFrame::modDescEllipsisHandler); + } + else + { + ui->label_ModDescription->setTextFormat(Qt::TextFormat::PlainText); + labeltext.append(finaltext); + } + ui->label_ModDescription->setText(labeltext); +} +void MCModInfoFrame::modDescEllipsisHandler(const QString &link) +{ + CustomMessageBox::selectable(this, tr(""), desc)->show(); +} diff --git a/application/widgets/MCModInfoFrame.h b/application/widgets/MCModInfoFrame.h new file mode 100644 index 00000000..3f75279c --- /dev/null +++ b/application/widgets/MCModInfoFrame.h @@ -0,0 +1,46 @@ +/* Copyright 2013-2015 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 <QFrame> +#include "minecraft/Mod.h" + +namespace Ui +{ +class MCModInfoFrame; +} + +class MCModInfoFrame : public QFrame +{ + Q_OBJECT + +public: + explicit MCModInfoFrame(QWidget *parent = 0); + ~MCModInfoFrame(); + + void setModText(QString text); + void setModDescription(QString text); + + void updateWithMod(Mod &m); + void clear(); + +public slots: + void modDescEllipsisHandler(const QString& link ); + +private: + Ui::MCModInfoFrame *ui; + QString desc; +}; diff --git a/application/widgets/MCModInfoFrame.ui b/application/widgets/MCModInfoFrame.ui new file mode 100644 index 00000000..60e0a65c --- /dev/null +++ b/application/widgets/MCModInfoFrame.ui @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MCModInfoFrame</class> + <widget class="QFrame" name="MCModInfoFrame"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>527</width> + <height>113</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>120</height> + </size> + </property> + <property name="windowTitle"> + <string>Frame</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="label_ModText"> + <property name="text"> + <string>Select a mod to view title and authors...</string> + </property> + <property name="textFormat"> + <enum>Qt::RichText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="openExternalLinks"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_ModDescription"> + <property name="text"> + <string>Select a mod to view description...</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/application/widgets/ModListView.cpp b/application/widgets/ModListView.cpp new file mode 100644 index 00000000..aa16ad05 --- /dev/null +++ b/application/widgets/ModListView.cpp @@ -0,0 +1,62 @@ +/* Copyright 2013-2015 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 "ModListView.h" +#include <QHeaderView> +#include <QMouseEvent> +#include <QPainter> +#include <QDrag> +#include <QRect> + +ModListView::ModListView ( QWidget* parent ) + :QTreeView ( parent ) +{ + setAllColumnsShowFocus ( true ); + setExpandsOnDoubleClick ( false ); + setRootIsDecorated ( false ); + setSortingEnabled ( false ); + setAlternatingRowColors ( true ); + setSelectionMode ( QAbstractItemView::ContiguousSelection ); + setHeaderHidden ( false ); + setSelectionBehavior(QAbstractItemView::SelectRows); + setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOn ); + setHorizontalScrollBarPolicy ( Qt::ScrollBarAsNeeded ); + setDropIndicatorShown(true); + setDragEnabled(true); + setDragDropMode(QAbstractItemView::DropOnly); + viewport()->setAcceptDrops(true); +} + +void ModListView::setModel ( QAbstractItemModel* model ) +{ + QTreeView::setModel ( model ); + auto head = header(); + head->setStretchLastSection(false); + // HACK: this is true for the checkbox column of mod lists + auto string = model->headerData(0,head->orientation()).toString(); + if(!string.size()) + { + head->setSectionResizeMode(0, QHeaderView::ResizeToContents); + head->setSectionResizeMode(1, QHeaderView::Stretch); + for(int i = 2; i < head->count(); i++) + head->setSectionResizeMode(i, QHeaderView::ResizeToContents); + } + else + { + head->setSectionResizeMode(0, QHeaderView::Stretch); + for(int i = 1; i < head->count(); i++) + head->setSectionResizeMode(i, QHeaderView::ResizeToContents); + } +} diff --git a/application/widgets/ModListView.h b/application/widgets/ModListView.h new file mode 100644 index 00000000..43de9811 --- /dev/null +++ b/application/widgets/ModListView.h @@ -0,0 +1,27 @@ +/* Copyright 2013-2015 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 <QTreeView> + +class Mod; + +class ModListView: public QTreeView +{ + Q_OBJECT +public: + explicit ModListView ( QWidget* parent = 0 ); + virtual void setModel ( QAbstractItemModel* model ); +}; diff --git a/application/widgets/PageContainer.cpp b/application/widgets/PageContainer.cpp new file mode 100644 index 00000000..679039a7 --- /dev/null +++ b/application/widgets/PageContainer.cpp @@ -0,0 +1,210 @@ +/* Copyright 2013-2015 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 <QStackedLayout> +#include <QPushButton> +#include <QSortFilterProxyModel> +#include <QUrl> +#include <QStyledItemDelegate> +#include <QListView> +#include <QLineEdit> +#include <QLabel> +#include <QDialogButtonBox> +#include <QGridLayout> +#include <QDesktopServices> + +#include "MultiMC.h" +#include "settings/SettingsObject.h" +#include "widgets/IconLabel.h" +#include "Platform.h" +#include "PageContainer_p.h" +#include <MultiMC.h> + +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<PageModel *>(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<QWidget *>(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); + const int rightMargin = MMC->style()->pixelMetric(QStyle::PM_LayoutRightMargin); + headerHLayout->addSpacerItem( + new QSpacerItem(rightMargin, 0, QSizePolicy::Fixed, QSizePolicy::Ignored)); + + 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::addButtons(QLayout *buttons) +{ + m_layout->addLayout(buttons, 2, 0, 1, 2); +} + +void PageContainer::showPage(int row) +{ + if (m_currentPage) + { + m_currentPage->closed(); + } + 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(MMC->getThemedIcon("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; + } + if (m_currentPage) + { + m_currentPage->closed(); + } + return true; +} diff --git a/application/widgets/PageContainer.h b/application/widgets/PageContainer.h new file mode 100644 index 00000000..3027af36 --- /dev/null +++ b/application/widgets/PageContainer.h @@ -0,0 +1,63 @@ +/* Copyright 2013-2015 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 <QWidget> +#include <QModelIndex> + +#include "pages/BasePageProvider.h" + +class QLayout; +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); + void addButtons(QLayout * 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 = 0; + 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/application/widgets/PageContainer_p.h b/application/widgets/PageContainer_p.h new file mode 100644 index 00000000..4c720e4c --- /dev/null +++ b/application/widgets/PageContainer_p.h @@ -0,0 +1,123 @@ +/* Copyright 2013-2015 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 <QListView> +#include <QStyledItemDelegate> +#include <QEvent> +#include <QScrollBar> + +class BasePage; +const int pageIconSize = 24; + +class PageViewDelegate : public QStyledItemDelegate +{ +public: + PageViewDelegate(QObject *parent) : QStyledItemDelegate(parent) + { + } + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) con |
