NOISSUE move everything.

This commit is contained in:
Petr Mrázek
2015-02-09 01:51:14 +01:00
parent 4730f54df7
commit db877ba121
665 changed files with 1321 additions and 1374 deletions

View File

@ -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;
}

View File

@ -0,0 +1,6 @@
#pragma once
#include <QStringList>
#include <QTextLayout>
QStringList viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
qreal &widthUsed);

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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());
}

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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 );
};

View File

@ -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 &current)
{
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;
}

View File

@ -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 &current);
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;
};

View File

@ -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) 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;
// HACK: fixes icon stretching on windows. TODO: report Qt bug for this
return QIcon(icon.pixmap(QSize(48,48)));
}
}
return QVariant();
}
void setPages(const QList<BasePage *> &pages)
{
beginResetModel();
m_pages = pages;
endResetModel();
}
const QList<BasePage *> &pages() const
{
return m_pages;
}
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);
}
};

View File

@ -0,0 +1,129 @@
#include "ServerStatus.h"
#include "LineSeparator.h"
#include "IconLabel.h"
#include "status/StatusChecker.h"
#include "MultiMC.h"
#include <QHBoxLayout>
#include <QFrame>
#include <QLabel>
#include <QMap>
#include <QToolButton>
#include <QAction>
ServerStatus::ServerStatus(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f)
{
layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
goodIcon = MMC->getThemedIcon("status-good");
yellowIcon = MMC->getThemedIcon("status-yellow");
badIcon = MMC->getThemedIcon("status-bad");
addStatus("minecraft.net", tr("Web"));
addLine();
addStatus("account.mojang.com", tr("Account"));
addLine();
addStatus("skins.minecraft.net", tr("Skins"));
addLine();
addStatus("authserver.mojang.com", tr("Auth"));
addLine();
addStatus("sessionserver.mojang.com", tr("Session"));
m_statusRefresh = new QToolButton(this);
m_statusRefresh->setCheckable(true);
m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly);
m_statusRefresh->setIcon(MMC->getThemedIcon("refresh"));
layout->addWidget(m_statusRefresh);
setLayout(layout);
// Start status checker
m_statusChecker.reset(new StatusChecker());
{
auto reloader = m_statusChecker.get();
connect(reloader, &StatusChecker::statusChanged, this, &ServerStatus::StatusChanged);
connect(reloader, &StatusChecker::statusLoading, this, &ServerStatus::StatusReloading);
connect(m_statusRefresh, &QAbstractButton::clicked, this, &ServerStatus::reloadStatus);
m_statusChecker->startTimer(60000);
reloadStatus();
}
}
ServerStatus::~ServerStatus()
{
}
void ServerStatus::reloadStatus()
{
m_statusChecker->reloadStatus();
}
void ServerStatus::addLine()
{
layout->addWidget(new LineSeparator(this, Qt::Vertical));
}
void ServerStatus::addStatus(QString key, QString name)
{
{
auto label = new IconLabel(this, badIcon, QSize(16, 16));
label->setToolTip(key);
serverLabels[key] = label;
layout->addWidget(label);
}
{
auto label = new QLabel(this);
label->setText(name);
label->setToolTip(key);
layout->addWidget(label);
}
}
void ServerStatus::setStatus(QString key, int value)
{
if (!serverLabels.contains(key))
return;
IconLabel *label = serverLabels[key];
switch(value)
{
case 0:
label->setIcon(goodIcon);
break;
case 1:
label->setIcon(yellowIcon);
break;
default:
case 2:
label->setIcon(badIcon);
break;
}
}
void ServerStatus::StatusChanged(const QMap<QString, QString> statusEntries)
{
auto convertStatus = [&](QString status)->int
{
if (status == "green")
return 0;
else if (status == "yellow")
return 1;
else if (status == "red")
return 2;
return 2;
}
;
auto iter = statusEntries.begin();
while (iter != statusEntries.end())
{
QString key = iter.key();
auto value = convertStatus(iter.value());
setStatus(key, value);
iter++;
}
}
void ServerStatus::StatusReloading(bool is_reloading)
{
m_statusRefresh->setChecked(is_reloading);
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <QString>
#include <QWidget>
#include <QMap>
#include <QIcon>
#include <memory>
class IconLabel;
class QToolButton;
class QHBoxLayout;
class StatusChecker;
class ServerStatus: public QWidget
{
Q_OBJECT
public:
explicit ServerStatus(QWidget *parent = nullptr, Qt::WindowFlags f = 0);
virtual ~ServerStatus();
;
public slots:
void reloadStatus();
void StatusChanged(const QMap<QString, QString> statuses);
void StatusReloading(bool is_reloading);
private: /* methods */
void addLine();
void addStatus(QString key, QString name);
void setStatus(QString key, int value);
private: /* data */
QHBoxLayout * layout = nullptr;
QToolButton *m_statusRefresh = nullptr;
QMap<QString, IconLabel *> serverLabels;
QIcon goodIcon;
QIcon yellowIcon;
QIcon badIcon;
std::shared_ptr<StatusChecker> m_statusChecker;
};

View File

@ -0,0 +1,147 @@
/* 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 <QHeaderView>
#include <QApplication>
#include <QMouseEvent>
#include <QDrag>
#include <QPainter>
#include "VersionListView.h"
#include "Common.h"
VersionListView::VersionListView(QWidget *parent)
:QTreeView ( parent )
{
m_emptyString = tr("No versions are currently available.");
}
void VersionListView::rowsInserted(const QModelIndex &parent, int start, int end)
{
if(!m_itemCount)
viewport()->update();
m_itemCount += end-start+1;
QTreeView::rowsInserted(parent, start, end);
}
void VersionListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
m_itemCount -= end-start+1;
if(!m_itemCount)
viewport()->update();
QTreeView::rowsInserted(parent, start, end);
}
void VersionListView::setModel(QAbstractItemModel *model)
{
m_itemCount = model->rowCount();
if(!m_itemCount)
viewport()->update();
QTreeView::setModel(model);
}
void VersionListView::reset()
{
if(model())
{
m_itemCount = model()->rowCount();
}
viewport()->update();
QTreeView::reset();
}
void VersionListView::setEmptyString(QString emptyString)
{
m_emptyString = emptyString;
if(!m_itemCount)
{
viewport()->update();
}
}
void VersionListView::paintEvent(QPaintEvent *event)
{
if(m_itemCount)
{
QTreeView::paintEvent(event);
}
else
{
paintInfoLabel(event);
}
}
void VersionListView::paintInfoLabel(QPaintEvent *event)
{
//calculate the rect for the overlay
QPainter painter(viewport());
painter.setRenderHint(QPainter::Antialiasing, true);
QFont font("sans", 20);
font.setBold(true);
QRect bounds = viewport()->geometry();
bounds.moveTop(0);
QTextLayout layout(m_emptyString, font);
qreal height = 0.0;
qreal widthUsed = 0.0;
QStringList lines = viewItemTextLayout(layout, bounds.width() - 20, height, widthUsed);
QRect rect (0,0, widthUsed, height);
rect.setWidth(rect.width()+20);
rect.setHeight(rect.height()+20);
rect.moveCenter(bounds.center());
//check if we are allowed to draw in our area
if (!event->rect().intersects(rect)) {
return;
}
//draw the letter of the topmost item semitransparent in the middle
QColor background = QApplication::palette().color(QPalette::Foreground);
QColor foreground = QApplication::palette().color(QPalette::Base);
/*
background.setAlpha(128 - scrollFade);
foreground.setAlpha(128 - scrollFade);
*/
painter.setBrush(QBrush(background));
painter.setPen(foreground);
painter.drawRoundedRect(rect, 5.0, 5.0);
foreground.setAlpha(190);
painter.setPen(foreground);
painter.setFont(font);
painter.drawText(rect, Qt::AlignCenter, lines.join("\n"));
}
/*
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);
}
}
*/

View File

@ -0,0 +1,43 @@
/* 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 VersionListView : public QTreeView
{
Q_OBJECT
public:
explicit VersionListView(QWidget *parent = 0);
virtual void paintEvent(QPaintEvent *event) override;
void setEmptyString(QString emptyString);
virtual void setModel ( QAbstractItemModel* model );
public slots:
virtual void reset() override;
protected slots:
virtual void rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end) override;
virtual void rowsInserted(const QModelIndex &parent, int start, int end) override;
private: /* methods */
void paintInfoLabel(QPaintEvent *event);
private: /* variables */
int m_itemCount = 0;
QString m_emptyString;
};