NOISSUE tabs -> spaces
This commit is contained in:
@ -5,50 +5,50 @@ Config BuildConfig;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
// Version information
|
||||
VERSION_MAJOR = @MultiMC_VERSION_MAJOR@;
|
||||
VERSION_MINOR = @MultiMC_VERSION_MINOR@;
|
||||
VERSION_HOTFIX = @MultiMC_VERSION_HOTFIX@;
|
||||
VERSION_BUILD = @MultiMC_VERSION_BUILD@;
|
||||
// Version information
|
||||
VERSION_MAJOR = @MultiMC_VERSION_MAJOR@;
|
||||
VERSION_MINOR = @MultiMC_VERSION_MINOR@;
|
||||
VERSION_HOTFIX = @MultiMC_VERSION_HOTFIX@;
|
||||
VERSION_BUILD = @MultiMC_VERSION_BUILD@;
|
||||
|
||||
BUILD_PLATFORM = "@MultiMC_BUILD_PLATFORM@";
|
||||
CHANLIST_URL = "@MultiMC_CHANLIST_URL@";
|
||||
ANALYTICS_ID = "@MultiMC_ANALYTICS_ID@";
|
||||
NOTIFICATION_URL = "@MultiMC_NOTIFICATION_URL@";
|
||||
FULL_VERSION_STR = "@MultiMC_VERSION_MAJOR@.@MultiMC_VERSION_MINOR@.@MultiMC_VERSION_BUILD@";
|
||||
BUILD_PLATFORM = "@MultiMC_BUILD_PLATFORM@";
|
||||
CHANLIST_URL = "@MultiMC_CHANLIST_URL@";
|
||||
ANALYTICS_ID = "@MultiMC_ANALYTICS_ID@";
|
||||
NOTIFICATION_URL = "@MultiMC_NOTIFICATION_URL@";
|
||||
FULL_VERSION_STR = "@MultiMC_VERSION_MAJOR@.@MultiMC_VERSION_MINOR@.@MultiMC_VERSION_BUILD@";
|
||||
|
||||
GIT_COMMIT = "@MultiMC_GIT_COMMIT@";
|
||||
GIT_REFSPEC = "@MultiMC_GIT_REFSPEC@";
|
||||
if(GIT_REFSPEC.startsWith("refs/heads/") && !CHANLIST_URL.isEmpty() && VERSION_BUILD >= 0)
|
||||
{
|
||||
VERSION_CHANNEL = GIT_REFSPEC;
|
||||
VERSION_CHANNEL.remove("refs/heads/");
|
||||
UPDATER_ENABLED = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VERSION_CHANNEL = QObject::tr("custom");
|
||||
}
|
||||
GIT_COMMIT = "@MultiMC_GIT_COMMIT@";
|
||||
GIT_REFSPEC = "@MultiMC_GIT_REFSPEC@";
|
||||
if(GIT_REFSPEC.startsWith("refs/heads/") && !CHANLIST_URL.isEmpty() && VERSION_BUILD >= 0)
|
||||
{
|
||||
VERSION_CHANNEL = GIT_REFSPEC;
|
||||
VERSION_CHANNEL.remove("refs/heads/");
|
||||
UPDATER_ENABLED = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VERSION_CHANNEL = QObject::tr("custom");
|
||||
}
|
||||
|
||||
VERSION_STR = "@MultiMC_VERSION_STRING@";
|
||||
NEWS_RSS_URL = "@MultiMC_NEWS_RSS_URL@";
|
||||
PASTE_EE_KEY = "@MultiMC_PASTE_EE_API_KEY@";
|
||||
VERSION_STR = "@MultiMC_VERSION_STRING@";
|
||||
NEWS_RSS_URL = "@MultiMC_NEWS_RSS_URL@";
|
||||
PASTE_EE_KEY = "@MultiMC_PASTE_EE_API_KEY@";
|
||||
}
|
||||
|
||||
QString Config::printableVersionString() const
|
||||
{
|
||||
QString vstr = QString("%1.%2.%3").arg(QString::number(VERSION_MAJOR), QString::number(VERSION_MINOR), QString::number(VERSION_HOTFIX));
|
||||
QString vstr = QString("%1.%2.%3").arg(QString::number(VERSION_MAJOR), QString::number(VERSION_MINOR), QString::number(VERSION_HOTFIX));
|
||||
|
||||
// If the build is not a main release, append the channel
|
||||
if(VERSION_CHANNEL != "stable")
|
||||
{
|
||||
vstr += "-" + VERSION_CHANNEL;
|
||||
}
|
||||
// If the build is not a main release, append the channel
|
||||
if(VERSION_CHANNEL != "stable")
|
||||
{
|
||||
vstr += "-" + VERSION_CHANNEL;
|
||||
}
|
||||
|
||||
// if a build number is set, also add it to the end
|
||||
if(VERSION_BUILD >= 0)
|
||||
{
|
||||
vstr += "-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
return vstr;
|
||||
// if a build number is set, also add it to the end
|
||||
if(VERSION_BUILD >= 0)
|
||||
{
|
||||
vstr += "-" + QString::number(VERSION_BUILD);
|
||||
}
|
||||
return vstr;
|
||||
}
|
||||
|
@ -7,64 +7,64 @@
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
Config();
|
||||
/// The major version number.
|
||||
int VERSION_MAJOR;
|
||||
/// The minor version number.
|
||||
int VERSION_MINOR;
|
||||
/// The hotfix number.
|
||||
int VERSION_HOTFIX;
|
||||
/// The build number.
|
||||
int VERSION_BUILD;
|
||||
Config();
|
||||
/// The major version number.
|
||||
int VERSION_MAJOR;
|
||||
/// The minor version number.
|
||||
int VERSION_MINOR;
|
||||
/// The hotfix number.
|
||||
int VERSION_HOTFIX;
|
||||
/// The build number.
|
||||
int VERSION_BUILD;
|
||||
|
||||
/**
|
||||
* The version channel
|
||||
* This is used by the updater to determine what channel the current version came from.
|
||||
*/
|
||||
QString VERSION_CHANNEL;
|
||||
/**
|
||||
* The version channel
|
||||
* This is used by the updater to determine what channel the current version came from.
|
||||
*/
|
||||
QString VERSION_CHANNEL;
|
||||
|
||||
bool UPDATER_ENABLED = false;
|
||||
bool UPDATER_ENABLED = false;
|
||||
|
||||
/// A short string identifying this build's platform. For example, "lin64" or "win32".
|
||||
QString BUILD_PLATFORM;
|
||||
/// A short string identifying this build's platform. For example, "lin64" or "win32".
|
||||
QString BUILD_PLATFORM;
|
||||
|
||||
/// URL for the updater's channel
|
||||
QString CHANLIST_URL;
|
||||
/// URL for the updater's channel
|
||||
QString CHANLIST_URL;
|
||||
|
||||
/// Google analytics ID
|
||||
QString ANALYTICS_ID;
|
||||
/// Google analytics ID
|
||||
QString ANALYTICS_ID;
|
||||
|
||||
/// URL for notifications
|
||||
QString NOTIFICATION_URL;
|
||||
/// URL for notifications
|
||||
QString NOTIFICATION_URL;
|
||||
|
||||
/// Used for matching notifications
|
||||
QString FULL_VERSION_STR;
|
||||
/// Used for matching notifications
|
||||
QString FULL_VERSION_STR;
|
||||
|
||||
/// The git commit hash of this build
|
||||
QString GIT_COMMIT;
|
||||
/// The git commit hash of this build
|
||||
QString GIT_COMMIT;
|
||||
|
||||
/// The git refspec of this build
|
||||
QString GIT_REFSPEC;
|
||||
/// The git refspec of this build
|
||||
QString GIT_REFSPEC;
|
||||
|
||||
/// This is printed on start to standard output
|
||||
QString VERSION_STR;
|
||||
/// This is printed on start to standard output
|
||||
QString VERSION_STR;
|
||||
|
||||
/**
|
||||
* This is used to fetch the news RSS feed.
|
||||
* It defaults in CMakeLists.txt to "http://multimc.org/rss.xml"
|
||||
*/
|
||||
QString NEWS_RSS_URL;
|
||||
/**
|
||||
* This is used to fetch the news RSS feed.
|
||||
* It defaults in CMakeLists.txt to "http://multimc.org/rss.xml"
|
||||
*/
|
||||
QString NEWS_RSS_URL;
|
||||
|
||||
/**
|
||||
* API key you can get from paste.ee when you register an account
|
||||
*/
|
||||
QString PASTE_EE_KEY;
|
||||
/**
|
||||
* API key you can get from paste.ee when you register an account
|
||||
*/
|
||||
QString PASTE_EE_KEY;
|
||||
|
||||
/**
|
||||
* \brief Converts the Version to a string.
|
||||
* \return The version number in string format (major.minor.revision.build).
|
||||
*/
|
||||
QString printableVersionString() const;
|
||||
/**
|
||||
* \brief Converts the Version to a string.
|
||||
* \return The version number in string format (major.minor.revision.build).
|
||||
*/
|
||||
QString printableVersionString() const;
|
||||
};
|
||||
|
||||
extern Config BuildConfig;
|
||||
|
@ -6,13 +6,13 @@
|
||||
*/
|
||||
QColor ColorCache::blend(QColor color)
|
||||
{
|
||||
if (Rainbow::luma(m_front) > Rainbow::luma(m_back))
|
||||
{
|
||||
// for dark color schemes, produce a fitting color first
|
||||
color = Rainbow::tint(m_front, color, 0.5);
|
||||
}
|
||||
// adapt contrast
|
||||
return Rainbow::mix(m_front, color, m_bias);
|
||||
if (Rainbow::luma(m_front) > Rainbow::luma(m_back))
|
||||
{
|
||||
// for dark color schemes, produce a fitting color first
|
||||
color = Rainbow::tint(m_front, color, 0.5);
|
||||
}
|
||||
// adapt contrast
|
||||
return Rainbow::mix(m_front, color, m_bias);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -20,16 +20,16 @@ QColor ColorCache::blend(QColor color)
|
||||
*/
|
||||
QColor ColorCache::blendBackground(QColor color)
|
||||
{
|
||||
// adapt contrast
|
||||
return Rainbow::mix(m_back, color, m_bias);
|
||||
// adapt contrast
|
||||
return Rainbow::mix(m_back, color, m_bias);
|
||||
}
|
||||
|
||||
void ColorCache::recolorAll()
|
||||
{
|
||||
auto iter = m_colors.begin();
|
||||
while(iter != m_colors.end())
|
||||
{
|
||||
iter->front = blend(iter->original);
|
||||
iter->back = blendBackground(iter->original);
|
||||
}
|
||||
auto iter = m_colors.begin();
|
||||
while(iter != m_colors.end())
|
||||
{
|
||||
iter->front = blend(iter->original);
|
||||
iter->back = blendBackground(iter->original);
|
||||
}
|
||||
}
|
||||
|
@ -7,113 +7,113 @@
|
||||
class ColorCache
|
||||
{
|
||||
public:
|
||||
ColorCache(QColor front, QColor back, qreal bias)
|
||||
{
|
||||
m_front = front;
|
||||
m_back = back;
|
||||
m_bias = bias;
|
||||
};
|
||||
ColorCache(QColor front, QColor back, qreal bias)
|
||||
{
|
||||
m_front = front;
|
||||
m_back = back;
|
||||
m_bias = bias;
|
||||
};
|
||||
|
||||
void addColor(int key, QColor color)
|
||||
{
|
||||
m_colors[key] = {color, blend(color), blendBackground(color)};
|
||||
}
|
||||
void addColor(int key, QColor color)
|
||||
{
|
||||
m_colors[key] = {color, blend(color), blendBackground(color)};
|
||||
}
|
||||
|
||||
void setForeground(QColor front)
|
||||
{
|
||||
if(m_front != front)
|
||||
{
|
||||
m_front = front;
|
||||
recolorAll();
|
||||
}
|
||||
}
|
||||
void setForeground(QColor front)
|
||||
{
|
||||
if(m_front != front)
|
||||
{
|
||||
m_front = front;
|
||||
recolorAll();
|
||||
}
|
||||
}
|
||||
|
||||
void setBackground(QColor back)
|
||||
{
|
||||
if(m_back != back)
|
||||
{
|
||||
m_back = back;
|
||||
recolorAll();
|
||||
}
|
||||
}
|
||||
void setBackground(QColor back)
|
||||
{
|
||||
if(m_back != back)
|
||||
{
|
||||
m_back = back;
|
||||
recolorAll();
|
||||
}
|
||||
}
|
||||
|
||||
QColor getFront(int key)
|
||||
{
|
||||
auto iter = m_colors.find(key);
|
||||
if(iter == m_colors.end())
|
||||
{
|
||||
return QColor();
|
||||
}
|
||||
return (*iter).front;
|
||||
}
|
||||
QColor getFront(int key)
|
||||
{
|
||||
auto iter = m_colors.find(key);
|
||||
if(iter == m_colors.end())
|
||||
{
|
||||
return QColor();
|
||||
}
|
||||
return (*iter).front;
|
||||
}
|
||||
|
||||
QColor getBack(int key)
|
||||
{
|
||||
auto iter = m_colors.find(key);
|
||||
if(iter == m_colors.end())
|
||||
{
|
||||
return QColor();
|
||||
}
|
||||
return (*iter).back;
|
||||
}
|
||||
QColor getBack(int key)
|
||||
{
|
||||
auto iter = m_colors.find(key);
|
||||
if(iter == m_colors.end())
|
||||
{
|
||||
return QColor();
|
||||
}
|
||||
return (*iter).back;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blend the color with the front color, adapting to the back color
|
||||
*/
|
||||
QColor blend(QColor color);
|
||||
/**
|
||||
* Blend the color with the front color, adapting to the back color
|
||||
*/
|
||||
QColor blend(QColor color);
|
||||
|
||||
/**
|
||||
* Blend the color with the back color
|
||||
*/
|
||||
QColor blendBackground(QColor color);
|
||||
/**
|
||||
* Blend the color with the back color
|
||||
*/
|
||||
QColor blendBackground(QColor color);
|
||||
|
||||
protected:
|
||||
void recolorAll();
|
||||
void recolorAll();
|
||||
|
||||
protected:
|
||||
struct ColorEntry
|
||||
{
|
||||
QColor original;
|
||||
QColor front;
|
||||
QColor back;
|
||||
};
|
||||
struct ColorEntry
|
||||
{
|
||||
QColor original;
|
||||
QColor front;
|
||||
QColor back;
|
||||
};
|
||||
|
||||
protected:
|
||||
qreal m_bias;
|
||||
QColor m_front;
|
||||
QColor m_back;
|
||||
QMap<int, ColorEntry> m_colors;
|
||||
qreal m_bias;
|
||||
QColor m_front;
|
||||
QColor m_back;
|
||||
QMap<int, ColorEntry> m_colors;
|
||||
};
|
||||
|
||||
class LogColorCache : public ColorCache
|
||||
{
|
||||
public:
|
||||
LogColorCache(QColor front, QColor back)
|
||||
: ColorCache(front, back, 1.0)
|
||||
{
|
||||
addColor((int)MessageLevel::MultiMC, QColor("purple"));
|
||||
addColor((int)MessageLevel::Debug, QColor("green"));
|
||||
addColor((int)MessageLevel::Warning, QColor("orange"));
|
||||
addColor((int)MessageLevel::Error, QColor("red"));
|
||||
addColor((int)MessageLevel::Fatal, QColor("red"));
|
||||
addColor((int)MessageLevel::Message, front);
|
||||
}
|
||||
LogColorCache(QColor front, QColor back)
|
||||
: ColorCache(front, back, 1.0)
|
||||
{
|
||||
addColor((int)MessageLevel::MultiMC, QColor("purple"));
|
||||
addColor((int)MessageLevel::Debug, QColor("green"));
|
||||
addColor((int)MessageLevel::Warning, QColor("orange"));
|
||||
addColor((int)MessageLevel::Error, QColor("red"));
|
||||
addColor((int)MessageLevel::Fatal, QColor("red"));
|
||||
addColor((int)MessageLevel::Message, front);
|
||||
}
|
||||
|
||||
QColor getFront(MessageLevel::Enum level)
|
||||
{
|
||||
if(!m_colors.contains((int) level))
|
||||
{
|
||||
return ColorCache::getFront((int)MessageLevel::Message);
|
||||
}
|
||||
return ColorCache::getFront((int)level);
|
||||
}
|
||||
QColor getFront(MessageLevel::Enum level)
|
||||
{
|
||||
if(!m_colors.contains((int) level))
|
||||
{
|
||||
return ColorCache::getFront((int)MessageLevel::Message);
|
||||
}
|
||||
return ColorCache::getFront((int)level);
|
||||
}
|
||||
|
||||
QColor getBack(MessageLevel::Enum level)
|
||||
{
|
||||
if(level == MessageLevel::Fatal)
|
||||
{
|
||||
return QColor(Qt::black);
|
||||
}
|
||||
return QColor(Qt::transparent);
|
||||
}
|
||||
QColor getBack(MessageLevel::Enum level)
|
||||
{
|
||||
if(level == MessageLevel::Fatal)
|
||||
{
|
||||
return QColor(Qt::black);
|
||||
}
|
||||
return QColor(Qt::transparent);
|
||||
}
|
||||
};
|
||||
|
@ -14,67 +14,67 @@
|
||||
class FormLayoutWidgetItem : public QWidgetItem
|
||||
{
|
||||
public:
|
||||
FormLayoutWidgetItem(QWidget* widget, QFormLayout* formLayout, QFormLayout::ItemRole itemRole)
|
||||
: QWidgetItem(widget)
|
||||
, m_width(-1)
|
||||
, m_formLayout(formLayout)
|
||||
, m_itemRole(itemRole)
|
||||
{}
|
||||
FormLayoutWidgetItem(QWidget* widget, QFormLayout* formLayout, QFormLayout::ItemRole itemRole)
|
||||
: QWidgetItem(widget)
|
||||
, m_width(-1)
|
||||
, m_formLayout(formLayout)
|
||||
, m_itemRole(itemRole)
|
||||
{}
|
||||
|
||||
QSize sizeHint() const
|
||||
{
|
||||
QSize size = QWidgetItem::sizeHint();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
QSize sizeHint() const
|
||||
{
|
||||
QSize size = QWidgetItem::sizeHint();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
QSize minimumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::minimumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
QSize minimumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::minimumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
QSize maximumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::maximumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
QSize maximumSize() const
|
||||
{
|
||||
QSize size = QWidgetItem::maximumSize();
|
||||
if (m_width != -1) {
|
||||
size.setWidth(m_width);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void setWidth(int width)
|
||||
{
|
||||
if (width != m_width) {
|
||||
m_width = width;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
void setWidth(int width)
|
||||
{
|
||||
if (width != m_width) {
|
||||
m_width = width;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void setGeometry(const QRect& _rect)
|
||||
{
|
||||
QRect rect = _rect;
|
||||
int width = widget()->sizeHint().width();
|
||||
if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) {
|
||||
rect.setLeft(rect.right() - width);
|
||||
}
|
||||
QWidgetItem::setGeometry(rect);
|
||||
}
|
||||
void setGeometry(const QRect& _rect)
|
||||
{
|
||||
QRect rect = _rect;
|
||||
int width = widget()->sizeHint().width();
|
||||
if (m_itemRole == QFormLayout::LabelRole && m_formLayout->labelAlignment() & Qt::AlignRight) {
|
||||
rect.setLeft(rect.right() - width);
|
||||
}
|
||||
QWidgetItem::setGeometry(rect);
|
||||
}
|
||||
|
||||
QFormLayout* formLayout() const
|
||||
{
|
||||
return m_formLayout;
|
||||
}
|
||||
QFormLayout* formLayout() const
|
||||
{
|
||||
return m_formLayout;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_width;
|
||||
QFormLayout* m_formLayout;
|
||||
QFormLayout::ItemRole m_itemRole;
|
||||
int m_width;
|
||||
QFormLayout* m_formLayout;
|
||||
QFormLayout::ItemRole m_itemRole;
|
||||
};
|
||||
|
||||
typedef QPair<QGridLayout*, int> GridColumnInfo;
|
||||
@ -82,25 +82,25 @@ typedef QPair<QGridLayout*, int> GridColumnInfo;
|
||||
class ColumnResizerPrivate
|
||||
{
|
||||
public:
|
||||
ColumnResizerPrivate(ColumnResizer* q_ptr)
|
||||
: q(q_ptr)
|
||||
, m_updateTimer(new QTimer(q))
|
||||
{
|
||||
m_updateTimer->setSingleShot(true);
|
||||
m_updateTimer->setInterval(0);
|
||||
QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
|
||||
}
|
||||
ColumnResizerPrivate(ColumnResizer* q_ptr)
|
||||
: q(q_ptr)
|
||||
, m_updateTimer(new QTimer(q))
|
||||
{
|
||||
m_updateTimer->setSingleShot(true);
|
||||
m_updateTimer->setInterval(0);
|
||||
QObject::connect(m_updateTimer, SIGNAL(timeout()), q, SLOT(updateWidth()));
|
||||
}
|
||||
|
||||
void scheduleWidthUpdate()
|
||||
{
|
||||
m_updateTimer->start();
|
||||
}
|
||||
void scheduleWidthUpdate()
|
||||
{
|
||||
m_updateTimer->start();
|
||||
}
|
||||
|
||||
ColumnResizer* q;
|
||||
QTimer* m_updateTimer;
|
||||
QList<QWidget*> m_widgets;
|
||||
QList<FormLayoutWidgetItem*> m_wrWidgetItemList;
|
||||
QList<GridColumnInfo> m_gridColumnInfoList;
|
||||
ColumnResizer* q;
|
||||
QTimer* m_updateTimer;
|
||||
QList<QWidget*> m_widgets;
|
||||
QList<FormLayoutWidgetItem*> m_wrWidgetItemList;
|
||||
QList<GridColumnInfo> m_gridColumnInfoList;
|
||||
};
|
||||
|
||||
ColumnResizer::ColumnResizer(QObject* parent)
|
||||
@ -110,90 +110,90 @@ ColumnResizer::ColumnResizer(QObject* parent)
|
||||
|
||||
ColumnResizer::~ColumnResizer()
|
||||
{
|
||||
delete d;
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidget(QWidget* widget)
|
||||
{
|
||||
d->m_widgets.append(widget);
|
||||
widget->installEventFilter(this);
|
||||
d->scheduleWidthUpdate();
|
||||
d->m_widgets.append(widget);
|
||||
widget->installEventFilter(this);
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
|
||||
void ColumnResizer::updateWidth()
|
||||
{
|
||||
int width = 0;
|
||||
Q_FOREACH(QWidget* widget, d->m_widgets) {
|
||||
width = qMax(widget->sizeHint().width(), width);
|
||||
}
|
||||
Q_FOREACH(FormLayoutWidgetItem* item, d->m_wrWidgetItemList) {
|
||||
item->setWidth(width);
|
||||
item->formLayout()->update();
|
||||
}
|
||||
Q_FOREACH(GridColumnInfo info, d->m_gridColumnInfoList) {
|
||||
info.first->setColumnMinimumWidth(info.second, width);
|
||||
}
|
||||
int width = 0;
|
||||
Q_FOREACH(QWidget* widget, d->m_widgets) {
|
||||
width = qMax(widget->sizeHint().width(), width);
|
||||
}
|
||||
Q_FOREACH(FormLayoutWidgetItem* item, d->m_wrWidgetItemList) {
|
||||
item->setWidth(width);
|
||||
item->formLayout()->update();
|
||||
}
|
||||
Q_FOREACH(GridColumnInfo info, d->m_gridColumnInfoList) {
|
||||
info.first->setColumnMinimumWidth(info.second, width);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColumnResizer::eventFilter(QObject*, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Resize) {
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
return false;
|
||||
if (event->type() == QEvent::Resize) {
|
||||
d->scheduleWidthUpdate();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromLayout(QLayout* layout, int column)
|
||||
{
|
||||
Q_ASSERT(column >= 0);
|
||||
QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
|
||||
QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
|
||||
if (gridLayout) {
|
||||
addWidgetsFromGridLayout(gridLayout, column);
|
||||
} else if (formLayout) {
|
||||
if (column > QFormLayout::SpanningRole) {
|
||||
qCritical() << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout";
|
||||
return;
|
||||
}
|
||||
QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
|
||||
addWidgetsFromFormLayout(formLayout, role);
|
||||
} else {
|
||||
qCritical() << "Don't know how to handle layout" << layout;
|
||||
}
|
||||
Q_ASSERT(column >= 0);
|
||||
QGridLayout* gridLayout = qobject_cast<QGridLayout*>(layout);
|
||||
QFormLayout* formLayout = qobject_cast<QFormLayout*>(layout);
|
||||
if (gridLayout) {
|
||||
addWidgetsFromGridLayout(gridLayout, column);
|
||||
} else if (formLayout) {
|
||||
if (column > QFormLayout::SpanningRole) {
|
||||
qCritical() << "column should not be more than" << QFormLayout::SpanningRole << "for QFormLayout";
|
||||
return;
|
||||
}
|
||||
QFormLayout::ItemRole role = static_cast<QFormLayout::ItemRole>(column);
|
||||
addWidgetsFromFormLayout(formLayout, role);
|
||||
} else {
|
||||
qCritical() << "Don't know how to handle layout" << layout;
|
||||
}
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromGridLayout(QGridLayout* layout, int column)
|
||||
{
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAtPosition(row, column);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
addWidget(widget);
|
||||
}
|
||||
d->m_gridColumnInfoList << GridColumnInfo(layout, column);
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAtPosition(row, column);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
addWidget(widget);
|
||||
}
|
||||
d->m_gridColumnInfoList << GridColumnInfo(layout, column);
|
||||
}
|
||||
|
||||
void ColumnResizer::addWidgetsFromFormLayout(QFormLayout* layout, QFormLayout::ItemRole role)
|
||||
{
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAt(row, role);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
layout->removeItem(item);
|
||||
delete item;
|
||||
FormLayoutWidgetItem* newItem = new FormLayoutWidgetItem(widget, layout, role);
|
||||
layout->setItem(row, role, newItem);
|
||||
addWidget(widget);
|
||||
d->m_wrWidgetItemList << newItem;
|
||||
}
|
||||
for (int row = 0; row < layout->rowCount(); ++row) {
|
||||
QLayoutItem* item = layout->itemAt(row, role);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
QWidget* widget = item->widget();
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
layout->removeItem(item);
|
||||
delete item;
|
||||
FormLayoutWidgetItem* newItem = new FormLayoutWidgetItem(widget, layout, role);
|
||||
layout->setItem(row, role, newItem);
|
||||
addWidget(widget);
|
||||
d->m_wrWidgetItemList << newItem;
|
||||
}
|
||||
}
|
||||
|
@ -18,24 +18,24 @@ class QWidget;
|
||||
class ColumnResizerPrivate;
|
||||
class ColumnResizer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColumnResizer(QObject* parent = 0);
|
||||
~ColumnResizer();
|
||||
ColumnResizer(QObject* parent = 0);
|
||||
~ColumnResizer();
|
||||
|
||||
void addWidget(QWidget* widget);
|
||||
void addWidgetsFromLayout(QLayout*, int column);
|
||||
void addWidgetsFromGridLayout(QGridLayout*, int column);
|
||||
void addWidgetsFromFormLayout(QFormLayout*, QFormLayout::ItemRole role);
|
||||
void addWidget(QWidget* widget);
|
||||
void addWidgetsFromLayout(QLayout*, int column);
|
||||
void addWidgetsFromGridLayout(QGridLayout*, int column);
|
||||
void addWidgetsFromFormLayout(QFormLayout*, QFormLayout::ItemRole role);
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateWidth();
|
||||
void updateWidth();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject*, QEvent* event);
|
||||
bool eventFilter(QObject*, QEvent* event);
|
||||
|
||||
private:
|
||||
ColumnResizerPrivate* const d;
|
||||
ColumnResizerPrivate* const d;
|
||||
};
|
||||
|
||||
#endif /* COLUMNRESIZER_H */
|
||||
|
@ -15,117 +15,117 @@
|
||||
|
||||
QString GuiUtil::uploadPaste(const QString &text, QWidget *parentWidget)
|
||||
{
|
||||
ProgressDialog dialog(parentWidget);
|
||||
auto APIKeySetting = MMC->settings()->get("PasteEEAPIKey").toString();
|
||||
if(APIKeySetting == "multimc")
|
||||
{
|
||||
APIKeySetting = BuildConfig.PASTE_EE_KEY;
|
||||
}
|
||||
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, text, APIKeySetting));
|
||||
ProgressDialog dialog(parentWidget);
|
||||
auto APIKeySetting = MMC->settings()->get("PasteEEAPIKey").toString();
|
||||
if(APIKeySetting == "multimc")
|
||||
{
|
||||
APIKeySetting = BuildConfig.PASTE_EE_KEY;
|
||||
}
|
||||
std::unique_ptr<PasteUpload> paste(new PasteUpload(parentWidget, text, APIKeySetting));
|
||||
|
||||
if (!paste->validateText())
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload failed"),
|
||||
QObject::tr("The log file is too big. You'll have to upload it manually."),
|
||||
QMessageBox::Warning)->exec();
|
||||
return QString();
|
||||
}
|
||||
if (!paste->validateText())
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload failed"),
|
||||
QObject::tr("The log file is too big. You'll have to upload it manually."),
|
||||
QMessageBox::Warning)->exec();
|
||||
return QString();
|
||||
}
|
||||
|
||||
dialog.execWithTask(paste.get());
|
||||
if (!paste->wasSuccessful())
|
||||
{
|
||||
CustomMessageBox::selectable(parentWidget, QObject::tr("Upload failed"),
|
||||
paste->failReason(), QMessageBox::Critical)->exec();
|
||||
return QString();
|
||||
}
|
||||
else
|
||||
{
|
||||
const QString link = paste->pasteLink();
|
||||
setClipboardText(link);
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload finished"),
|
||||
QObject::tr("The <a href=\"%1\">link to the uploaded log</a> has been placed in your clipboard.").arg(link),
|
||||
QMessageBox::Information)->exec();
|
||||
return link;
|
||||
}
|
||||
dialog.execWithTask(paste.get());
|
||||
if (!paste->wasSuccessful())
|
||||
{
|
||||
CustomMessageBox::selectable(parentWidget, QObject::tr("Upload failed"),
|
||||
paste->failReason(), QMessageBox::Critical)->exec();
|
||||
return QString();
|
||||
}
|
||||
else
|
||||
{
|
||||
const QString link = paste->pasteLink();
|
||||
setClipboardText(link);
|
||||
CustomMessageBox::selectable(
|
||||
parentWidget, QObject::tr("Upload finished"),
|
||||
QObject::tr("The <a href=\"%1\">link to the uploaded log</a> has been placed in your clipboard.").arg(link),
|
||||
QMessageBox::Information)->exec();
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiUtil::setClipboardText(const QString &text)
|
||||
{
|
||||
QApplication::clipboard()->setText(text);
|
||||
QApplication::clipboard()->setText(text);
|
||||
}
|
||||
|
||||
static QStringList BrowseForFileInternal(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget, bool single)
|
||||
{
|
||||
static QMap<QString, QString> savedPaths;
|
||||
static QMap<QString, QString> savedPaths;
|
||||
|
||||
QFileDialog w(parentWidget, caption);
|
||||
QSet<QString> locations;
|
||||
auto f = [&](QStandardPaths::StandardLocation l)
|
||||
{
|
||||
QString location = QStandardPaths::writableLocation(l);
|
||||
QFileInfo finfo(location);
|
||||
if (!finfo.exists())
|
||||
return;
|
||||
locations.insert(location);
|
||||
};
|
||||
f(QStandardPaths::DesktopLocation);
|
||||
f(QStandardPaths::DocumentsLocation);
|
||||
f(QStandardPaths::DownloadLocation);
|
||||
f(QStandardPaths::HomeLocation);
|
||||
QList<QUrl> urls;
|
||||
for (auto location : locations)
|
||||
{
|
||||
urls.append(QUrl::fromLocalFile(location));
|
||||
}
|
||||
urls.append(QUrl::fromLocalFile(defaultPath));
|
||||
QFileDialog w(parentWidget, caption);
|
||||
QSet<QString> locations;
|
||||
auto f = [&](QStandardPaths::StandardLocation l)
|
||||
{
|
||||
QString location = QStandardPaths::writableLocation(l);
|
||||
QFileInfo finfo(location);
|
||||
if (!finfo.exists())
|
||||
return;
|
||||
locations.insert(location);
|
||||
};
|
||||
f(QStandardPaths::DesktopLocation);
|
||||
f(QStandardPaths::DocumentsLocation);
|
||||
f(QStandardPaths::DownloadLocation);
|
||||
f(QStandardPaths::HomeLocation);
|
||||
QList<QUrl> urls;
|
||||
for (auto location : locations)
|
||||
{
|
||||
urls.append(QUrl::fromLocalFile(location));
|
||||
}
|
||||
urls.append(QUrl::fromLocalFile(defaultPath));
|
||||
|
||||
w.setFileMode(single ? QFileDialog::ExistingFile : QFileDialog::ExistingFiles);
|
||||
w.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
w.setNameFilter(filter);
|
||||
w.setFileMode(single ? QFileDialog::ExistingFile : QFileDialog::ExistingFiles);
|
||||
w.setAcceptMode(QFileDialog::AcceptOpen);
|
||||
w.setNameFilter(filter);
|
||||
|
||||
QString pathToOpen;
|
||||
if(savedPaths.contains(context))
|
||||
{
|
||||
pathToOpen = savedPaths[context];
|
||||
}
|
||||
else
|
||||
{
|
||||
pathToOpen = defaultPath;
|
||||
}
|
||||
if(!pathToOpen.isEmpty())
|
||||
{
|
||||
QFileInfo finfo(pathToOpen);
|
||||
if(finfo.exists() && finfo.isDir())
|
||||
{
|
||||
w.setDirectory(finfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
QString pathToOpen;
|
||||
if(savedPaths.contains(context))
|
||||
{
|
||||
pathToOpen = savedPaths[context];
|
||||
}
|
||||
else
|
||||
{
|
||||
pathToOpen = defaultPath;
|
||||
}
|
||||
if(!pathToOpen.isEmpty())
|
||||
{
|
||||
QFileInfo finfo(pathToOpen);
|
||||
if(finfo.exists() && finfo.isDir())
|
||||
{
|
||||
w.setDirectory(finfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
w.setSidebarUrls(urls);
|
||||
w.setSidebarUrls(urls);
|
||||
|
||||
if (w.exec())
|
||||
{
|
||||
savedPaths[context] = w.directory().absolutePath();
|
||||
return w.selectedFiles();
|
||||
}
|
||||
savedPaths[context] = w.directory().absolutePath();
|
||||
return {};
|
||||
if (w.exec())
|
||||
{
|
||||
savedPaths[context] = w.directory().absolutePath();
|
||||
return w.selectedFiles();
|
||||
}
|
||||
savedPaths[context] = w.directory().absolutePath();
|
||||
return {};
|
||||
}
|
||||
|
||||
QString GuiUtil::BrowseForFile(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget)
|
||||
{
|
||||
auto resultList = BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, true);
|
||||
if(resultList.size())
|
||||
{
|
||||
return resultList[0];
|
||||
}
|
||||
return QString();
|
||||
auto resultList = BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, true);
|
||||
if(resultList.size())
|
||||
{
|
||||
return resultList[0];
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
QStringList GuiUtil::BrowseForFiles(QString context, QString caption, QString filter, QString defaultPath, QWidget *parentWidget)
|
||||
{
|
||||
return BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, false);
|
||||
return BrowseForFileInternal(context, caption, filter, defaultPath, parentWidget, false);
|
||||
}
|
||||
|
@ -25,52 +25,52 @@
|
||||
class HoeDown
|
||||
{
|
||||
public:
|
||||
class buffer
|
||||
{
|
||||
public:
|
||||
buffer(size_t unit = 4096)
|
||||
{
|
||||
buf = hoedown_buffer_new(unit);
|
||||
}
|
||||
~buffer()
|
||||
{
|
||||
hoedown_buffer_free(buf);
|
||||
}
|
||||
const char * cstr()
|
||||
{
|
||||
return hoedown_buffer_cstr(buf);
|
||||
}
|
||||
void put(QByteArray input)
|
||||
{
|
||||
hoedown_buffer_put(buf, (uint8_t *) input.data(), input.size());
|
||||
}
|
||||
const uint8_t * data() const
|
||||
{
|
||||
return buf->data;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
return buf->size;
|
||||
}
|
||||
hoedown_buffer * buf;
|
||||
} ib, ob;
|
||||
HoeDown()
|
||||
{
|
||||
renderer = hoedown_html_renderer_new((hoedown_html_flags) 0,0);
|
||||
document = hoedown_document_new(renderer, (hoedown_extensions) 0, 8);
|
||||
}
|
||||
~HoeDown()
|
||||
{
|
||||
hoedown_document_free(document);
|
||||
hoedown_html_renderer_free(renderer);
|
||||
}
|
||||
QString process(QByteArray input)
|
||||
{
|
||||
ib.put(input);
|
||||
hoedown_document_render(document, ob.buf, ib.data(), ib.size());
|
||||
return ob.cstr();
|
||||
}
|
||||
class buffer
|
||||
{
|
||||
public:
|
||||
buffer(size_t unit = 4096)
|
||||
{
|
||||
buf = hoedown_buffer_new(unit);
|
||||
}
|
||||
~buffer()
|
||||
{
|
||||
hoedown_buffer_free(buf);
|
||||
}
|
||||
const char * cstr()
|
||||
{
|
||||
return hoedown_buffer_cstr(buf);
|
||||
}
|
||||
void put(QByteArray input)
|
||||
{
|
||||
hoedown_buffer_put(buf, (uint8_t *) input.data(), input.size());
|
||||
}
|
||||
const uint8_t * data() const
|
||||
{
|
||||
return buf->data;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
return buf->size;
|
||||
}
|
||||
hoedown_buffer * buf;
|
||||
} ib, ob;
|
||||
HoeDown()
|
||||
{
|
||||
renderer = hoedown_html_renderer_new((hoedown_html_flags) 0,0);
|
||||
document = hoedown_document_new(renderer, (hoedown_extensions) 0, 8);
|
||||
}
|
||||
~HoeDown()
|
||||
{
|
||||
hoedown_document_free(document);
|
||||
hoedown_html_renderer_free(renderer);
|
||||
}
|
||||
QString process(QByteArray input)
|
||||
{
|
||||
ib.put(input);
|
||||
hoedown_document_render(document, ob.buf, ib.data(), ib.size());
|
||||
return ob.cstr();
|
||||
}
|
||||
private:
|
||||
hoedown_document * document;
|
||||
hoedown_renderer * renderer;
|
||||
hoedown_document * document;
|
||||
hoedown_renderer * renderer;
|
||||
};
|
||||
|
@ -21,57 +21,57 @@
|
||||
|
||||
class InstancePageProvider : public QObject, public BasePageProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InstancePageProvider(InstancePtr parent)
|
||||
{
|
||||
inst = parent;
|
||||
}
|
||||
explicit InstancePageProvider(InstancePtr parent)
|
||||
{
|
||||
inst = parent;
|
||||
}
|
||||
|
||||
virtual ~InstancePageProvider() {};
|
||||
virtual QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> values;
|
||||
values.append(new LogPage(inst));
|
||||
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
|
||||
if(onesix)
|
||||
{
|
||||
values.append(new VersionPage(onesix.get()));
|
||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
|
||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||
values.append(modsPage);
|
||||
auto modsPage2 = new NewModFolderPage(onesix.get(), onesix->modsModel(), "newmods", "newloadermods", tr("New loader mods"), "New-loader-mods");
|
||||
modsPage2->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||
values.append(modsPage2);
|
||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
|
||||
values.append(new ResourcePackPage(onesix.get()));
|
||||
values.append(new TexturePackPage(onesix.get()));
|
||||
values.append(new NotesPage(onesix.get()));
|
||||
values.append(new WorldListPage(onesix.get(), onesix->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds"));
|
||||
values.append(new ServersPage(onesix.get()));
|
||||
values.append(new ScreenshotsPage(FS::PathCombine(onesix->minecraftRoot(), "screenshots")));
|
||||
values.append(new InstanceSettingsPage(onesix.get()));
|
||||
}
|
||||
std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst);
|
||||
if(legacy)
|
||||
{
|
||||
values.append(new LegacyUpgradePage(legacy));
|
||||
values.append(new NotesPage(legacy.get()));
|
||||
values.append(new WorldListPage(legacy.get(), legacy->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds"));
|
||||
values.append(new ScreenshotsPage(FS::PathCombine(legacy->minecraftRoot(), "screenshots")));
|
||||
}
|
||||
auto logMatcher = inst->getLogFileMatcher();
|
||||
if(logMatcher)
|
||||
{
|
||||
values.append(new OtherLogsPage(inst->getLogFileRoot(), logMatcher));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
virtual ~InstancePageProvider() {};
|
||||
virtual QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> values;
|
||||
values.append(new LogPage(inst));
|
||||
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
|
||||
if(onesix)
|
||||
{
|
||||
values.append(new VersionPage(onesix.get()));
|
||||
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList(), "mods", "loadermods", tr("Loader mods"), "Loader-mods");
|
||||
modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||
values.append(modsPage);
|
||||
auto modsPage2 = new NewModFolderPage(onesix.get(), onesix->modsModel(), "newmods", "newloadermods", tr("New loader mods"), "New-loader-mods");
|
||||
modsPage2->setFilter("%1 (*.zip *.jar *.litemod)");
|
||||
values.append(modsPage2);
|
||||
values.append(new CoreModFolderPage(onesix.get(), onesix->coreModList(), "coremods", "coremods", tr("Core mods"), "Core-mods"));
|
||||
values.append(new ResourcePackPage(onesix.get()));
|
||||
values.append(new TexturePackPage(onesix.get()));
|
||||
values.append(new NotesPage(onesix.get()));
|
||||
values.append(new WorldListPage(onesix.get(), onesix->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds"));
|
||||
values.append(new ServersPage(onesix.get()));
|
||||
values.append(new ScreenshotsPage(FS::PathCombine(onesix->minecraftRoot(), "screenshots")));
|
||||
values.append(new InstanceSettingsPage(onesix.get()));
|
||||
}
|
||||
std::shared_ptr<LegacyInstance> legacy = std::dynamic_pointer_cast<LegacyInstance>(inst);
|
||||
if(legacy)
|
||||
{
|
||||
values.append(new LegacyUpgradePage(legacy));
|
||||
values.append(new NotesPage(legacy.get()));
|
||||
values.append(new WorldListPage(legacy.get(), legacy->worldList(), "worlds", "worlds", tr("Worlds"), "Worlds"));
|
||||
values.append(new ScreenshotsPage(FS::PathCombine(legacy->minecraftRoot(), "screenshots")));
|
||||
}
|
||||
auto logMatcher = inst->getLogFileMatcher();
|
||||
if(logMatcher)
|
||||
{
|
||||
values.append(new OtherLogsPage(inst->getLogFileRoot(), logMatcher));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
virtual QString dialogTitle() override
|
||||
{
|
||||
return tr("Edit Instance (%1)").arg(inst->name());
|
||||
}
|
||||
virtual QString dialogTitle() override
|
||||
{
|
||||
return tr("Edit Instance (%1)").arg(inst->name());
|
||||
}
|
||||
protected:
|
||||
InstancePtr inst;
|
||||
InstancePtr inst;
|
||||
};
|
||||
|
@ -9,26 +9,26 @@ InstanceProxyModel::InstanceProxyModel(QObject *parent) : GroupedProxyModel(pare
|
||||
|
||||
QVariant InstanceProxyModel::data(const QModelIndex & index, int role) const
|
||||
{
|
||||
QVariant data = QSortFilterProxyModel::data(index, role);
|
||||
if(role == Qt::DecorationRole)
|
||||
{
|
||||
return QVariant(MMC->icons()->getIcon(data.toString()));
|
||||
}
|
||||
return data;
|
||||
QVariant data = QSortFilterProxyModel::data(index, role);
|
||||
if(role == Qt::DecorationRole)
|
||||
{
|
||||
return QVariant(MMC->icons()->getIcon(data.toString()));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
bool InstanceProxyModel::subSortLessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const
|
||||
const QModelIndex &right) const
|
||||
{
|
||||
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
|
||||
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
|
||||
QString sortMode = MMC->settings()->get("InstSortMode").toString();
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0;
|
||||
}
|
||||
BaseInstance *pdataLeft = static_cast<BaseInstance *>(left.internalPointer());
|
||||
BaseInstance *pdataRight = static_cast<BaseInstance *>(right.internalPointer());
|
||||
QString sortMode = MMC->settings()->get("InstSortMode").toString();
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
return pdataLeft->lastLaunch() > pdataRight->lastLaunch();
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString::localeAwareCompare(pdataLeft->name(), pdataRight->name()) < 0;
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,9 @@
|
||||
class InstanceProxyModel : public GroupedProxyModel
|
||||
{
|
||||
public:
|
||||
explicit InstanceProxyModel(QObject *parent = 0);
|
||||
QVariant data(const QModelIndex & index, int role) const override;
|
||||
explicit InstanceProxyModel(QObject *parent = 0);
|
||||
QVariant data(const QModelIndex & index, int role) const override;
|
||||
|
||||
protected:
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
};
|
||||
|
@ -31,184 +31,184 @@
|
||||
#include "icons/IconList.h"
|
||||
|
||||
InstanceWindow::InstanceWindow(InstancePtr instance, QWidget *parent)
|
||||
: QMainWindow(parent), m_instance(instance)
|
||||
: QMainWindow(parent), m_instance(instance)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto icon = MMC->icons()->getIcon(m_instance->iconKey());
|
||||
QString windowTitle = tr("Console window for ") + m_instance->name();
|
||||
auto icon = MMC->icons()->getIcon(m_instance->iconKey());
|
||||
QString windowTitle = tr("Console window for ") + m_instance->name();
|
||||
|
||||
// Set window properties
|
||||
{
|
||||
setWindowIcon(icon);
|
||||
setWindowTitle(windowTitle);
|
||||
}
|
||||
// Set window properties
|
||||
{
|
||||
setWindowIcon(icon);
|
||||
setWindowTitle(windowTitle);
|
||||
}
|
||||
|
||||
// Add page container
|
||||
{
|
||||
auto provider = std::make_shared<InstancePageProvider>(m_instance);
|
||||
m_container = new PageContainer(provider.get(), "console", this);
|
||||
m_container->setParentContainer(this);
|
||||
setCentralWidget(m_container);
|
||||
}
|
||||
// Add page container
|
||||
{
|
||||
auto provider = std::make_shared<InstancePageProvider>(m_instance);
|
||||
m_container = new PageContainer(provider.get(), "console", this);
|
||||
m_container->setParentContainer(this);
|
||||
setCentralWidget(m_container);
|
||||
}
|
||||
|
||||
// Add custom buttons to the page container layout.
|
||||
{
|
||||
auto horizontalLayout = new QHBoxLayout();
|
||||
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
horizontalLayout->setContentsMargins(6, -1, 6, -1);
|
||||
// Add custom buttons to the page container layout.
|
||||
{
|
||||
auto horizontalLayout = new QHBoxLayout();
|
||||
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
horizontalLayout->setContentsMargins(6, -1, 6, -1);
|
||||
|
||||
auto btnHelp = new QPushButton();
|
||||
btnHelp->setText(tr("Help"));
|
||||
horizontalLayout->addWidget(btnHelp);
|
||||
connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
|
||||
auto btnHelp = new QPushButton();
|
||||
btnHelp->setText(tr("Help"));
|
||||
horizontalLayout->addWidget(btnHelp);
|
||||
connect(btnHelp, SIGNAL(clicked(bool)), m_container, SLOT(help()));
|
||||
|
||||
auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addSpacerItem(spacer);
|
||||
auto spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
horizontalLayout->addSpacerItem(spacer);
|
||||
|
||||
m_killButton = new QPushButton();
|
||||
horizontalLayout->addWidget(m_killButton);
|
||||
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
||||
m_killButton = new QPushButton();
|
||||
horizontalLayout->addWidget(m_killButton);
|
||||
connect(m_killButton, SIGNAL(clicked(bool)), SLOT(on_btnKillMinecraft_clicked()));
|
||||
|
||||
m_launchOfflineButton = new QPushButton();
|
||||
horizontalLayout->addWidget(m_launchOfflineButton);
|
||||
m_launchOfflineButton->setText(tr("Launch Offline"));
|
||||
updateLaunchButtons();
|
||||
connect(m_launchOfflineButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftOffline_clicked()));
|
||||
m_launchOfflineButton = new QPushButton();
|
||||
horizontalLayout->addWidget(m_launchOfflineButton);
|
||||
m_launchOfflineButton->setText(tr("Launch Offline"));
|
||||
updateLaunchButtons();
|
||||
connect(m_launchOfflineButton, SIGNAL(clicked(bool)), SLOT(on_btnLaunchMinecraftOffline_clicked()));
|
||||
|
||||
m_closeButton = new QPushButton();
|
||||
m_closeButton->setText(tr("Close"));
|
||||
horizontalLayout->addWidget(m_closeButton);
|
||||
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
|
||||
m_closeButton = new QPushButton();
|
||||
m_closeButton->setText(tr("Close"));
|
||||
horizontalLayout->addWidget(m_closeButton);
|
||||
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(on_closeButton_clicked()));
|
||||
|
||||
m_container->addButtons(horizontalLayout);
|
||||
}
|
||||
m_container->addButtons(horizontalLayout);
|
||||
}
|
||||
|
||||
// restore window state
|
||||
{
|
||||
auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
|
||||
restoreState(QByteArray::fromBase64(base64State));
|
||||
auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
|
||||
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
||||
}
|
||||
// restore window state
|
||||
{
|
||||
auto base64State = MMC->settings()->get("ConsoleWindowState").toByteArray();
|
||||
restoreState(QByteArray::fromBase64(base64State));
|
||||
auto base64Geometry = MMC->settings()->get("ConsoleWindowGeometry").toByteArray();
|
||||
restoreGeometry(QByteArray::fromBase64(base64Geometry));
|
||||
}
|
||||
|
||||
// set up instance and launch process recognition
|
||||
{
|
||||
auto launchTask = m_instance->getLaunchTask();
|
||||
on_InstanceLaunchTask_changed(launchTask);
|
||||
connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &InstanceWindow::on_InstanceLaunchTask_changed);
|
||||
connect(m_instance.get(), &BaseInstance::runningStatusChanged, this, &InstanceWindow::on_RunningState_changed);
|
||||
}
|
||||
// set up instance and launch process recognition
|
||||
{
|
||||
auto launchTask = m_instance->getLaunchTask();
|
||||
on_InstanceLaunchTask_changed(launchTask);
|
||||
connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &InstanceWindow::on_InstanceLaunchTask_changed);
|
||||
connect(m_instance.get(), &BaseInstance::runningStatusChanged, this, &InstanceWindow::on_RunningState_changed);
|
||||
}
|
||||
|
||||
// set up instance destruction detection
|
||||
{
|
||||
connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged);
|
||||
}
|
||||
show();
|
||||
// set up instance destruction detection
|
||||
{
|
||||
connect(m_instance.get(), &BaseInstance::statusChanged, this, &InstanceWindow::on_instanceStatusChanged);
|
||||
}
|
||||
show();
|
||||
}
|
||||
|
||||
void InstanceWindow::on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus)
|
||||
{
|
||||
if(newStatus == BaseInstance::Status::Gone)
|
||||
{
|
||||
m_doNotSave = true;
|
||||
close();
|
||||
}
|
||||
if(newStatus == BaseInstance::Status::Gone)
|
||||
{
|
||||
m_doNotSave = true;
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::updateLaunchButtons()
|
||||
{
|
||||
if(m_instance->isRunning())
|
||||
{
|
||||
m_launchOfflineButton->setEnabled(false);
|
||||
m_killButton->setText(tr("Kill"));
|
||||
m_killButton->setToolTip(tr("Kill the running instance"));
|
||||
}
|
||||
else if(!m_instance->canLaunch())
|
||||
{
|
||||
m_launchOfflineButton->setEnabled(false);
|
||||
m_killButton->setText(tr("Launch"));
|
||||
m_killButton->setToolTip(tr("Launch the instance"));
|
||||
m_killButton->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_launchOfflineButton->setEnabled(true);
|
||||
m_killButton->setText(tr("Launch"));
|
||||
m_killButton->setToolTip(tr("Launch the instance"));
|
||||
}
|
||||
if(m_instance->isRunning())
|
||||
{
|
||||
m_launchOfflineButton->setEnabled(false);
|
||||
m_killButton->setText(tr("Kill"));
|
||||
m_killButton->setToolTip(tr("Kill the running instance"));
|
||||
}
|
||||
else if(!m_instance->canLaunch())
|
||||
{
|
||||
m_launchOfflineButton->setEnabled(false);
|
||||
m_killButton->setText(tr("Launch"));
|
||||
m_killButton->setToolTip(tr("Launch the instance"));
|
||||
m_killButton->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_launchOfflineButton->setEnabled(true);
|
||||
m_killButton->setText(tr("Launch"));
|
||||
m_killButton->setToolTip(tr("Launch the instance"));
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceWindow::on_btnLaunchMinecraftOffline_clicked()
|
||||
{
|
||||
MMC->launch(m_instance, false, nullptr);
|
||||
MMC->launch(m_instance, false, nullptr);
|
||||
}
|
||||
|
||||
void InstanceWindow::on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc)
|
||||
{
|
||||
m_proc = proc;
|
||||
m_proc = proc;
|
||||
}
|
||||
|
||||
void InstanceWindow::on_RunningState_changed(bool)
|
||||
{
|
||||
updateLaunchButtons();
|
||||
m_container->refreshContainer();
|
||||
updateLaunchButtons();
|
||||
m_container->refreshContainer();
|
||||
}
|
||||
|
||||
void InstanceWindow::on_closeButton_clicked()
|
||||
{
|
||||
close();
|
||||
close();
|
||||
}
|
||||
|
||||
void InstanceWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
bool proceed = true;
|
||||
if(!m_doNotSave)
|
||||
{
|
||||
proceed &= m_container->prepareToClose();
|
||||
}
|
||||
bool proceed = true;
|
||||
if(!m_doNotSave)
|
||||
{
|
||||
proceed &= m_container->prepareToClose();
|
||||
}
|
||||
|
||||
if(!proceed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!proceed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
|
||||
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
||||
emit isClosing();
|
||||
event->accept();
|
||||
MMC->settings()->set("ConsoleWindowState", saveState().toBase64());
|
||||
MMC->settings()->set("ConsoleWindowGeometry", saveGeometry().toBase64());
|
||||
emit isClosing();
|
||||
event->accept();
|
||||
}
|
||||
|
||||
bool InstanceWindow::saveAll()
|
||||
{
|
||||
return m_container->saveAll();
|
||||
return m_container->saveAll();
|
||||
}
|
||||
|
||||
void InstanceWindow::on_btnKillMinecraft_clicked()
|
||||
{
|
||||
if(m_instance->isRunning())
|
||||
{
|
||||
MMC->kill(m_instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC->launch(m_instance, true, nullptr);
|
||||
}
|
||||
if(m_instance->isRunning())
|
||||
{
|
||||
MMC->kill(m_instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC->launch(m_instance, true, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
QString InstanceWindow::instanceId()
|
||||
{
|
||||
return m_instance->id();
|
||||
return m_instance->id();
|
||||
}
|
||||
|
||||
bool InstanceWindow::selectPage(QString pageId)
|
||||
{
|
||||
return m_container->selectPage(pageId);
|
||||
return m_container->selectPage(pageId);
|
||||
}
|
||||
|
||||
void InstanceWindow::refreshContainer()
|
||||
{
|
||||
m_container->refreshContainer();
|
||||
m_container->refreshContainer();
|
||||
}
|
||||
|
||||
InstanceWindow::~InstanceWindow()
|
||||
@ -217,10 +217,10 @@ InstanceWindow::~InstanceWindow()
|
||||
|
||||
bool InstanceWindow::requestClose()
|
||||
{
|
||||
if(m_container->prepareToClose())
|
||||
{
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if(m_container->prepareToClose())
|
||||
{
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -26,48 +26,48 @@ class QPushButton;
|
||||
class PageContainer;
|
||||
class InstanceWindow : public QMainWindow, public BasePageContainer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit InstanceWindow(InstancePtr proc, QWidget *parent = 0);
|
||||
virtual ~InstanceWindow();
|
||||
explicit InstanceWindow(InstancePtr proc, QWidget *parent = 0);
|
||||
virtual ~InstanceWindow();
|
||||
|
||||
bool selectPage(QString pageId) override;
|
||||
void refreshContainer() override;
|
||||
bool selectPage(QString pageId) override;
|
||||
void refreshContainer() override;
|
||||
|
||||
QString instanceId();
|
||||
QString instanceId();
|
||||
|
||||
// save all settings and changes (prepare for launch)
|
||||
bool saveAll();
|
||||
// save all settings and changes (prepare for launch)
|
||||
bool saveAll();
|
||||
|
||||
// request closing the window (from a page)
|
||||
bool requestClose() override;
|
||||
// request closing the window (from a page)
|
||||
bool requestClose() override;
|
||||
|
||||
signals:
|
||||
void isClosing();
|
||||
void isClosing();
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_closeButton_clicked();
|
||||
void on_btnKillMinecraft_clicked();
|
||||
void on_btnLaunchMinecraftOffline_clicked();
|
||||
void on_closeButton_clicked();
|
||||
void on_btnKillMinecraft_clicked();
|
||||
void on_btnLaunchMinecraftOffline_clicked();
|
||||
|
||||
void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
|
||||
void on_RunningState_changed(bool running);
|
||||
void on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus);
|
||||
void on_InstanceLaunchTask_changed(std::shared_ptr<LaunchTask> proc);
|
||||
void on_RunningState_changed(bool running);
|
||||
void on_instanceStatusChanged(BaseInstance::Status, BaseInstance::Status newStatus);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
|
||||
private:
|
||||
void updateLaunchButtons();
|
||||
void updateLaunchButtons();
|
||||
|
||||
private:
|
||||
std::shared_ptr<LaunchTask> m_proc;
|
||||
InstancePtr m_instance;
|
||||
bool m_doNotSave = false;
|
||||
PageContainer *m_container = nullptr;
|
||||
QPushButton *m_closeButton = nullptr;
|
||||
QPushButton *m_killButton = nullptr;
|
||||
QPushButton *m_launchOfflineButton = nullptr;
|
||||
std::shared_ptr<LaunchTask> m_proc;
|
||||
InstancePtr m_instance;
|
||||
bool m_doNotSave = false;
|
||||
PageContainer *m_container = nullptr;
|
||||
QPushButton *m_closeButton = nullptr;
|
||||
QPushButton *m_killButton = nullptr;
|
||||
QPushButton *m_launchOfflineButton = nullptr;
|
||||
};
|
||||
|
@ -4,100 +4,100 @@
|
||||
|
||||
bool JavaCommon::checkJVMArgs(QString jvmargs, QWidget *parent)
|
||||
{
|
||||
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]"))
|
||||
|| jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize"))
|
||||
{
|
||||
auto warnStr = QObject::tr(
|
||||
"You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" or \"-Xms\").\n"
|
||||
"There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n"
|
||||
"This message will be displayed until you remove them from the JVM arguments.");
|
||||
CustomMessageBox::selectable(
|
||||
parent, QObject::tr("JVM arguments warning"),
|
||||
warnStr,
|
||||
QMessageBox::Warning)->exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (jvmargs.contains("-XX:PermSize=") || jvmargs.contains(QRegExp("-Xm[sx]"))
|
||||
|| jvmargs.contains("-XX-MaxHeapSize") || jvmargs.contains("-XX:InitialHeapSize"))
|
||||
{
|
||||
auto warnStr = QObject::tr(
|
||||
"You tried to manually set a JVM memory option (using \"-XX:PermSize\", \"-XX-MaxHeapSize\", \"-XX:InitialHeapSize\", \"-Xmx\" or \"-Xms\").\n"
|
||||
"There are dedicated boxes for these in the settings (Java tab, in the Memory group at the top).\n"
|
||||
"This message will be displayed until you remove them from the JVM arguments.");
|
||||
CustomMessageBox::selectable(
|
||||
parent, QObject::tr("JVM arguments warning"),
|
||||
warnStr,
|
||||
QMessageBox::Warning)->exec();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void JavaCommon::javaWasOk(QWidget *parent, JavaCheckResult result)
|
||||
{
|
||||
QString text;
|
||||
text += QObject::tr("Java test succeeded!<br />Platform reported: %1<br />Java version "
|
||||
"reported: %2<br />").arg(result.realPlatform, result.javaVersion.toString());
|
||||
if (result.errorLog.size())
|
||||
{
|
||||
auto htmlError = result.errorLog;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += QObject::tr("<br />Warnings:<br /><font color=\"orange\">%1</font>").arg(htmlError);
|
||||
}
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test success"), text, QMessageBox::Information)->show();
|
||||
QString text;
|
||||
text += QObject::tr("Java test succeeded!<br />Platform reported: %1<br />Java version "
|
||||
"reported: %2<br />").arg(result.realPlatform, result.javaVersion.toString());
|
||||
if (result.errorLog.size())
|
||||
{
|
||||
auto htmlError = result.errorLog;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += QObject::tr("<br />Warnings:<br /><font color=\"orange\">%1</font>").arg(htmlError);
|
||||
}
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test success"), text, QMessageBox::Information)->show();
|
||||
}
|
||||
|
||||
void JavaCommon::javaArgsWereBad(QWidget *parent, JavaCheckResult result)
|
||||
{
|
||||
auto htmlError = result.errorLog;
|
||||
QString text;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += QObject::tr("The specified java binary didn't work with the arguments you provided:<br />");
|
||||
text += QString("<font color=\"red\">%1</font>").arg(htmlError);
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||
auto htmlError = result.errorLog;
|
||||
QString text;
|
||||
htmlError.replace('\n', "<br />");
|
||||
text += QObject::tr("The specified java binary didn't work with the arguments you provided:<br />");
|
||||
text += QString("<font color=\"red\">%1</font>").arg(htmlError);
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||
}
|
||||
|
||||
void JavaCommon::javaBinaryWasBad(QWidget *parent, JavaCheckResult result)
|
||||
{
|
||||
QString text;
|
||||
text += QObject::tr(
|
||||
"The specified java binary didn't work.<br />You should use the auto-detect feature, "
|
||||
"or set the path to the java executable.<br />");
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||
QString text;
|
||||
text += QObject::tr(
|
||||
"The specified java binary didn't work.<br />You should use the auto-detect feature, "
|
||||
"or set the path to the java executable.<br />");
|
||||
CustomMessageBox::selectable(parent, QObject::tr("Java test failure"), text, QMessageBox::Warning)->show();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::run()
|
||||
{
|
||||
if (!JavaCommon::checkJVMArgs(m_args, m_parent))
|
||||
{
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinished(JavaCheckResult)));
|
||||
checker->m_path = m_path;
|
||||
checker->performCheck();
|
||||
if (!JavaCommon::checkJVMArgs(m_args, m_parent))
|
||||
{
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinished(JavaCheckResult)));
|
||||
checker->m_path = m_path;
|
||||
checker->performCheck();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::checkFinished(JavaCheckResult result)
|
||||
{
|
||||
if (result.validity != JavaCheckResult::Validity::Valid)
|
||||
{
|
||||
javaBinaryWasBad(m_parent, result);
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinishedWithArgs(JavaCheckResult)));
|
||||
checker->m_path = m_path;
|
||||
checker->m_args = m_args;
|
||||
checker->m_minMem = m_minMem;
|
||||
checker->m_maxMem = m_maxMem;
|
||||
if (result.javaVersion.requiresPermGen())
|
||||
{
|
||||
checker->m_permGen = m_permGen;
|
||||
}
|
||||
checker->performCheck();
|
||||
if (result.validity != JavaCheckResult::Validity::Valid)
|
||||
{
|
||||
javaBinaryWasBad(m_parent, result);
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaChecker());
|
||||
connect(checker.get(), SIGNAL(checkFinished(JavaCheckResult)), this,
|
||||
SLOT(checkFinishedWithArgs(JavaCheckResult)));
|
||||
checker->m_path = m_path;
|
||||
checker->m_args = m_args;
|
||||
checker->m_minMem = m_minMem;
|
||||
checker->m_maxMem = m_maxMem;
|
||||
if (result.javaVersion.requiresPermGen())
|
||||
{
|
||||
checker->m_permGen = m_permGen;
|
||||
}
|
||||
checker->performCheck();
|
||||
}
|
||||
|
||||
void JavaCommon::TestCheck::checkFinishedWithArgs(JavaCheckResult result)
|
||||
{
|
||||
if (result.validity == JavaCheckResult::Validity::Valid)
|
||||
{
|
||||
javaWasOk(m_parent, result);
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
javaArgsWereBad(m_parent, result);
|
||||
emit finished();
|
||||
if (result.validity == JavaCheckResult::Validity::Valid)
|
||||
{
|
||||
javaWasOk(m_parent, result);
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
javaArgsWereBad(m_parent, result);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
|
@ -8,41 +8,41 @@ class QWidget;
|
||||
*/
|
||||
namespace JavaCommon
|
||||
{
|
||||
bool checkJVMArgs(QString args, QWidget *parent);
|
||||
bool checkJVMArgs(QString args, QWidget *parent);
|
||||
|
||||
// Show a dialog saying that the Java binary was not usable
|
||||
void javaBinaryWasBad(QWidget *parent, JavaCheckResult result);
|
||||
// Show a dialog saying that the Java binary was not usable because of bad options
|
||||
void javaArgsWereBad(QWidget *parent, JavaCheckResult result);
|
||||
// Show a dialog saying that the Java binary was usable
|
||||
void javaWasOk(QWidget *parent, JavaCheckResult result);
|
||||
// Show a dialog saying that the Java binary was not usable
|
||||
void javaBinaryWasBad(QWidget *parent, JavaCheckResult result);
|
||||
// Show a dialog saying that the Java binary was not usable because of bad options
|
||||
void javaArgsWereBad(QWidget *parent, JavaCheckResult result);
|
||||
// Show a dialog saying that the Java binary was usable
|
||||
void javaWasOk(QWidget *parent, JavaCheckResult result);
|
||||
|
||||
class TestCheck : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestCheck(QWidget *parent, QString path, QString args, int minMem, int maxMem, int permGen)
|
||||
:m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen)
|
||||
{
|
||||
}
|
||||
virtual ~TestCheck() {};
|
||||
class TestCheck : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestCheck(QWidget *parent, QString path, QString args, int minMem, int maxMem, int permGen)
|
||||
:m_parent(parent), m_path(path), m_args(args), m_minMem(minMem), m_maxMem(maxMem), m_permGen(permGen)
|
||||
{
|
||||
}
|
||||
virtual ~TestCheck() {};
|
||||
|
||||
void run();
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private slots:
|
||||
void checkFinished(JavaCheckResult result);
|
||||
void checkFinishedWithArgs(JavaCheckResult result);
|
||||
private slots:
|
||||
void checkFinished(JavaCheckResult result);
|
||||
void checkFinishedWithArgs(JavaCheckResult result);
|
||||
|
||||
private:
|
||||
std::shared_ptr<JavaChecker> checker;
|
||||
QWidget *m_parent = nullptr;
|
||||
QString m_path;
|
||||
QString m_args;
|
||||
int m_minMem = 0;
|
||||
int m_maxMem = 0;
|
||||
int m_permGen = 64;
|
||||
};
|
||||
private:
|
||||
std::shared_ptr<JavaChecker> checker;
|
||||
QWidget *m_parent = nullptr;
|
||||
QString m_path;
|
||||
QString m_args;
|
||||
int m_minMem = 0;
|
||||
int m_maxMem = 0;
|
||||
int m_permGen = 64;
|
||||
};
|
||||
}
|
||||
|
@ -6,13 +6,13 @@
|
||||
namespace {
|
||||
const std::array<Qt::Key, 10> konamiCode =
|
||||
{
|
||||
{
|
||||
Qt::Key_Up, Qt::Key_Up,
|
||||
Qt::Key_Down, Qt::Key_Down,
|
||||
Qt::Key_Left, Qt::Key_Right,
|
||||
Qt::Key_Left, Qt::Key_Right,
|
||||
Qt::Key_B, Qt::Key_A
|
||||
}
|
||||
{
|
||||
Qt::Key_Up, Qt::Key_Up,
|
||||
Qt::Key_Down, Qt::Key_Down,
|
||||
Qt::Key_Left, Qt::Key_Right,
|
||||
Qt::Key_Left, Qt::Key_Right,
|
||||
Qt::Key_B, Qt::Key_A
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -23,22 +23,22 @@ KonamiCode::KonamiCode(QObject* parent) : QObject(parent)
|
||||
|
||||
void KonamiCode::input(QEvent* event)
|
||||
{
|
||||
if( event->type() == QEvent::KeyPress )
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
|
||||
auto key = Qt::Key(keyEvent->key());
|
||||
if(key == konamiCode[m_progress])
|
||||
{
|
||||
m_progress ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_progress = 0;
|
||||
}
|
||||
if(m_progress == konamiCode.size())
|
||||
{
|
||||
m_progress = 0;
|
||||
emit triggered();
|
||||
}
|
||||
}
|
||||
if( event->type() == QEvent::KeyPress )
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
|
||||
auto key = Qt::Key(keyEvent->key());
|
||||
if(key == konamiCode[m_progress])
|
||||
{
|
||||
m_progress ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_progress = 0;
|
||||
}
|
||||
if(m_progress == konamiCode.size())
|
||||
{
|
||||
m_progress = 0;
|
||||
emit triggered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
class KonamiCode : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
KonamiCode(QObject *parent = 0);
|
||||
void input(QEvent *event);
|
||||
KonamiCode(QObject *parent = 0);
|
||||
void input(QEvent *event);
|
||||
|
||||
signals:
|
||||
void triggered();
|
||||
void triggered();
|
||||
|
||||
private:
|
||||
int m_progress = 0;
|
||||
int m_progress = 0;
|
||||
};
|
||||
|
@ -23,291 +23,291 @@ LaunchController::LaunchController(QObject *parent) : Task(parent)
|
||||
|
||||
void LaunchController::executeTask()
|
||||
{
|
||||
if (!m_instance)
|
||||
{
|
||||
emitFailed(tr("No instance specified"));
|
||||
return;
|
||||
}
|
||||
if (!m_instance)
|
||||
{
|
||||
emitFailed(tr("No instance specified"));
|
||||
return;
|
||||
}
|
||||
|
||||
login();
|
||||
login();
|
||||
}
|
||||
|
||||
// FIXME: minecraft specific
|
||||
void LaunchController::login()
|
||||
{
|
||||
JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
|
||||
JavaCommon::checkJVMArgs(m_instance->settings()->get("JvmArgs").toString(), m_parentWidget);
|
||||
|
||||
// Find an account to use.
|
||||
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
|
||||
MojangAccountPtr account = accounts->activeAccount();
|
||||
if (accounts->count() <= 0)
|
||||
{
|
||||
// Tell the user they need to log in at least one account in order to play.
|
||||
auto reply = CustomMessageBox::selectable(
|
||||
m_parentWidget, tr("No Accounts"),
|
||||
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
|
||||
"account logged in to MultiMC."
|
||||
"Would you like to open the account manager to add an account now?"),
|
||||
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
|
||||
// Find an account to use.
|
||||
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
|
||||
MojangAccountPtr account = accounts->activeAccount();
|
||||
if (accounts->count() <= 0)
|
||||
{
|
||||
// Tell the user they need to log in at least one account in order to play.
|
||||
auto reply = CustomMessageBox::selectable(
|
||||
m_parentWidget, tr("No Accounts"),
|
||||
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft "
|
||||
"account logged in to MultiMC."
|
||||
"Would you like to open the account manager to add an account now?"),
|
||||
QMessageBox::Information, QMessageBox::Yes | QMessageBox::No)->exec();
|
||||
|
||||
if (reply == QMessageBox::Yes)
|
||||
{
|
||||
// Open the account manager.
|
||||
SettingsUI::ShowPageDialog(MMC->globalSettingsPages(), m_parentWidget, "accounts");
|
||||
}
|
||||
}
|
||||
else if (account.get() == nullptr)
|
||||
{
|
||||
// If no default account is set, ask the user which one to use.
|
||||
ProfileSelectDialog selectDialog(tr("Which profile would you like to use?"),
|
||||
ProfileSelectDialog::GlobalDefaultCheckbox, m_parentWidget);
|
||||
if (reply == QMessageBox::Yes)
|
||||
{
|
||||
// Open the account manager.
|
||||
SettingsUI::ShowPageDialog(MMC->globalSettingsPages(), m_parentWidget, "accounts");
|
||||
}
|
||||
}
|
||||
else if (account.get() == nullptr)
|
||||
{
|
||||
// If no default account is set, ask the user which one to use.
|
||||
ProfileSelectDialog selectDialog(tr("Which profile would you like to use?"),
|
||||
ProfileSelectDialog::GlobalDefaultCheckbox, m_parentWidget);
|
||||
|
||||
selectDialog.exec();
|
||||
selectDialog.exec();
|
||||
|
||||
// Launch the instance with the selected account.
|
||||
account = selectDialog.selectedAccount();
|
||||
// Launch the instance with the selected account.
|
||||
account = selectDialog.selectedAccount();
|
||||
|
||||
// If the user said to use the account as default, do that.
|
||||
if (selectDialog.useAsGlobalDefault() && account.get() != nullptr)
|
||||
accounts->setActiveAccount(account->username());
|
||||
}
|
||||
// If the user said to use the account as default, do that.
|
||||
if (selectDialog.useAsGlobalDefault() && account.get() != nullptr)
|
||||
accounts->setActiveAccount(account->username());
|
||||
}
|
||||
|
||||
// if no account is selected, we bail
|
||||
if (!account.get())
|
||||
{
|
||||
emitFailed(tr("No account selected for launch"));
|
||||
return;
|
||||
}
|
||||
// if no account is selected, we bail
|
||||
if (!account.get())
|
||||
{
|
||||
emitFailed(tr("No account selected for launch"));
|
||||
return;
|
||||
}
|
||||
|
||||
// we try empty password first :)
|
||||
QString password;
|
||||
// we loop until the user succeeds in logging in or gives up
|
||||
bool tryagain = true;
|
||||
// the failure. the default failure.
|
||||
const QString needLoginAgain = tr("Your account is currently not logged in. Please enter "
|
||||
"your password to log in again.");
|
||||
QString failReason = needLoginAgain;
|
||||
// we try empty password first :)
|
||||
QString password;
|
||||
// we loop until the user succeeds in logging in or gives up
|
||||
bool tryagain = true;
|
||||
// the failure. the default failure.
|
||||
const QString needLoginAgain = tr("Your account is currently not logged in. Please enter "
|
||||
"your password to log in again.");
|
||||
QString failReason = needLoginAgain;
|
||||
|
||||
while (tryagain)
|
||||
{
|
||||
m_session = std::make_shared<AuthSession>();
|
||||
m_session->wants_online = m_online;
|
||||
auto task = account->login(m_session, password);
|
||||
if (task)
|
||||
{
|
||||
// We'll need to validate the access token to make sure the account
|
||||
// is still logged in.
|
||||
ProgressDialog progDialog(m_parentWidget);
|
||||
if (m_online)
|
||||
{
|
||||
progDialog.setSkipButton(true, tr("Play Offline"));
|
||||
}
|
||||
progDialog.execWithTask(task.get());
|
||||
if (!task->wasSuccessful())
|
||||
{
|
||||
auto failReasonNew = task->failReason();
|
||||
if(failReasonNew == "Invalid token.")
|
||||
{
|
||||
account->invalidateClientToken();
|
||||
failReason = needLoginAgain;
|
||||
}
|
||||
else failReason = failReasonNew;
|
||||
}
|
||||
}
|
||||
switch (m_session->status)
|
||||
{
|
||||
case AuthSession::Undetermined:
|
||||
{
|
||||
qCritical() << "Received undetermined session status during login. Bye.";
|
||||
tryagain = false;
|
||||
emitFailed(tr("Received undetermined session status during login."));
|
||||
break;
|
||||
}
|
||||
case AuthSession::RequiresPassword:
|
||||
{
|
||||
EditAccountDialog passDialog(failReason, m_parentWidget, EditAccountDialog::PasswordField);
|
||||
auto username = m_session->username;
|
||||
auto chopN = [](QString toChop, int N) -> QString
|
||||
{
|
||||
if(toChop.size() > N)
|
||||
{
|
||||
auto left = toChop.left(N);
|
||||
left += QString("\u25CF").repeated(toChop.size() - N);
|
||||
return left;
|
||||
}
|
||||
return toChop;
|
||||
};
|
||||
while (tryagain)
|
||||
{
|
||||
m_session = std::make_shared<AuthSession>();
|
||||
m_session->wants_online = m_online;
|
||||
auto task = account->login(m_session, password);
|
||||
if (task)
|
||||
{
|
||||
// We'll need to validate the access token to make sure the account
|
||||
// is still logged in.
|
||||
ProgressDialog progDialog(m_parentWidget);
|
||||
if (m_online)
|
||||
{
|
||||
progDialog.setSkipButton(true, tr("Play Offline"));
|
||||
}
|
||||
progDialog.execWithTask(task.get());
|
||||
if (!task->wasSuccessful())
|
||||
{
|
||||
auto failReasonNew = task->failReason();
|
||||
if(failReasonNew == "Invalid token.")
|
||||
{
|
||||
account->invalidateClientToken();
|
||||
failReason = needLoginAgain;
|
||||
}
|
||||
else failReason = failReasonNew;
|
||||
}
|
||||
}
|
||||
switch (m_session->status)
|
||||
{
|
||||
case AuthSession::Undetermined:
|
||||
{
|
||||
qCritical() << "Received undetermined session status during login. Bye.";
|
||||
tryagain = false;
|
||||
emitFailed(tr("Received undetermined session status during login."));
|
||||
break;
|
||||
}
|
||||
case AuthSession::RequiresPassword:
|
||||
{
|
||||
EditAccountDialog passDialog(failReason, m_parentWidget, EditAccountDialog::PasswordField);
|
||||
auto username = m_session->username;
|
||||
auto chopN = [](QString toChop, int N) -> QString
|
||||
{
|
||||
if(toChop.size() > N)
|
||||
{
|
||||
auto left = toChop.left(N);
|
||||
left += QString("\u25CF").repeated(toChop.size() - N);
|
||||
return left;
|
||||
}
|
||||
return toChop;
|
||||
};
|
||||
|
||||
if(username.contains('@'))
|
||||
{
|
||||
auto parts = username.split('@');
|
||||
auto mailbox = chopN(parts[0],3);
|
||||
QString domain = chopN(parts[1], 3);
|
||||
username = mailbox + '@' + domain;
|
||||
}
|
||||
passDialog.setUsername(username);
|
||||
if (passDialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
password = passDialog.password();
|
||||
}
|
||||
else
|
||||
{
|
||||
tryagain = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AuthSession::PlayableOffline:
|
||||
{
|
||||
// we ask the user for a player name
|
||||
bool ok = false;
|
||||
QString usedname = m_session->player_name;
|
||||
QString name = QInputDialog::getText(m_parentWidget, tr("Player name"),
|
||||
tr("Choose your offline mode player name."),
|
||||
QLineEdit::Normal, m_session->player_name, &ok);
|
||||
if (!ok)
|
||||
{
|
||||
tryagain = false;
|
||||
break;
|
||||
}
|
||||
if (name.length())
|
||||
{
|
||||
usedname = name;
|
||||
}
|
||||
m_session->MakeOffline(usedname);
|
||||
// offline flavored game from here :3
|
||||
}
|
||||
case AuthSession::PlayableOnline:
|
||||
{
|
||||
launchInstance();
|
||||
tryagain = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
emitFailed(tr("Failed to launch."));
|
||||
if(username.contains('@'))
|
||||
{
|
||||
auto parts = username.split('@');
|
||||
auto mailbox = chopN(parts[0],3);
|
||||
QString domain = chopN(parts[1], 3);
|
||||
username = mailbox + '@' + domain;
|
||||
}
|
||||
passDialog.setUsername(username);
|
||||
if (passDialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
password = passDialog.password();
|
||||
}
|
||||
else
|
||||
{
|
||||
tryagain = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AuthSession::PlayableOffline:
|
||||
{
|
||||
// we ask the user for a player name
|
||||
bool ok = false;
|
||||
QString usedname = m_session->player_name;
|
||||
QString name = QInputDialog::getText(m_parentWidget, tr("Player name"),
|
||||
tr("Choose your offline mode player name."),
|
||||
QLineEdit::Normal, m_session->player_name, &ok);
|
||||
if (!ok)
|
||||
{
|
||||
tryagain = false;
|
||||
break;
|
||||
}
|
||||
if (name.length())
|
||||
{
|
||||
usedname = name;
|
||||
}
|
||||
m_session->MakeOffline(usedname);
|
||||
// offline flavored game from here :3
|
||||
}
|
||||
case AuthSession::PlayableOnline:
|
||||
{
|
||||
launchInstance();
|
||||
tryagain = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
emitFailed(tr("Failed to launch."));
|
||||
}
|
||||
|
||||
void LaunchController::launchInstance()
|
||||
{
|
||||
Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL");
|
||||
Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL");
|
||||
Q_ASSERT_X(m_instance != NULL, "launchInstance", "instance is NULL");
|
||||
Q_ASSERT_X(m_session.get() != nullptr, "launchInstance", "session is NULL");
|
||||
|
||||
if(!m_instance->reloadSettings())
|
||||
{
|
||||
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't load the instance profile."));
|
||||
emitFailed(tr("Couldn't load the instance profile."));
|
||||
return;
|
||||
}
|
||||
if(!m_instance->reloadSettings())
|
||||
{
|
||||
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't load the instance profile."));
|
||||
emitFailed(tr("Couldn't load the instance profile."));
|
||||
return;
|
||||
}
|
||||
|
||||
m_launcher = m_instance->createLaunchTask(m_session);
|
||||
if (!m_launcher)
|
||||
{
|
||||
emitFailed(tr("Couldn't instantiate a launcher."));
|
||||
return;
|
||||
}
|
||||
m_launcher = m_instance->createLaunchTask(m_session);
|
||||
if (!m_launcher)
|
||||
{
|
||||
emitFailed(tr("Couldn't instantiate a launcher."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto console = qobject_cast<InstanceWindow *>(m_parentWidget);
|
||||
auto showConsole = m_instance->settings()->get("ShowConsole").toBool();
|
||||
if(!console && showConsole)
|
||||
{
|
||||
MMC->showInstanceWindow(m_instance);
|
||||
}
|
||||
connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch);
|
||||
connect(m_launcher.get(), &LaunchTask::succeeded, this, &LaunchController::onSucceeded);
|
||||
connect(m_launcher.get(), &LaunchTask::failed, this, &LaunchController::onFailed);
|
||||
connect(m_launcher.get(), &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested);
|
||||
auto console = qobject_cast<InstanceWindow *>(m_parentWidget);
|
||||
auto showConsole = m_instance->settings()->get("ShowConsole").toBool();
|
||||
if(!console && showConsole)
|
||||
{
|
||||
MMC->showInstanceWindow(m_instance);
|
||||
}
|
||||
connect(m_launcher.get(), &LaunchTask::readyForLaunch, this, &LaunchController::readyForLaunch);
|
||||
connect(m_launcher.get(), &LaunchTask::succeeded, this, &LaunchController::onSucceeded);
|
||||
connect(m_launcher.get(), &LaunchTask::failed, this, &LaunchController::onFailed);
|
||||
connect(m_launcher.get(), &LaunchTask::requestProgress, this, &LaunchController::onProgressRequested);
|
||||
|
||||
|
||||
m_launcher->prependStep(std::make_shared<TextPrint>(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC));
|
||||
m_launcher->start();
|
||||
m_launcher->prependStep(std::make_shared<TextPrint>(m_launcher.get(), "MultiMC version: " + BuildConfig.printableVersionString() + "\n\n", MessageLevel::MultiMC));
|
||||
m_launcher->start();
|
||||
}
|
||||
|
||||
void LaunchController::readyForLaunch()
|
||||
{
|
||||
if (!m_profiler)
|
||||
{
|
||||
m_launcher->proceed();
|
||||
return;
|
||||
}
|
||||
if (!m_profiler)
|
||||
{
|
||||
m_launcher->proceed();
|
||||
return;
|
||||
}
|
||||
|
||||
QString error;
|
||||
if (!m_profiler->check(&error))
|
||||
{
|
||||
m_launcher->abort();
|
||||
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't start profiler: %1").arg(error));
|
||||
emitFailed("Profiler startup failed");
|
||||
return;
|
||||
}
|
||||
BaseProfiler *profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this);
|
||||
QString error;
|
||||
if (!m_profiler->check(&error))
|
||||
{
|
||||
m_launcher->abort();
|
||||
QMessageBox::critical(m_parentWidget, tr("Error"), tr("Couldn't start profiler: %1").arg(error));
|
||||
emitFailed("Profiler startup failed");
|
||||
return;
|
||||
}
|
||||
BaseProfiler *profilerInstance = m_profiler->createProfiler(m_launcher->instance(), this);
|
||||
|
||||
connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString & message)
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setText(tr("The game launch is delayed until you press the "
|
||||
"button. This is the right time to setup the profiler, as the "
|
||||
"profiler server is running now.\n\n%1").arg(message));
|
||||
msg.setWindowTitle(tr("Waiting"));
|
||||
msg.setIcon(QMessageBox::Information);
|
||||
msg.addButton(tr("Launch"), QMessageBox::AcceptRole);
|
||||
msg.setModal(true);
|
||||
msg.exec();
|
||||
m_launcher->proceed();
|
||||
});
|
||||
connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString & message)
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setText(tr("Couldn't start the profiler: %1").arg(message));
|
||||
msg.setWindowTitle(tr("Error"));
|
||||
msg.setIcon(QMessageBox::Critical);
|
||||
msg.addButton(QMessageBox::Ok);
|
||||
msg.setModal(true);
|
||||
msg.exec();
|
||||
m_launcher->abort();
|
||||
emitFailed("Profiler startup failed");
|
||||
});
|
||||
profilerInstance->beginProfiling(m_launcher);
|
||||
connect(profilerInstance, &BaseProfiler::readyToLaunch, [this](const QString & message)
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setText(tr("The game launch is delayed until you press the "
|
||||
"button. This is the right time to setup the profiler, as the "
|
||||
"profiler server is running now.\n\n%1").arg(message));
|
||||
msg.setWindowTitle(tr("Waiting"));
|
||||
msg.setIcon(QMessageBox::Information);
|
||||
msg.addButton(tr("Launch"), QMessageBox::AcceptRole);
|
||||
msg.setModal(true);
|
||||
msg.exec();
|
||||
m_launcher->proceed();
|
||||
});
|
||||
connect(profilerInstance, &BaseProfiler::abortLaunch, [this](const QString & message)
|
||||
{
|
||||
QMessageBox msg;
|
||||
msg.setText(tr("Couldn't start the profiler: %1").arg(message));
|
||||
msg.setWindowTitle(tr("Error"));
|
||||
msg.setIcon(QMessageBox::Critical);
|
||||
msg.addButton(QMessageBox::Ok);
|
||||
msg.setModal(true);
|
||||
msg.exec();
|
||||
m_launcher->abort();
|
||||
emitFailed("Profiler startup failed");
|
||||
});
|
||||
profilerInstance->beginProfiling(m_launcher);
|
||||
}
|
||||
|
||||
void LaunchController::onSucceeded()
|
||||
{
|
||||
emitSucceeded();
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
void LaunchController::onFailed(QString reason)
|
||||
{
|
||||
if(m_instance->settings()->get("ShowConsoleOnError").toBool())
|
||||
{
|
||||
MMC->showInstanceWindow(m_instance, "console");
|
||||
}
|
||||
emitFailed(reason);
|
||||
if(m_instance->settings()->get("ShowConsoleOnError").toBool())
|
||||
{
|
||||
MMC->showInstanceWindow(m_instance, "console");
|
||||
}
|
||||
emitFailed(reason);
|
||||
}
|
||||
|
||||
void LaunchController::onProgressRequested(Task* task)
|
||||
{
|
||||
ProgressDialog progDialog(m_parentWidget);
|
||||
progDialog.setSkipButton(true, tr("Abort"));
|
||||
m_launcher->proceed();
|
||||
progDialog.execWithTask(task);
|
||||
ProgressDialog progDialog(m_parentWidget);
|
||||
progDialog.setSkipButton(true, tr("Abort"));
|
||||
m_launcher->proceed();
|
||||
progDialog.execWithTask(task);
|
||||
}
|
||||
|
||||
bool LaunchController::abort()
|
||||
{
|
||||
if(!m_launcher)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(!m_launcher->canAbort())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto response = CustomMessageBox::selectable(
|
||||
m_parentWidget, tr("Kill Minecraft?"),
|
||||
tr("This can cause the instance to get corrupted and should only be used if Minecraft "
|
||||
"is frozen for some reason"),
|
||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
{
|
||||
return m_launcher->abort();
|
||||
}
|
||||
return false;
|
||||
if(!m_launcher)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(!m_launcher->canAbort())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto response = CustomMessageBox::selectable(
|
||||
m_parentWidget, tr("Kill Minecraft?"),
|
||||
tr("This can cause the instance to get corrupted and should only be used if Minecraft "
|
||||
"is frozen for some reason"),
|
||||
QMessageBox::Question, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)->exec();
|
||||
if (response == QMessageBox::Yes)
|
||||
{
|
||||
return m_launcher->abort();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -6,56 +6,56 @@
|
||||
class InstanceWindow;
|
||||
class LaunchController: public Task
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
void executeTask() override;
|
||||
void executeTask() override;
|
||||
|
||||
LaunchController(QObject * parent = nullptr);
|
||||
virtual ~LaunchController(){};
|
||||
LaunchController(QObject * parent = nullptr);
|
||||
virtual ~LaunchController(){};
|
||||
|
||||
void setInstance(InstancePtr instance)
|
||||
{
|
||||
m_instance = instance;
|
||||
}
|
||||
InstancePtr instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
void setOnline(bool online)
|
||||
{
|
||||
m_online = online;
|
||||
}
|
||||
void setProfiler(BaseProfilerFactory *profiler)
|
||||
{
|
||||
m_profiler = profiler;
|
||||
}
|
||||
void setParentWidget(QWidget * widget)
|
||||
{
|
||||
m_parentWidget = widget;
|
||||
}
|
||||
QString id()
|
||||
{
|
||||
return m_instance->id();
|
||||
}
|
||||
bool abort() override;
|
||||
void setInstance(InstancePtr instance)
|
||||
{
|
||||
m_instance = instance;
|
||||
}
|
||||
InstancePtr instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
void setOnline(bool online)
|
||||
{
|
||||
m_online = online;
|
||||
}
|
||||
void setProfiler(BaseProfilerFactory *profiler)
|
||||
{
|
||||
m_profiler = profiler;
|
||||
}
|
||||
void setParentWidget(QWidget * widget)
|
||||
{
|
||||
m_parentWidget = widget;
|
||||
}
|
||||
QString id()
|
||||
{
|
||||
return m_instance->id();
|
||||
}
|
||||
bool abort() override;
|
||||
|
||||
private:
|
||||
void login();
|
||||
void launchInstance();
|
||||
void login();
|
||||
void launchInstance();
|
||||
|
||||
private slots:
|
||||
void readyForLaunch();
|
||||
void readyForLaunch();
|
||||
|
||||
void onSucceeded();
|
||||
void onFailed(QString reason);
|
||||
void onProgressRequested(Task *task);
|
||||
void onSucceeded();
|
||||
void onFailed(QString reason);
|
||||
void onProgressRequested(Task *task);
|
||||
|
||||
private:
|
||||
BaseProfilerFactory *m_profiler = nullptr;
|
||||
bool m_online = true;
|
||||
InstancePtr m_instance;
|
||||
QWidget * m_parentWidget = nullptr;
|
||||
InstanceWindow *m_console = nullptr;
|
||||
AuthSessionPtr m_session;
|
||||
std::shared_ptr <LaunchTask> m_launcher;
|
||||
BaseProfilerFactory *m_profiler = nullptr;
|
||||
bool m_online = true;
|
||||
InstancePtr m_instance;
|
||||
QWidget * m_parentWidget = nullptr;
|
||||
InstanceWindow *m_console = nullptr;
|
||||
AuthSessionPtr m_session;
|
||||
std::shared_ptr <LaunchTask> m_launcher;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,174 +42,174 @@ class InstanceTask;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
class Ui;
|
||||
class Ui;
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
bool eventFilter(QObject *obj, QEvent *ev) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void changeEvent(QEvent * event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *ev) override;
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void changeEvent(QEvent * event) override;
|
||||
|
||||
void checkInstancePathForProblems();
|
||||
void checkInstancePathForProblems();
|
||||
|
||||
void updatesAllowedChanged(bool allowed);
|
||||
void updatesAllowedChanged(bool allowed);
|
||||
signals:
|
||||
void isClosing();
|
||||
void isClosing();
|
||||
|
||||
private slots:
|
||||
void onCatToggled(bool);
|
||||
void onCatToggled(bool);
|
||||
|
||||
void on_actionAbout_triggered();
|
||||
void on_actionAbout_triggered();
|
||||
|
||||
void on_actionAddInstance_triggered();
|
||||
void on_actionAddInstance_triggered();
|
||||
|
||||
void on_actionREDDIT_triggered();
|
||||
void on_actionREDDIT_triggered();
|
||||
|
||||
void on_actionDISCORD_triggered();
|
||||
void on_actionDISCORD_triggered();
|
||||
|
||||
void on_actionCopyInstance_triggered();
|
||||
void on_actionCopyInstance_triggered();
|
||||
|
||||
void on_actionChangeInstGroup_triggered();
|
||||
void on_actionChangeInstGroup_triggered();
|
||||
|
||||
void on_actionChangeInstIcon_triggered();
|
||||
void on_changeIconButton_clicked(bool)
|
||||
{
|
||||
on_actionChangeInstIcon_triggered();
|
||||
}
|
||||
void on_actionChangeInstIcon_triggered();
|
||||
void on_changeIconButton_clicked(bool)
|
||||
{
|
||||
on_actionChangeInstIcon_triggered();
|
||||
}
|
||||
|
||||
void on_actionViewInstanceFolder_triggered();
|
||||
void on_actionViewInstanceFolder_triggered();
|
||||
|
||||
void on_actionConfig_Folder_triggered();
|
||||
void on_actionConfig_Folder_triggered();
|
||||
|
||||
void on_actionViewSelectedInstFolder_triggered();
|
||||
void on_actionViewSelectedInstFolder_triggered();
|
||||
|
||||
void refreshInstances();
|
||||
void refreshInstances();
|
||||
|
||||
void on_actionViewCentralModsFolder_triggered();
|
||||
void on_actionViewCentralModsFolder_triggered();
|
||||
|
||||
void checkForUpdates();
|
||||
void checkForUpdates();
|
||||
|
||||
void on_actionSettings_triggered();
|
||||
void on_actionSettings_triggered();
|
||||
|
||||
void on_actionInstanceSettings_triggered();
|
||||
void on_actionInstanceSettings_triggered();
|
||||
|
||||
void on_actionManageAccounts_triggered();
|
||||
void on_actionManageAccounts_triggered();
|
||||
|
||||
void on_actionReportBug_triggered();
|
||||
void on_actionReportBug_triggered();
|
||||
|
||||
void on_actionPatreon_triggered();
|
||||
void on_actionPatreon_triggered();
|
||||
|
||||
void on_actionMoreNews_triggered();
|
||||
void on_actionMoreNews_triggered();
|
||||
|
||||
void newsButtonClicked();
|
||||
void newsButtonClicked();
|
||||
|
||||
void on_mainToolBar_visibilityChanged(bool);
|
||||
void on_mainToolBar_visibilityChanged(bool);
|
||||
|
||||
void on_actionLaunchInstance_triggered();
|
||||
void on_actionLaunchInstance_triggered();
|
||||
|
||||
void on_actionLaunchInstanceOffline_triggered();
|
||||
void on_actionLaunchInstanceOffline_triggered();
|
||||
|
||||
void on_actionDeleteInstance_triggered();
|
||||
void on_actionDeleteInstance_triggered();
|
||||
|
||||
void deleteGroup();
|
||||
void deleteGroup();
|
||||
|
||||
void on_actionExportInstance_triggered();
|
||||
void on_actionExportInstance_triggered();
|
||||
|
||||
void on_actionRenameInstance_triggered();
|
||||
void on_renameButton_clicked(bool)
|
||||
{
|
||||
on_actionRenameInstance_triggered();
|
||||
}
|
||||
void on_actionRenameInstance_triggered();
|
||||
void on_renameButton_clicked(bool)
|
||||
{
|
||||
on_actionRenameInstance_triggered();
|
||||
}
|
||||
|
||||
void on_actionEditInstance_triggered();
|
||||
void on_actionEditInstance_triggered();
|
||||
|
||||
void on_actionEditInstNotes_triggered();
|
||||
void on_actionEditInstNotes_triggered();
|
||||
|
||||
void on_actionWorlds_triggered();
|
||||
void on_actionWorlds_triggered();
|
||||
|
||||
void on_actionScreenshots_triggered();
|
||||
void on_actionScreenshots_triggered();
|
||||
|
||||
void taskEnd();
|
||||
void taskEnd();
|
||||
|
||||
/**
|
||||
* called when an icon is changed in the icon model.
|
||||
*/
|
||||
void iconUpdated(QString);
|
||||
/**
|
||||
* called when an icon is changed in the icon model.
|
||||
*/
|
||||
void iconUpdated(QString);
|
||||
|
||||
void showInstanceContextMenu(const QPoint &);
|
||||
void showInstanceContextMenu(const QPoint &);
|
||||
|
||||
void updateToolsMenu();
|
||||
void updateToolsMenu();
|
||||
|
||||
void skinJobFinished();
|
||||
void skinJobFinished();
|
||||
|
||||
void instanceActivated(QModelIndex);
|
||||
void instanceActivated(QModelIndex);
|
||||
|
||||
void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void instanceChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
|
||||
void instanceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||
void instanceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||
|
||||
void selectionBad();
|
||||
void selectionBad();
|
||||
|
||||
void startTask(Task *task);
|
||||
void startTask(Task *task);
|
||||
|
||||
void updateAvailable(GoUpdate::Status status);
|
||||
void updateAvailable(GoUpdate::Status status);
|
||||
|
||||
void updateNotAvailable();
|
||||
void updateNotAvailable();
|
||||
|
||||
void notificationsChanged();
|
||||
void notificationsChanged();
|
||||
|
||||
void activeAccountChanged();
|
||||
void activeAccountChanged();
|
||||
|
||||
void changeActiveAccount();
|
||||
void changeActiveAccount();
|
||||
|
||||
void repopulateAccountsMenu();
|
||||
void repopulateAccountsMenu();
|
||||
|
||||
void updateNewsLabel();
|
||||
void updateNewsLabel();
|
||||
|
||||
/*!
|
||||
* Runs the DownloadTask and installs updates.
|
||||
*/
|
||||
void downloadUpdates(GoUpdate::Status status);
|
||||
/*!
|
||||
* Runs the DownloadTask and installs updates.
|
||||
*/
|
||||
void downloadUpdates(GoUpdate::Status status);
|
||||
|
||||
void droppedURLs(QList<QUrl> urls);
|
||||
void droppedURLs(QList<QUrl> urls);
|
||||
|
||||
void konamiTriggered();
|
||||
void konamiTriggered();
|
||||
|
||||
private:
|
||||
void addInstance(QString url = QString());
|
||||
void activateInstance(InstancePtr instance);
|
||||
void setCatBackground(bool enabled);
|
||||
void updateInstanceToolIcon(QString new_icon);
|
||||
void setSelectedInstanceById(const QString &id);
|
||||
void addInstance(QString url = QString());
|
||||
void activateInstance(InstancePtr instance);
|
||||
void setCatBackground(bool enabled);
|
||||
void updateInstanceToolIcon(QString new_icon);
|
||||
void setSelectedInstanceById(const QString &id);
|
||||
|
||||
void runModalTask(Task *task);
|
||||
void instanceFromInstanceTask(InstanceTask *task);
|
||||
void finalizeInstance(InstancePtr inst);
|
||||
void runModalTask(Task *task);
|
||||
void instanceFromInstanceTask(InstanceTask *task);
|
||||
void finalizeInstance(InstancePtr inst);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui> ui;
|
||||
std::unique_ptr<Ui> ui;
|
||||
|
||||
// these are managed by Qt's memory management model!
|
||||
GroupView *view = nullptr;
|
||||
InstanceProxyModel *proxymodel = nullptr;
|
||||
QToolButton *newsLabel = nullptr;
|
||||
QLabel *m_statusLeft = nullptr;
|
||||
ServerStatus *m_statusRight = nullptr;
|
||||
QMenu *accountMenu = nullptr;
|
||||
QToolButton *accountMenuButton = nullptr;
|
||||
KonamiCode * secretEventFilter = nullptr;
|
||||
// these are managed by Qt's memory management model!
|
||||
GroupView *view = nullptr;
|
||||
InstanceProxyModel *proxymodel = nullptr;
|
||||
QToolButton *newsLabel = nullptr;
|
||||
QLabel *m_statusLeft = nullptr;
|
||||
ServerStatus *m_statusRight = nullptr;
|
||||
QMenu *accountMenu = nullptr;
|
||||
QToolButton *accountMenuButton = nullptr;
|
||||
KonamiCode * secretEventFilter = nullptr;
|
||||
|
||||
unique_qobject_ptr<NetJob> skin_download_job;
|
||||
unique_qobject_ptr<NewsChecker> m_newsChecker;
|
||||
unique_qobject_ptr<NotificationChecker> m_notificationChecker;
|
||||
unique_qobject_ptr<NetJob> skin_download_job;
|
||||
unique_qobject_ptr<NewsChecker> m_newsChecker;
|
||||
unique_qobject_ptr<NotificationChecker> m_notificationChecker;
|
||||
|
||||
InstancePtr m_selectedInstance;
|
||||
QString m_currentInstIcon;
|
||||
InstancePtr m_selectedInstance;
|
||||
QString m_currentInstIcon;
|
||||
|
||||
// managed by the application object
|
||||
Task *m_versionLoadTask = nullptr;
|
||||
// managed by the application object
|
||||
Task *m_versionLoadTask = nullptr;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,187 +40,187 @@ class GAnalytics;
|
||||
|
||||
class MultiMC : public QApplication
|
||||
{
|
||||
// friends for the purpose of limiting access to deprecated stuff
|
||||
Q_OBJECT
|
||||
// friends for the purpose of limiting access to deprecated stuff
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Status
|
||||
{
|
||||
StartingUp,
|
||||
Failed,
|
||||
Succeeded,
|
||||
Initialized
|
||||
};
|
||||
enum Status
|
||||
{
|
||||
StartingUp,
|
||||
Failed,
|
||||
Succeeded,
|
||||
Initialized
|
||||
};
|
||||
|
||||
public:
|
||||
MultiMC(int &argc, char **argv);
|
||||
virtual ~MultiMC();
|
||||
MultiMC(int &argc, char **argv);
|
||||
virtual ~MultiMC();
|
||||
|
||||
GAnalytics *analytics() const
|
||||
{
|
||||
return m_analytics;
|
||||
}
|
||||
GAnalytics *analytics() const
|
||||
{
|
||||
return m_analytics;
|
||||
}
|
||||
|
||||
std::shared_ptr<SettingsObject> settings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
std::shared_ptr<SettingsObject> settings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
std::shared_ptr<GenericPageProvider> globalSettingsPages() const
|
||||
{
|
||||
return m_globalSettingsProvider;
|
||||
}
|
||||
std::shared_ptr<GenericPageProvider> globalSettingsPages() const
|
||||
{
|
||||
return m_globalSettingsProvider;
|
||||
}
|
||||
|
||||
qint64 timeSinceStart() const
|
||||
{
|
||||
return startTime.msecsTo(QDateTime::currentDateTime());
|
||||
}
|
||||
qint64 timeSinceStart() const
|
||||
{
|
||||
return startTime.msecsTo(QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
QIcon getThemedIcon(const QString& name);
|
||||
QIcon getThemedIcon(const QString& name);
|
||||
|
||||
void setIconTheme(const QString& name);
|
||||
void setIconTheme(const QString& name);
|
||||
|
||||
std::vector<ITheme *> getValidApplicationThemes();
|
||||
std::vector<ITheme *> getValidApplicationThemes();
|
||||
|
||||
void setApplicationTheme(const QString& name, bool initial);
|
||||
void setApplicationTheme(const QString& name, bool initial);
|
||||
|
||||
// DownloadUpdateTask
|
||||
std::shared_ptr<UpdateChecker> updateChecker()
|
||||
{
|
||||
return m_updateChecker;
|
||||
}
|
||||
// DownloadUpdateTask
|
||||
std::shared_ptr<UpdateChecker> updateChecker()
|
||||
{
|
||||
return m_updateChecker;
|
||||
}
|
||||
|
||||
std::shared_ptr<TranslationsModel> translations();
|
||||
std::shared_ptr<TranslationsModel> translations();
|
||||
|
||||
std::shared_ptr<JavaInstallList> javalist();
|
||||
std::shared_ptr<JavaInstallList> javalist();
|
||||
|
||||
std::shared_ptr<InstanceList> instances() const
|
||||
{
|
||||
return m_instances;
|
||||
}
|
||||
std::shared_ptr<InstanceList> instances() const
|
||||
{
|
||||
return m_instances;
|
||||
}
|
||||
|
||||
FolderInstanceProvider * folderProvider() const
|
||||
{
|
||||
return m_instanceFolder;
|
||||
}
|
||||
FolderInstanceProvider * folderProvider() const
|
||||
{
|
||||
return m_instanceFolder;
|
||||
}
|
||||
|
||||
std::shared_ptr<IconList> icons() const
|
||||
{
|
||||
return m_icons;
|
||||
}
|
||||
std::shared_ptr<IconList> icons() const
|
||||
{
|
||||
return m_icons;
|
||||
}
|
||||
|
||||
MCEditTool *mcedit() const
|
||||
{
|
||||
return m_mcedit.get();
|
||||
}
|
||||
MCEditTool *mcedit() const
|
||||
{
|
||||
return m_mcedit.get();
|
||||
}
|
||||
|
||||
std::shared_ptr<MojangAccountList> accounts() const
|
||||
{
|
||||
return m_accounts;
|
||||
}
|
||||
std::shared_ptr<MojangAccountList> accounts() const
|
||||
{
|
||||
return m_accounts;
|
||||
}
|
||||
|
||||
Status status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
Status status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
const QMap<QString, std::shared_ptr<BaseProfilerFactory>> &profilers() const
|
||||
{
|
||||
return m_profilers;
|
||||
}
|
||||
const QMap<QString, std::shared_ptr<BaseProfilerFactory>> &profilers() const
|
||||
{
|
||||
return m_profilers;
|
||||
}
|
||||
|
||||
/// this is the root of the 'installation'. Used for automatic updates
|
||||
const QString &root()
|
||||
{
|
||||
return m_rootPath;
|
||||
}
|
||||
/// this is the root of the 'installation'. Used for automatic updates
|
||||
const QString &root()
|
||||
{
|
||||
return m_rootPath;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Opens a json file using either a system default editor, or, if not empty, the editor
|
||||
* specified in the settings
|
||||
*/
|
||||
bool openJsonEditor(const QString &filename);
|
||||
/*!
|
||||
* Opens a json file using either a system default editor, or, if not empty, the editor
|
||||
* specified in the settings
|
||||
*/
|
||||
bool openJsonEditor(const QString &filename);
|
||||
|
||||
InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString());
|
||||
MainWindow *showMainWindow(bool minimized = false);
|
||||
InstanceWindow *showInstanceWindow(InstancePtr instance, QString page = QString());
|
||||
MainWindow *showMainWindow(bool minimized = false);
|
||||
|
||||
void updateIsRunning(bool running);
|
||||
bool updatesAreAllowed();
|
||||
void updateIsRunning(bool running);
|
||||
bool updatesAreAllowed();
|
||||
|
||||
signals:
|
||||
void updateAllowedChanged(bool status);
|
||||
void updateAllowedChanged(bool status);
|
||||
|
||||
public slots:
|
||||
bool launch(InstancePtr instance, bool online = true, BaseProfilerFactory *profiler = nullptr);
|
||||
bool kill(InstancePtr instance);
|
||||
bool launch(InstancePtr instance, bool online = true, BaseProfilerFactory *profiler = nullptr);
|
||||
bool kill(InstancePtr instance);
|
||||
|
||||
private slots:
|
||||
void on_windowClose();
|
||||
void messageReceived(const QString & message);
|
||||
void controllerSucceeded();
|
||||
void controllerFailed(const QString & error);
|
||||
void analyticsSettingChanged(const Setting &setting, QVariant value);
|
||||
void setupWizardFinished(int status);
|
||||
void on_windowClose();
|
||||
void messageReceived(const QString & message);
|
||||
void controllerSucceeded();
|
||||
void controllerFailed(const QString & error);
|
||||
void analyticsSettingChanged(const Setting &setting, QVariant value);
|
||||
void setupWizardFinished(int status);
|
||||
|
||||
private:
|
||||
bool createSetupWizard();
|
||||
void performMainStartupAction();
|
||||
bool createSetupWizard();
|
||||
void performMainStartupAction();
|
||||
|
||||
// sets the fatal error message and m_status to Failed.
|
||||
void showFatalErrorMessage(const QString & title, const QString & content);
|
||||
// sets the fatal error message and m_status to Failed.
|
||||
void showFatalErrorMessage(const QString & title, const QString & content);
|
||||
|
||||
private:
|
||||
void addRunningInstance();
|
||||
void subRunningInstance();
|
||||
bool shouldExitNow() const;
|
||||
void addRunningInstance();
|
||||
void subRunningInstance();
|
||||
bool shouldExitNow() const;
|
||||
|
||||
private:
|
||||
QDateTime startTime;
|
||||
QDateTime startTime;
|
||||
|
||||
std::shared_ptr<SettingsObject> m_settings;
|
||||
std::shared_ptr<InstanceList> m_instances;
|
||||
FolderInstanceProvider * m_instanceFolder = nullptr;
|
||||
std::shared_ptr<IconList> m_icons;
|
||||
std::shared_ptr<UpdateChecker> m_updateChecker;
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
std::shared_ptr<JavaInstallList> m_javalist;
|
||||
std::shared_ptr<TranslationsModel> m_translations;
|
||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||
std::map<QString, std::unique_ptr<ITheme>> m_themes;
|
||||
std::unique_ptr<MCEditTool> m_mcedit;
|
||||
std::shared_ptr<SettingsObject> m_settings;
|
||||
std::shared_ptr<InstanceList> m_instances;
|
||||
FolderInstanceProvider * m_instanceFolder = nullptr;
|
||||
std::shared_ptr<IconList> m_icons;
|
||||
std::shared_ptr<UpdateChecker> m_updateChecker;
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
std::shared_ptr<JavaInstallList> m_javalist;
|
||||
std::shared_ptr<TranslationsModel> m_translations;
|
||||
std::shared_ptr<GenericPageProvider> m_globalSettingsProvider;
|
||||
std::map<QString, std::unique_ptr<ITheme>> m_themes;
|
||||
std::unique_ptr<MCEditTool> m_mcedit;
|
||||
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||
QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers;
|
||||
|
||||
QString m_rootPath;
|
||||
Status m_status = MultiMC::StartingUp;
|
||||
QString m_rootPath;
|
||||
Status m_status = MultiMC::StartingUp;
|
||||
|
||||
#if defined Q_OS_WIN32
|
||||
// used on Windows to attach the standard IO streams
|
||||
bool consoleAttached = false;
|
||||
// used on Windows to attach the standard IO streams
|
||||
bool consoleAttached = false;
|
||||
#endif
|
||||
|
||||
// FIXME: attach to instances instead.
|
||||
struct InstanceXtras
|
||||
{
|
||||
InstanceWindow * window = nullptr;
|
||||
shared_qobject_ptr<LaunchController> controller;
|
||||
};
|
||||
std::map<QString, InstanceXtras> m_instanceExtras;
|
||||
// FIXME: attach to instances instead.
|
||||
struct InstanceXtras
|
||||
{
|
||||
InstanceWindow * window = nullptr;
|
||||
shared_qobject_ptr<LaunchController> controller;
|
||||
};
|
||||
std::map<QString, InstanceXtras> m_instanceExtras;
|
||||
|
||||
// main state variables
|
||||
size_t m_openWindows = 0;
|
||||
size_t m_runningInstances = 0;
|
||||
bool m_updateRunning = false;
|
||||
// main state variables
|
||||
size_t m_openWindows = 0;
|
||||
size_t m_runningInstances = 0;
|
||||
bool m_updateRunning = false;
|
||||
|
||||
// main window, if any
|
||||
MainWindow * m_mainWindow = nullptr;
|
||||
// main window, if any
|
||||
MainWindow * m_mainWindow = nullptr;
|
||||
|
||||
// peer MultiMC instance connector - used to implement single instance MultiMC and signalling
|
||||
LocalPeer * m_peerInstance = nullptr;
|
||||
// peer MultiMC instance connector - used to implement single instance MultiMC and signalling
|
||||
LocalPeer * m_peerInstance = nullptr;
|
||||
|
||||
GAnalytics * m_analytics = nullptr;
|
||||
SetupWizard * m_setupWizard = nullptr;
|
||||
GAnalytics * m_analytics = nullptr;
|
||||
SetupWizard * m_setupWizard = nullptr;
|
||||
public:
|
||||
QString m_instanceIdToLaunch;
|
||||
bool m_liveCheck = false;
|
||||
std::unique_ptr<QFile> logFile;
|
||||
QString m_instanceIdToLaunch;
|
||||
bool m_liveCheck = false;
|
||||
std::unique_ptr<QFile> logFile;
|
||||
};
|
||||
|
@ -14,13 +14,13 @@ namespace SettingsUI
|
||||
template <typename T>
|
||||
void ShowPageDialog(T raw_provider, QWidget * parent, QString open_page = QString())
|
||||
{
|
||||
auto provider = std::dynamic_pointer_cast<BasePageProvider>(raw_provider);
|
||||
if(!provider)
|
||||
return;
|
||||
{
|
||||
SettingsObject::Lock lock(MMC->settings());
|
||||
PageDialog dlg(provider.get(), open_page, parent);
|
||||
dlg.exec();
|
||||
}
|
||||
auto provider = std::dynamic_pointer_cast<BasePageProvider>(raw_provider);
|
||||
if(!provider)
|
||||
return;
|
||||
{
|
||||
SettingsObject::Lock lock(MMC->settings());
|
||||
PageDialog dlg(provider.get(), open_page, parent);
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,423 +27,423 @@
|
||||
#endif
|
||||
static QFile::Permissions unixModeToPermissions(const int mode)
|
||||
{
|
||||
QFile::Permissions perms;
|
||||
QFile::Permissions perms;
|
||||
|
||||
if (mode & S_IRUSR)
|
||||
{
|
||||
perms |= QFile::ReadUser;
|
||||
}
|
||||
if (mode & S_IWUSR)
|
||||
{
|
||||
perms |= QFile::WriteUser;
|
||||
}
|
||||
if (mode & S_IXUSR)
|
||||
{
|
||||
perms |= QFile::ExeUser;
|
||||
}
|
||||
if (mode & S_IRUSR)
|
||||
{
|
||||
perms |= QFile::ReadUser;
|
||||
}
|
||||
if (mode & S_IWUSR)
|
||||
{
|
||||
perms |= QFile::WriteUser;
|
||||
}
|
||||
if (mode & S_IXUSR)
|
||||
{
|
||||
perms |= QFile::ExeUser;
|
||||
}
|
||||
|
||||
if (mode & S_IRGRP)
|
||||
{
|
||||
perms |= QFile::ReadGroup;
|
||||
}
|
||||
if (mode & S_IWGRP)
|
||||
{
|
||||
perms |= QFile::WriteGroup;
|
||||
}
|
||||
if (mode & S_IXGRP)
|
||||
{
|
||||
perms |= QFile::ExeGroup;
|
||||
}
|
||||
if (mode & S_IRGRP)
|
||||
{
|
||||
perms |= QFile::ReadGroup;
|
||||
}
|
||||
if (mode & S_IWGRP)
|
||||
{
|
||||
perms |= QFile::WriteGroup;
|
||||
}
|
||||
if (mode & S_IXGRP)
|
||||
{
|
||||
perms |= QFile::ExeGroup;
|
||||
}
|
||||
|
||||
if (mode & S_IROTH)
|
||||
{
|
||||
perms |= QFile::ReadOther;
|
||||
}
|
||||
if (mode & S_IWOTH)
|
||||
{
|
||||
perms |= QFile::WriteOther;
|
||||
}
|
||||
if (mode & S_IXOTH)
|
||||
{
|
||||
perms |= QFile::ExeOther;
|
||||
}
|
||||
return perms;
|
||||
if (mode & S_IROTH)
|
||||
{
|
||||
perms |= QFile::ReadOther;
|
||||
}
|
||||
if (mode & S_IWOTH)
|
||||
{
|
||||
perms |= QFile::WriteOther;
|
||||
}
|
||||
if (mode & S_IXOTH)
|
||||
{
|
||||
perms |= QFile::ExeOther;
|
||||
}
|
||||
return perms;
|
||||
}
|
||||
|
||||
static const QLatin1String liveCheckFile("live.check");
|
||||
|
||||
UpdateController::UpdateController(QWidget * parent, const QString& root, const QString updateFilesDir, GoUpdate::OperationList operations)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_root = root;
|
||||
m_updateFilesDir = updateFilesDir;
|
||||
m_operations = operations;
|
||||
m_parent = parent;
|
||||
m_root = root;
|
||||
m_updateFilesDir = updateFilesDir;
|
||||
m_operations = operations;
|
||||
}
|
||||
|
||||
|
||||
void UpdateController::installUpdates()
|
||||
{
|
||||
qint64 pid = -1;
|
||||
QStringList args;
|
||||
bool started = false;
|
||||
qint64 pid = -1;
|
||||
QStringList args;
|
||||
bool started = false;
|
||||
|
||||
qDebug() << "Installing updates.";
|
||||
qDebug() << "Installing updates.";
|
||||
#ifdef Q_OS_WIN
|
||||
QString finishCmd = QApplication::applicationFilePath();
|
||||
QString finishCmd = QApplication::applicationFilePath();
|
||||
#elif defined Q_OS_LINUX
|
||||
QString finishCmd = FS::PathCombine(m_root, "MultiMC");
|
||||
QString finishCmd = FS::PathCombine(m_root, "MultiMC");
|
||||
#elif defined Q_OS_MAC
|
||||
QString finishCmd = QApplication::applicationFilePath();
|
||||
QString finishCmd = QApplication::applicationFilePath();
|
||||
#else
|
||||
#error Unsupported operating system.
|
||||
#endif
|
||||
|
||||
QString backupPath = FS::PathCombine(m_root, "update", "backup");
|
||||
QDir origin(m_root);
|
||||
QString backupPath = FS::PathCombine(m_root, "update", "backup");
|
||||
QDir origin(m_root);
|
||||
|
||||
// clean up the backup folder. it should be empty before we start
|
||||
if(!FS::deletePath(backupPath))
|
||||
{
|
||||
qWarning() << "couldn't remove previous backup folder" << backupPath;
|
||||
}
|
||||
// and it should exist.
|
||||
if(!FS::ensureFolderPathExists(backupPath))
|
||||
{
|
||||
qWarning() << "couldn't create folder" << backupPath;
|
||||
return;
|
||||
}
|
||||
// clean up the backup folder. it should be empty before we start
|
||||
if(!FS::deletePath(backupPath))
|
||||
{
|
||||
qWarning() << "couldn't remove previous backup folder" << backupPath;
|
||||
}
|
||||
// and it should exist.
|
||||
if(!FS::ensureFolderPathExists(backupPath))
|
||||
{
|
||||
qWarning() << "couldn't create folder" << backupPath;
|
||||
return;
|
||||
}
|
||||
|
||||
bool useXPHack = false;
|
||||
QString exePath;
|
||||
QString exeOrigin;
|
||||
QString exeBackup;
|
||||
bool useXPHack = false;
|
||||
QString exePath;
|
||||
QString exeOrigin;
|
||||
QString exeBackup;
|
||||
|
||||
// perform the update operations
|
||||
for(auto op: m_operations)
|
||||
{
|
||||
switch(op.type)
|
||||
{
|
||||
// replace = move original out to backup, if it exists, move the new file in its place
|
||||
case GoUpdate::Operation::OP_REPLACE:
|
||||
{
|
||||
// perform the update operations
|
||||
for(auto op: m_operations)
|
||||
{
|
||||
switch(op.type)
|
||||
{
|
||||
// replace = move original out to backup, if it exists, move the new file in its place
|
||||
case GoUpdate::Operation::OP_REPLACE:
|
||||
{
|
||||
#ifdef Q_OS_WIN32
|
||||
// hack for people renaming the .exe because ... reasons :)
|
||||
if(op.destination == "MultiMC.exe")
|
||||
{
|
||||
op.destination = QFileInfo(QApplication::applicationFilePath()).fileName();
|
||||
}
|
||||
// hack for people renaming the .exe because ... reasons :)
|
||||
if(op.destination == "MultiMC.exe")
|
||||
{
|
||||
op.destination = QFileInfo(QApplication::applicationFilePath()).fileName();
|
||||
}
|
||||
#endif
|
||||
QFileInfo destination (FS::PathCombine(m_root, op.destination));
|
||||
QFileInfo destination (FS::PathCombine(m_root, op.destination));
|
||||
#ifdef Q_OS_WIN32
|
||||
if(QSysInfo::windowsVersion() < QSysInfo::WV_VISTA)
|
||||
{
|
||||
if(destination.fileName() == "MultiMC.exe")
|
||||
{
|
||||
QDir rootDir(m_root);
|
||||
exeOrigin = rootDir.relativeFilePath(op.source);
|
||||
exePath = rootDir.relativeFilePath(op.destination);
|
||||
exeBackup = rootDir.relativeFilePath(FS::PathCombine(backupPath, destination.fileName()));
|
||||
useXPHack = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(QSysInfo::windowsVersion() < QSysInfo::WV_VISTA)
|
||||
{
|
||||
if(destination.fileName() == "MultiMC.exe")
|
||||
{
|
||||
QDir rootDir(m_root);
|
||||
exeOrigin = rootDir.relativeFilePath(op.source);
|
||||
exePath = rootDir.relativeFilePath(op.destination);
|
||||
exeBackup = rootDir.relativeFilePath(FS::PathCombine(backupPath, destination.fileName()));
|
||||
useXPHack = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(destination.exists())
|
||||
{
|
||||
QString backupName = op.destination;
|
||||
backupName.replace('/', '_');
|
||||
QString backupFilePath = FS::PathCombine(backupPath, backupName);
|
||||
if(!QFile::rename(destination.absoluteFilePath(), backupFilePath))
|
||||
{
|
||||
qWarning() << "Couldn't move:" << destination.absoluteFilePath() << "to" << backupFilePath;
|
||||
m_failedOperationType = Replace;
|
||||
m_failedFile = op.destination;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
BackupEntry be;
|
||||
be.original = destination.absoluteFilePath();
|
||||
be.backup = backupFilePath;
|
||||
be.update = op.source;
|
||||
m_replace_backups.append(be);
|
||||
}
|
||||
// make sure the folder we are putting this into exists
|
||||
if(!FS::ensureFilePathExists(destination.absoluteFilePath()))
|
||||
{
|
||||
qWarning() << "REPLACE: Couldn't create folder:" << destination.absoluteFilePath();
|
||||
m_failedOperationType = Replace;
|
||||
m_failedFile = op.destination;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
// now move the new file in
|
||||
if(!QFile::rename(op.source, destination.absoluteFilePath()))
|
||||
{
|
||||
qWarning() << "REPLACE: Couldn't move:" << op.source << "to" << destination.absoluteFilePath();
|
||||
m_failedOperationType = Replace;
|
||||
m_failedFile = op.destination;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
QFile::setPermissions(destination.absoluteFilePath(), unixModeToPermissions(op.destinationMode));
|
||||
}
|
||||
break;
|
||||
// delete = move original to backup
|
||||
case GoUpdate::Operation::OP_DELETE:
|
||||
{
|
||||
QString destFilePath = FS::PathCombine(m_root, op.destination);
|
||||
if(QFile::exists(destFilePath))
|
||||
{
|
||||
QString backupName = op.destination;
|
||||
backupName.replace('/', '_');
|
||||
QString trashFilePath = FS::PathCombine(backupPath, backupName);
|
||||
if(destination.exists())
|
||||
{
|
||||
QString backupName = op.destination;
|
||||
backupName.replace('/', '_');
|
||||
QString backupFilePath = FS::PathCombine(backupPath, backupName);
|
||||
if(!QFile::rename(destination.absoluteFilePath(), backupFilePath))
|
||||
{
|
||||
qWarning() << "Couldn't move:" << destination.absoluteFilePath() << "to" << backupFilePath;
|
||||
m_failedOperationType = Replace;
|
||||
m_failedFile = op.destination;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
BackupEntry be;
|
||||
be.original = destination.absoluteFilePath();
|
||||
be.backup = backupFilePath;
|
||||
be.update = op.source;
|
||||
m_replace_backups.append(be);
|
||||
}
|
||||
// make sure the folder we are putting this into exists
|
||||
if(!FS::ensureFilePathExists(destination.absoluteFilePath()))
|
||||
{
|
||||
qWarning() << "REPLACE: Couldn't create folder:" << destination.absoluteFilePath();
|
||||
m_failedOperationType = Replace;
|
||||
m_failedFile = op.destination;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
// now move the new file in
|
||||
if(!QFile::rename(op.source, destination.absoluteFilePath()))
|
||||
{
|
||||
qWarning() << "REPLACE: Couldn't move:" << op.source << "to" << destination.absoluteFilePath();
|
||||
m_failedOperationType = Replace;
|
||||
m_failedFile = op.destination;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
QFile::setPermissions(destination.absoluteFilePath(), unixModeToPermissions(op.destinationMode));
|
||||
}
|
||||
break;
|
||||
// delete = move original to backup
|
||||
case GoUpdate::Operation::OP_DELETE:
|
||||
{
|
||||
QString destFilePath = FS::PathCombine(m_root, op.destination);
|
||||
if(QFile::exists(destFilePath))
|
||||
{
|
||||
QString backupName = op.destination;
|
||||
backupName.replace('/', '_');
|
||||
QString trashFilePath = FS::PathCombine(backupPath, backupName);
|
||||
|
||||
if(!QFile::rename(destFilePath, trashFilePath))
|
||||
{
|
||||
qWarning() << "DELETE: Couldn't move:" << op.destination << "to" << trashFilePath;
|
||||
m_failedFile = op.destination;
|
||||
m_failedOperationType = Delete;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
BackupEntry be;
|
||||
be.original = destFilePath;
|
||||
be.backup = trashFilePath;
|
||||
m_delete_backups.append(be);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!QFile::rename(destFilePath, trashFilePath))
|
||||
{
|
||||
qWarning() << "DELETE: Couldn't move:" << op.destination << "to" << trashFilePath;
|
||||
m_failedFile = op.destination;
|
||||
m_failedOperationType = Delete;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
BackupEntry be;
|
||||
be.original = destFilePath;
|
||||
be.backup = trashFilePath;
|
||||
m_delete_backups.append(be);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// try to start the new binary
|
||||
args = qApp->arguments();
|
||||
args.removeFirst();
|
||||
// try to start the new binary
|
||||
args = qApp->arguments();
|
||||
args.removeFirst();
|
||||
|
||||
// on old Windows, do insane things... no error checking here, this is just to have something.
|
||||
if(useXPHack)
|
||||
{
|
||||
QString script;
|
||||
auto nativePath = QDir::toNativeSeparators(exePath);
|
||||
auto nativeOriginPath = QDir::toNativeSeparators(exeOrigin);
|
||||
auto nativeBackupPath = QDir::toNativeSeparators(exeBackup);
|
||||
// on old Windows, do insane things... no error checking here, this is just to have something.
|
||||
if(useXPHack)
|
||||
{
|
||||
QString script;
|
||||
auto nativePath = QDir::toNativeSeparators(exePath);
|
||||
auto nativeOriginPath = QDir::toNativeSeparators(exeOrigin);
|
||||
auto nativeBackupPath = QDir::toNativeSeparators(exeBackup);
|
||||
|
||||
// so we write this vbscript thing...
|
||||
QTextStream out(&script);
|
||||
out << "WScript.Sleep 1000\n";
|
||||
out << "Set fso=CreateObject(\"Scripting.FileSystemObject\")\n";
|
||||
out << "Set shell=CreateObject(\"WScript.Shell\")\n";
|
||||
out << "fso.MoveFile \"" << nativePath << "\", \"" << nativeBackupPath << "\"\n";
|
||||
out << "fso.MoveFile \"" << nativeOriginPath << "\", \"" << nativePath << "\"\n";
|
||||
out << "shell.Run \"" << nativePath << "\"\n";
|
||||
// so we write this vbscript thing...
|
||||
QTextStream out(&script);
|
||||
out << "WScript.Sleep 1000\n";
|
||||
out << "Set fso=CreateObject(\"Scripting.FileSystemObject\")\n";
|
||||
out << "Set shell=CreateObject(\"WScript.Shell\")\n";
|
||||
out << "fso.MoveFile \"" << nativePath << "\", \"" << nativeBackupPath << "\"\n";
|
||||
out << "fso.MoveFile \"" << nativeOriginPath << "\", \"" << nativePath << "\"\n";
|
||||
out << "shell.Run \"" << nativePath << "\"\n";
|
||||
|
||||
QString scriptPath = FS::PathCombine(m_root, "update", "update.vbs");
|
||||
QString scriptPath = FS::PathCombine(m_root, "update", "update.vbs");
|
||||
|
||||
// we save it
|
||||
QFile scriptFile(scriptPath);
|
||||
scriptFile.open(QIODevice::WriteOnly);
|
||||
scriptFile.write(script.toLocal8Bit().replace("\n", "\r\n"));
|
||||
scriptFile.close();
|
||||
// we save it
|
||||
QFile scriptFile(scriptPath);
|
||||
scriptFile.open(QIODevice::WriteOnly);
|
||||
scriptFile.write(script.toLocal8Bit().replace("\n", "\r\n"));
|
||||
scriptFile.close();
|
||||
|
||||
// we run it
|
||||
started = QProcess::startDetached("wscript", {scriptPath}, m_root);
|
||||
// we run it
|
||||
started = QProcess::startDetached("wscript", {scriptPath}, m_root);
|
||||
|
||||
// and we quit. conscious thought.
|
||||
qApp->quit();
|
||||
return;
|
||||
}
|
||||
bool doLiveCheck = true;
|
||||
bool startFailed = false;
|
||||
// and we quit. conscious thought.
|
||||
qApp->quit();
|
||||
return;
|
||||
}
|
||||
bool doLiveCheck = true;
|
||||
bool startFailed = false;
|
||||
|
||||
// remove live check file, if any
|
||||
if(QFile::exists(liveCheckFile))
|
||||
{
|
||||
if(!QFile::remove(liveCheckFile))
|
||||
{
|
||||
qWarning() << "Couldn't remove the" << liveCheckFile << "file! We will proceed without :(";
|
||||
doLiveCheck = false;
|
||||
}
|
||||
}
|
||||
// remove live check file, if any
|
||||
if(QFile::exists(liveCheckFile))
|
||||
{
|
||||
if(!QFile::remove(liveCheckFile))
|
||||
{
|
||||
qWarning() << "Couldn't remove the" << liveCheckFile << "file! We will proceed without :(";
|
||||
doLiveCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(doLiveCheck)
|
||||
{
|
||||
if(!args.contains("--alive"))
|
||||
{
|
||||
args.append("--alive");
|
||||
}
|
||||
}
|
||||
if(doLiveCheck)
|
||||
{
|
||||
if(!args.contains("--alive"))
|
||||
{
|
||||
args.append("--alive");
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: reparse args and construct a safe variant from scratch. This is a workaround for GH-1874:
|
||||
QStringList realargs;
|
||||
int skip = 0;
|
||||
for(auto & arg: args)
|
||||
{
|
||||
if(skip)
|
||||
{
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
if(arg == "-l")
|
||||
{
|
||||
skip = 1;
|
||||
continue;
|
||||
}
|
||||
realargs.append(arg);
|
||||
}
|
||||
// FIXME: reparse args and construct a safe variant from scratch. This is a workaround for GH-1874:
|
||||
QStringList realargs;
|
||||
int skip = 0;
|
||||
for(auto & arg: args)
|
||||
{
|
||||
if(skip)
|
||||
{
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
if(arg == "-l")
|
||||
{
|
||||
skip = 1;
|
||||
continue;
|
||||
}
|
||||
realargs.append(arg);
|
||||
}
|
||||
|
||||
// start the updated application
|
||||
started = QProcess::startDetached(finishCmd, realargs, QDir::currentPath(), &pid);
|
||||
// much dumber check - just find out if the call
|
||||
if(!started || pid == -1)
|
||||
{
|
||||
qWarning() << "Couldn't start new process properly!";
|
||||
startFailed = true;
|
||||
}
|
||||
if(!startFailed && doLiveCheck)
|
||||
{
|
||||
int attempts = 0;
|
||||
while(attempts < 10)
|
||||
{
|
||||
attempts++;
|
||||
QString key;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
if(!QFile::exists(liveCheckFile))
|
||||
{
|
||||
qWarning() << "Couldn't find the" << liveCheckFile << "file!";
|
||||
startFailed = true;
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
key = QString::fromUtf8(FS::read(liveCheckFile));
|
||||
auto id = ApplicationId::fromRawString(key);
|
||||
LocalPeer peer(nullptr, id);
|
||||
if(peer.isClient())
|
||||
{
|
||||
startFailed = false;
|
||||
qDebug() << "Found process started with key " << key;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
startFailed = true;
|
||||
qDebug() << "Process started with key " << key << "apparently died or is not reponding...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qWarning() << "Couldn't read the" << liveCheckFile << "file!";
|
||||
startFailed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(startFailed)
|
||||
{
|
||||
m_failedOperationType = Start;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
origin.rmdir(m_updateFilesDir);
|
||||
qApp->quit();
|
||||
return;
|
||||
}
|
||||
// start the updated application
|
||||
started = QProcess::startDetached(finishCmd, realargs, QDir::currentPath(), &pid);
|
||||
// much dumber check - just find out if the call
|
||||
if(!started || pid == -1)
|
||||
{
|
||||
qWarning() << "Couldn't start new process properly!";
|
||||
startFailed = true;
|
||||
}
|
||||
if(!startFailed && doLiveCheck)
|
||||
{
|
||||
int attempts = 0;
|
||||
while(attempts < 10)
|
||||
{
|
||||
attempts++;
|
||||
QString key;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
if(!QFile::exists(liveCheckFile))
|
||||
{
|
||||
qWarning() << "Couldn't find the" << liveCheckFile << "file!";
|
||||
startFailed = true;
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
key = QString::fromUtf8(FS::read(liveCheckFile));
|
||||
auto id = ApplicationId::fromRawString(key);
|
||||
LocalPeer peer(nullptr, id);
|
||||
if(peer.isClient())
|
||||
{
|
||||
startFailed = false;
|
||||
qDebug() << "Found process started with key " << key;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
startFailed = true;
|
||||
qDebug() << "Process started with key " << key << "apparently died or is not reponding...";
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qWarning() << "Couldn't read the" << liveCheckFile << "file!";
|
||||
startFailed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(startFailed)
|
||||
{
|
||||
m_failedOperationType = Start;
|
||||
fail();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
origin.rmdir(m_updateFilesDir);
|
||||
qApp->quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateController::fail()
|
||||
{
|
||||
qWarning() << "Update failed!";
|
||||
qWarning() << "Update failed!";
|
||||
|
||||
QString msg;
|
||||
bool doRollback = false;
|
||||
QString failTitle = QObject::tr("Update failed!");
|
||||
QString rollFailTitle = QObject::tr("Rollback failed!");
|
||||
switch (m_failedOperationType)
|
||||
{
|
||||
case Replace:
|
||||
{
|
||||
msg = QObject::tr("Couldn't replace file %1. Changes will be reverted.\n"
|
||||
"See the MultiMC log file for details.").arg(m_failedFile);
|
||||
doRollback = true;
|
||||
QMessageBox::critical(m_parent, failTitle, msg);
|
||||
break;
|
||||
}
|
||||
case Delete:
|
||||
{
|
||||
msg = QObject::tr("Couldn't remove file %1. Changes will be reverted.\n"
|
||||
"See the MultiMC log file for details.").arg(m_failedFile);
|
||||
doRollback = true;
|
||||
QMessageBox::critical(m_parent, failTitle, msg);
|
||||
break;
|
||||
}
|
||||
case Start:
|
||||
{
|
||||
msg = QObject::tr("The new version didn't start or is too old and doesn't respond to startup checks.\n"
|
||||
"\n"
|
||||
"Roll back to previous version?");
|
||||
auto result = QMessageBox::critical(
|
||||
m_parent,
|
||||
failTitle,
|
||||
msg,
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::Yes
|
||||
);
|
||||
doRollback = (result == QMessageBox::Yes);
|
||||
break;
|
||||
}
|
||||
case Nothing:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if(doRollback)
|
||||
{
|
||||
auto rollbackOK = rollback();
|
||||
if(!rollbackOK)
|
||||
{
|
||||
msg = QObject::tr("The rollback failed too.\n"
|
||||
"You will have to repair MultiMC manually.\n"
|
||||
"Please let us know why and how this happened.").arg(m_failedFile);
|
||||
QMessageBox::critical(m_parent, rollFailTitle, msg);
|
||||
qApp->quit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qApp->quit();
|
||||
}
|
||||
QString msg;
|
||||
bool doRollback = false;
|
||||
QString failTitle = QObject::tr("Update failed!");
|
||||
QString rollFailTitle = QObject::tr("Rollback failed!");
|
||||
switch (m_failedOperationType)
|
||||
{
|
||||
case Replace:
|
||||
{
|
||||
msg = QObject::tr("Couldn't replace file %1. Changes will be reverted.\n"
|
||||
"See the MultiMC log file for details.").arg(m_failedFile);
|
||||
doRollback = true;
|
||||
QMessageBox::critical(m_parent, failTitle, msg);
|
||||
break;
|
||||
}
|
||||
case Delete:
|
||||
{
|
||||
msg = QObject::tr("Couldn't remove file %1. Changes will be reverted.\n"
|
||||
"See the MultiMC log file for details.").arg(m_failedFile);
|
||||
doRollback = true;
|
||||
QMessageBox::critical(m_parent, failTitle, msg);
|
||||
break;
|
||||
}
|
||||
case Start:
|
||||
{
|
||||
msg = QObject::tr("The new version didn't start or is too old and doesn't respond to startup checks.\n"
|
||||
"\n"
|
||||
"Roll back to previous version?");
|
||||
auto result = QMessageBox::critical(
|
||||
m_parent,
|
||||
failTitle,
|
||||
msg,
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::Yes
|
||||
);
|
||||
doRollback = (result == QMessageBox::Yes);
|
||||
break;
|
||||
}
|
||||
case Nothing:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if(doRollback)
|
||||
{
|
||||
auto rollbackOK = rollback();
|
||||
if(!rollbackOK)
|
||||
{
|
||||
msg = QObject::tr("The rollback failed too.\n"
|
||||
"You will have to repair MultiMC manually.\n"
|
||||
"Please let us know why and how this happened.").arg(m_failedFile);
|
||||
QMessageBox::critical(m_parent, rollFailTitle, msg);
|
||||
qApp->quit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qApp->quit();
|
||||
}
|
||||
}
|
||||
|
||||
bool UpdateController::rollback()
|
||||
{
|
||||
bool revertOK = true;
|
||||
// if the above failed, roll back changes
|
||||
for(auto backup:m_replace_backups)
|
||||
{
|
||||
qWarning() << "restoring" << backup.original << "from" << backup.backup;
|
||||
if(!QFile::rename(backup.original, backup.update))
|
||||
{
|
||||
revertOK = false;
|
||||
qWarning() << "moving new" << backup.original << "back to" << backup.update << "failed!";
|
||||
continue;
|
||||
}
|
||||
bool revertOK = true;
|
||||
// if the above failed, roll back changes
|
||||
for(auto backup:m_replace_backups)
|
||||
{
|
||||
qWarning() << "restoring" << backup.original << "from" << backup.backup;
|
||||
if(!QFile::rename(backup.original, backup.update))
|
||||
{
|
||||
revertOK = false;
|
||||
qWarning() << "moving new" << backup.original << "back to" << backup.update << "failed!";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!QFile::rename(backup.backup, backup.original))
|
||||
{
|
||||
revertOK = false;
|
||||
qWarning() << "restoring" << backup.original << "failed!";
|
||||
}
|
||||
}
|
||||
for(auto backup:m_delete_backups)
|
||||
{
|
||||
qWarning() << "restoring" << backup.original << "from" << backup.backup;
|
||||
if(!QFile::rename(backup.backup, backup.original))
|
||||
{
|
||||
revertOK = false;
|
||||
qWarning() << "restoring" << backup.original << "failed!";
|
||||
}
|
||||
}
|
||||
return revertOK;
|
||||
if(!QFile::rename(backup.backup, backup.original))
|
||||
{
|
||||
revertOK = false;
|
||||
qWarning() << "restoring" << backup.original << "failed!";
|
||||
}
|
||||
}
|
||||
for(auto backup:m_delete_backups)
|
||||
{
|
||||
qWarning() << "restoring" << backup.original << "from" << backup.backup;
|
||||
if(!QFile::rename(backup.backup, backup.original))
|
||||
{
|
||||
revertOK = false;
|
||||
qWarning() << "restoring" << backup.original << "failed!";
|
||||
}
|
||||
}
|
||||
return revertOK;
|
||||
}
|
||||
|
@ -9,36 +9,36 @@ class QWidget;
|
||||
class UpdateController
|
||||
{
|
||||
public:
|
||||
UpdateController(QWidget * parent, const QString &root, const QString updateFilesDir, GoUpdate::OperationList operations);
|
||||
void installUpdates();
|
||||
UpdateController(QWidget * parent, const QString &root, const QString updateFilesDir, GoUpdate::OperationList operations);
|
||||
void installUpdates();
|
||||
|
||||
private:
|
||||
void fail();
|
||||
bool rollback();
|
||||
void fail();
|
||||
bool rollback();
|
||||
|
||||
private:
|
||||
QString m_root;
|
||||
QString m_updateFilesDir;
|
||||
GoUpdate::OperationList m_operations;
|
||||
QWidget * m_parent;
|
||||
QString m_root;
|
||||
QString m_updateFilesDir;
|
||||
GoUpdate::OperationList m_operations;
|
||||
QWidget * m_parent;
|
||||
|
||||
struct BackupEntry
|
||||
{
|
||||
// path where we got the new file from
|
||||
QString update;
|
||||
// path of what is being actually updated
|
||||
QString original;
|
||||
// path where the backup of the updated file was placed
|
||||
QString backup;
|
||||
};
|
||||
QList <BackupEntry> m_replace_backups;
|
||||
QList <BackupEntry> m_delete_backups;
|
||||
enum Failure
|
||||
{
|
||||
Replace,
|
||||
Delete,
|
||||
Start,
|
||||
Nothing
|
||||
} m_failedOperationType = Nothing;
|
||||
QString m_failedFile;
|
||||
struct BackupEntry
|
||||
{
|
||||
// path where we got the new file from
|
||||
QString update;
|
||||
// path of what is being actually updated
|
||||
QString original;
|
||||
// path where the backup of the updated file was placed
|
||||
QString backup;
|
||||
};
|
||||
QList <BackupEntry> m_replace_backups;
|
||||
QList <BackupEntry> m_delete_backups;
|
||||
enum Failure
|
||||
{
|
||||
Replace,
|
||||
Delete,
|
||||
Start,
|
||||
Nothing
|
||||
} m_failedOperationType = Nothing;
|
||||
QString m_failedFile;
|
||||
};
|
||||
|
@ -7,429 +7,429 @@
|
||||
|
||||
class VersionFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
VersionFilterModel(VersionProxyModel *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
setSortRole(BaseVersionList::SortRole);
|
||||
sort(0, Qt::DescendingOrder);
|
||||
}
|
||||
VersionFilterModel(VersionProxyModel *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
setSortRole(BaseVersionList::SortRole);
|
||||
sort(0, Qt::DescendingOrder);
|
||||
}
|
||||
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
const auto &filters = m_parent->filters();
|
||||
for (auto it = filters.begin(); it != filters.end(); ++it)
|
||||
{
|
||||
auto idx = sourceModel()->index(source_row, 0, source_parent);
|
||||
auto data = sourceModel()->data(idx, it.key());
|
||||
auto match = data.toString();
|
||||
if(!it.value()->accepts(match))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
const auto &filters = m_parent->filters();
|
||||
for (auto it = filters.begin(); it != filters.end(); ++it)
|
||||
{
|
||||
auto idx = sourceModel()->index(source_row, 0, source_parent);
|
||||
auto data = sourceModel()->data(idx, it.key());
|
||||
auto match = data.toString();
|
||||
if(!it.value()->accepts(match))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void filterChanged()
|
||||
{
|
||||
invalidateFilter();
|
||||
}
|
||||
void filterChanged()
|
||||
{
|
||||
invalidateFilter();
|
||||
}
|
||||
private:
|
||||
VersionProxyModel *m_parent;
|
||||
VersionProxyModel *m_parent;
|
||||
};
|
||||
|
||||
VersionProxyModel::VersionProxyModel(QObject *parent) : QAbstractProxyModel(parent)
|
||||
{
|
||||
filterModel = new VersionFilterModel(this);
|
||||
connect(filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged);
|
||||
connect(filterModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &VersionProxyModel::sourceRowsAboutToBeInserted);
|
||||
connect(filterModel, &QAbstractItemModel::rowsInserted, this, &VersionProxyModel::sourceRowsInserted);
|
||||
connect(filterModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &VersionProxyModel::sourceRowsAboutToBeRemoved);
|
||||
connect(filterModel, &QAbstractItemModel::rowsRemoved, this, &VersionProxyModel::sourceRowsRemoved);
|
||||
// FIXME: implement when needed
|
||||
/*
|
||||
connect(replacing, &QAbstractItemModel::rowsAboutToBeMoved, this, &VersionProxyModel::sourceRowsAboutToBeMoved);
|
||||
connect(replacing, &QAbstractItemModel::rowsMoved, this, &VersionProxyModel::sourceRowsMoved);
|
||||
connect(replacing, &QAbstractItemModel::layoutAboutToBeChanged, this, &VersionProxyModel::sourceLayoutAboutToBeChanged);
|
||||
connect(replacing, &QAbstractItemModel::layoutChanged, this, &VersionProxyModel::sourceLayoutChanged);
|
||||
*/
|
||||
connect(filterModel, &QAbstractItemModel::modelAboutToBeReset, this, &VersionProxyModel::sourceAboutToBeReset);
|
||||
connect(filterModel, &QAbstractItemModel::modelReset, this, &VersionProxyModel::sourceReset);
|
||||
filterModel = new VersionFilterModel(this);
|
||||
connect(filterModel, &QAbstractItemModel::dataChanged, this, &VersionProxyModel::sourceDataChanged);
|
||||
connect(filterModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &VersionProxyModel::sourceRowsAboutToBeInserted);
|
||||
connect(filterModel, &QAbstractItemModel::rowsInserted, this, &VersionProxyModel::sourceRowsInserted);
|
||||
connect(filterModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &VersionProxyModel::sourceRowsAboutToBeRemoved);
|
||||
connect(filterModel, &QAbstractItemModel::rowsRemoved, this, &VersionProxyModel::sourceRowsRemoved);
|
||||
// FIXME: implement when needed
|
||||
/*
|
||||
connect(replacing, &QAbstractItemModel::rowsAboutToBeMoved, this, &VersionProxyModel::sourceRowsAboutToBeMoved);
|
||||
connect(replacing, &QAbstractItemModel::rowsMoved, this, &VersionProxyModel::sourceRowsMoved);
|
||||
connect(replacing, &QAbstractItemModel::layoutAboutToBeChanged, this, &VersionProxyModel::sourceLayoutAboutToBeChanged);
|
||||
connect(replacing, &QAbstractItemModel::layoutChanged, this, &VersionProxyModel::sourceLayoutChanged);
|
||||
*/
|
||||
connect(filterModel, &QAbstractItemModel::modelAboutToBeReset, this, &VersionProxyModel::sourceAboutToBeReset);
|
||||
connect(filterModel, &QAbstractItemModel::modelReset, this, &VersionProxyModel::sourceReset);
|
||||
|
||||
QAbstractProxyModel::setSourceModel(filterModel);
|
||||
QAbstractProxyModel::setSourceModel(filterModel);
|
||||
}
|
||||
|
||||
QVariant VersionProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if(section < 0 || section >= m_columns.size())
|
||||
return QVariant();
|
||||
if(orientation != Qt::Horizontal)
|
||||
return QVariant();
|
||||
auto column = m_columns[section];
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return tr("Version");
|
||||
case ParentVersion:
|
||||
return tr("Minecraft"); //FIXME: this should come from metadata
|
||||
case Branch:
|
||||
return tr("Branch");
|
||||
case Type:
|
||||
return tr("Type");
|
||||
case Architecture:
|
||||
return tr("Architecture");
|
||||
case Path:
|
||||
return tr("Path");
|
||||
case Time:
|
||||
return tr("Released");
|
||||
}
|
||||
}
|
||||
else if(role == Qt::ToolTipRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return tr("The name of the version.");
|
||||
case ParentVersion:
|
||||
return tr("Minecraft version"); //FIXME: this should come from metadata
|
||||
case Branch:
|
||||
return tr("The version's branch");
|
||||
case Type:
|
||||
return tr("The version's type");
|
||||
case Architecture:
|
||||
return tr("CPU Architecture");
|
||||
case Path:
|
||||
return tr("Filesystem path to this version");
|
||||
case Time:
|
||||
return tr("Release date of this version");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
if(section < 0 || section >= m_columns.size())
|
||||
return QVariant();
|
||||
if(orientation != Qt::Horizontal)
|
||||
return QVariant();
|
||||
auto column = m_columns[section];
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return tr("Version");
|
||||
case ParentVersion:
|
||||
return tr("Minecraft"); //FIXME: this should come from metadata
|
||||
case Branch:
|
||||
return tr("Branch");
|
||||
case Type:
|
||||
return tr("Type");
|
||||
case Architecture:
|
||||
return tr("Architecture");
|
||||
case Path:
|
||||
return tr("Path");
|
||||
case Time:
|
||||
return tr("Released");
|
||||
}
|
||||
}
|
||||
else if(role == Qt::ToolTipRole)
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return tr("The name of the version.");
|
||||
case ParentVersion:
|
||||
return tr("Minecraft version"); //FIXME: this should come from metadata
|
||||
case Branch:
|
||||
return tr("The version's branch");
|
||||
case Type:
|
||||
return tr("The version's type");
|
||||
case Architecture:
|
||||
return tr("CPU Architecture");
|
||||
case Path:
|
||||
return tr("Filesystem path to this version");
|
||||
case Time:
|
||||
return tr("Release date of this version");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant VersionProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
auto column = m_columns[index.column()];
|
||||
auto parentIndex = mapToSource(index);
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::VersionRole);
|
||||
case ParentVersion:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::ParentVersionRole);
|
||||
case Branch:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::BranchRole);
|
||||
case Type:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::TypeRole);
|
||||
case Architecture:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole);
|
||||
case Path:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
||||
case Time:
|
||||
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
{
|
||||
if(hasRecommended)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return tr("Recommended");
|
||||
}
|
||||
else if(hasLatest)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return tr("Latest");
|
||||
}
|
||||
}
|
||||
else if(index.row() == 0)
|
||||
{
|
||||
return tr("Latest");
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
{
|
||||
if(hasRecommended)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return MMC->getThemedIcon("star");
|
||||
}
|
||||
else if(hasLatest)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return MMC->getThemedIcon("bug");
|
||||
}
|
||||
}
|
||||
else if(index.row() == 0)
|
||||
{
|
||||
return MMC->getThemedIcon("bug");
|
||||
}
|
||||
auto pixmap = QPixmapCache::find("placeholder");
|
||||
if(!pixmap)
|
||||
{
|
||||
QPixmap px(16,16);
|
||||
px.fill(Qt::transparent);
|
||||
QPixmapCache::insert("placeholder", px);
|
||||
return px;
|
||||
}
|
||||
return *pixmap;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(roles.contains((BaseVersionList::ModelRoles)role))
|
||||
{
|
||||
return sourceModel()->data(parentIndex, role);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
if(!index.isValid())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
auto column = m_columns[index.column()];
|
||||
auto parentIndex = mapToSource(index);
|
||||
switch(role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::VersionRole);
|
||||
case ParentVersion:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::ParentVersionRole);
|
||||
case Branch:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::BranchRole);
|
||||
case Type:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::TypeRole);
|
||||
case Architecture:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::ArchitectureRole);
|
||||
case Path:
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::PathRole);
|
||||
case Time:
|
||||
return sourceModel()->data(parentIndex, Meta::VersionList::TimeRole).toDate();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
{
|
||||
if(hasRecommended)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return tr("Recommended");
|
||||
}
|
||||
else if(hasLatest)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return tr("Latest");
|
||||
}
|
||||
}
|
||||
else if(index.row() == 0)
|
||||
{
|
||||
return tr("Latest");
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return sourceModel()->data(parentIndex, BaseVersionList::VersionIdRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
case Qt::DecorationRole:
|
||||
{
|
||||
switch(column)
|
||||
{
|
||||
case Name:
|
||||
{
|
||||
if(hasRecommended)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::RecommendedRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return MMC->getThemedIcon("star");
|
||||
}
|
||||
else if(hasLatest)
|
||||
{
|
||||
auto value = sourceModel()->data(parentIndex, BaseVersionList::LatestRole);
|
||||
if(value.toBool())
|
||||
{
|
||||
return MMC->getThemedIcon("bug");
|
||||
}
|
||||
}
|
||||
else if(index.row() == 0)
|
||||
{
|
||||
return MMC->getThemedIcon("bug");
|
||||
}
|
||||
auto pixmap = QPixmapCache::find("placeholder");
|
||||
if(!pixmap)
|
||||
{
|
||||
QPixmap px(16,16);
|
||||
px.fill(Qt::transparent);
|
||||
QPixmapCache::insert("placeholder", px);
|
||||
return px;
|
||||
}
|
||||
return *pixmap;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(roles.contains((BaseVersionList::ModelRoles)role))
|
||||
{
|
||||
return sourceModel()->data(parentIndex, role);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
return QModelIndex();
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
|
||||
{
|
||||
if(sourceIndex.isValid())
|
||||
{
|
||||
return index(sourceIndex.row(), 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
if(sourceIndex.isValid())
|
||||
{
|
||||
return index(sourceIndex.row(), 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
|
||||
{
|
||||
if(proxyIndex.isValid())
|
||||
{
|
||||
return sourceModel()->index(proxyIndex.row(), 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
if(proxyIndex.isValid())
|
||||
{
|
||||
return sourceModel()->index(proxyIndex.row(), 0);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
// no trees here... shoo
|
||||
if(parent.isValid())
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
if(row < 0 || row >= sourceModel()->rowCount())
|
||||
return QModelIndex();
|
||||
if(column < 0 || column >= columnCount())
|
||||
return QModelIndex();
|
||||
return QAbstractItemModel::createIndex(row, column);
|
||||
// no trees here... shoo
|
||||
if(parent.isValid())
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
if(row < 0 || row >= sourceModel()->rowCount())
|
||||
return QModelIndex();
|
||||
if(column < 0 || column >= columnCount())
|
||||
return QModelIndex();
|
||||
return QAbstractItemModel::createIndex(row, column);
|
||||
}
|
||||
|
||||
int VersionProxyModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return m_columns.size();
|
||||
return m_columns.size();
|
||||
}
|
||||
|
||||
int VersionProxyModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(sourceModel())
|
||||
{
|
||||
return sourceModel()->rowCount();
|
||||
}
|
||||
return 0;
|
||||
if(sourceModel())
|
||||
{
|
||||
return sourceModel()->rowCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceDataChanged(const QModelIndex &source_top_left,
|
||||
const QModelIndex &source_bottom_right)
|
||||
const QModelIndex &source_bottom_right)
|
||||
{
|
||||
if(source_top_left.parent() != source_bottom_right.parent())
|
||||
return;
|
||||
if(source_top_left.parent() != source_bottom_right.parent())
|
||||
return;
|
||||
|
||||
// whole row is getting changed
|
||||
auto topLeft = createIndex(source_top_left.row(), 0);
|
||||
auto bottomRight = createIndex(source_bottom_right.row(), columnCount() - 1);
|
||||
emit dataChanged(topLeft, bottomRight);
|
||||
// whole row is getting changed
|
||||
auto topLeft = createIndex(source_top_left.row(), 0);
|
||||
auto bottomRight = createIndex(source_bottom_right.row(), columnCount() - 1);
|
||||
emit dataChanged(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
void VersionProxyModel::setSourceModel(QAbstractItemModel *replacingRaw)
|
||||
{
|
||||
auto replacing = dynamic_cast<BaseVersionList *>(replacingRaw);
|
||||
beginResetModel();
|
||||
auto replacing = dynamic_cast<BaseVersionList *>(replacingRaw);
|
||||
beginResetModel();
|
||||
|
||||
m_columns.clear();
|
||||
if(!replacing)
|
||||
{
|
||||
roles.clear();
|
||||
filterModel->setSourceModel(replacing);
|
||||
return;
|
||||
}
|
||||
m_columns.clear();
|
||||
if(!replacing)
|
||||
{
|
||||
roles.clear();
|
||||
filterModel->setSourceModel(replacing);
|
||||
return;
|
||||
}
|
||||
|
||||
roles = replacing->providesRoles();
|
||||
if(roles.contains(BaseVersionList::VersionRole))
|
||||
{
|
||||
m_columns.push_back(Name);
|
||||
}
|
||||
/*
|
||||
if(roles.contains(BaseVersionList::ParentVersionRole))
|
||||
{
|
||||
m_columns.push_back(ParentVersion);
|
||||
}
|
||||
*/
|
||||
if(roles.contains(BaseVersionList::ArchitectureRole))
|
||||
{
|
||||
m_columns.push_back(Architecture);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::PathRole))
|
||||
{
|
||||
m_columns.push_back(Path);
|
||||
}
|
||||
if(roles.contains(Meta::VersionList::TimeRole))
|
||||
{
|
||||
m_columns.push_back(Time);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::BranchRole))
|
||||
{
|
||||
m_columns.push_back(Branch);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::TypeRole))
|
||||
{
|
||||
m_columns.push_back(Type);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::RecommendedRole))
|
||||
{
|
||||
hasRecommended = true;
|
||||
}
|
||||
if(roles.contains(BaseVersionList::LatestRole))
|
||||
{
|
||||
hasLatest = true;
|
||||
}
|
||||
filterModel->setSourceModel(replacing);
|
||||
roles = replacing->providesRoles();
|
||||
if(roles.contains(BaseVersionList::VersionRole))
|
||||
{
|
||||
m_columns.push_back(Name);
|
||||
}
|
||||
/*
|
||||
if(roles.contains(BaseVersionList::ParentVersionRole))
|
||||
{
|
||||
m_columns.push_back(ParentVersion);
|
||||
}
|
||||
*/
|
||||
if(roles.contains(BaseVersionList::ArchitectureRole))
|
||||
{
|
||||
m_columns.push_back(Architecture);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::PathRole))
|
||||
{
|
||||
m_columns.push_back(Path);
|
||||
}
|
||||
if(roles.contains(Meta::VersionList::TimeRole))
|
||||
{
|
||||
m_columns.push_back(Time);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::BranchRole))
|
||||
{
|
||||
m_columns.push_back(Branch);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::TypeRole))
|
||||
{
|
||||
m_columns.push_back(Type);
|
||||
}
|
||||
if(roles.contains(BaseVersionList::RecommendedRole))
|
||||
{
|
||||
hasRecommended = true;
|
||||
}
|
||||
if(roles.contains(BaseVersionList::LatestRole))
|
||||
{
|
||||
hasLatest = true;
|
||||
}
|
||||
filterModel->setSourceModel(replacing);
|
||||
|
||||
endResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::getRecommended() const
|
||||
{
|
||||
if(!roles.contains(BaseVersionList::RecommendedRole))
|
||||
{
|
||||
return index(0, 0);
|
||||
}
|
||||
int recommended = 0;
|
||||
for (int i = 0; i < rowCount(); i++)
|
||||
{
|
||||
auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole);
|
||||
if (value.toBool())
|
||||
{
|
||||
recommended = i;
|
||||
}
|
||||
}
|
||||
return index(recommended, 0);
|
||||
if(!roles.contains(BaseVersionList::RecommendedRole))
|
||||
{
|
||||
return index(0, 0);
|
||||
}
|
||||
int recommended = 0;
|
||||
for (int i = 0; i < rowCount(); i++)
|
||||
{
|
||||
auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::RecommendedRole);
|
||||
if (value.toBool())
|
||||
{
|
||||
recommended = i;
|
||||
}
|
||||
}
|
||||
return index(recommended, 0);
|
||||
}
|
||||
|
||||
QModelIndex VersionProxyModel::getVersion(const QString& version) const
|
||||
{
|
||||
int found = -1;
|
||||
for (int i = 0; i < rowCount(); i++)
|
||||
{
|
||||
auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::VersionRole);
|
||||
if (value.toString() == version)
|
||||
{
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
if(found == -1)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
return index(found, 0);
|
||||
int found = -1;
|
||||
for (int i = 0; i < rowCount(); i++)
|
||||
{
|
||||
auto value = sourceModel()->data(mapToSource(index(i, 0)), BaseVersionList::VersionRole);
|
||||
if (value.toString() == version)
|
||||
{
|
||||
found = i;
|
||||
}
|
||||
}
|
||||
if(found == -1)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
return index(found, 0);
|
||||
}
|
||||
|
||||
void VersionProxyModel::clearFilters()
|
||||
{
|
||||
m_filters.clear();
|
||||
filterModel->filterChanged();
|
||||
m_filters.clear();
|
||||
filterModel->filterChanged();
|
||||
}
|
||||
|
||||
void VersionProxyModel::setFilter(const BaseVersionList::ModelRoles column, Filter * f)
|
||||
{
|
||||
m_filters[column].reset(f);
|
||||
filterModel->filterChanged();
|
||||
m_filters[column].reset(f);
|
||||
filterModel->filterChanged();
|
||||
}
|
||||
|
||||
const VersionProxyModel::FilterMap &VersionProxyModel::filters() const
|
||||
{
|
||||
return m_filters;
|
||||
return m_filters;
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceAboutToBeReset()
|
||||
{
|
||||
beginResetModel();
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceReset()
|
||||
{
|
||||
endResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceRowsAboutToBeInserted(const QModelIndex& parent, int first, int last)
|
||||
{
|
||||
beginInsertRows(parent, first, last);
|
||||
beginInsertRows(parent, first, last);
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceRowsInserted(const QModelIndex& parent, int first, int last)
|
||||
{
|
||||
endInsertRows();
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceRowsAboutToBeRemoved(const QModelIndex& parent, int first, int last)
|
||||
{
|
||||
beginRemoveRows(parent, first, last);
|
||||
beginRemoveRows(parent, first, last);
|
||||
}
|
||||
|
||||
void VersionProxyModel::sourceRowsRemoved(const QModelIndex& parent, int first, int last)
|
||||
{
|
||||
endRemoveRows();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,58 +8,58 @@ class VersionFilterModel;
|
||||
|
||||
class VersionProxyModel: public QAbstractProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum Column
|
||||
{
|
||||
Name,
|
||||
ParentVersion,
|
||||
Branch,
|
||||
Type,
|
||||
Architecture,
|
||||
Path,
|
||||
Time
|
||||
};
|
||||
typedef QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>> FilterMap;
|
||||
enum Column
|
||||
{
|
||||
Name,
|
||||
ParentVersion,
|
||||
Branch,
|
||||
Type,
|
||||
Architecture,
|
||||
Path,
|
||||
Time
|
||||
};
|
||||
typedef QHash<BaseVersionList::ModelRoles, std::shared_ptr<Filter>> FilterMap;
|
||||
|
||||
public:
|
||||
VersionProxyModel ( QObject* parent = 0 );
|
||||
virtual ~VersionProxyModel() {};
|
||||
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
|
||||
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
virtual QModelIndex parent(const QModelIndex &child) const override;
|
||||
virtual void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
|
||||
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
virtual QModelIndex parent(const QModelIndex &child) const override;
|
||||
virtual void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
const FilterMap &filters() const;
|
||||
void setFilter(const BaseVersionList::ModelRoles column, Filter * filter);
|
||||
void clearFilters();
|
||||
QModelIndex getRecommended() const;
|
||||
QModelIndex getVersion(const QString & version) const;
|
||||
const FilterMap &filters() const;
|
||||
void setFilter(const BaseVersionList::ModelRoles column, Filter * filter);
|
||||
void clearFilters();
|
||||
QModelIndex getRecommended() const;
|
||||
QModelIndex getVersion(const QString & version) const;
|
||||
private slots:
|
||||
|
||||
void sourceDataChanged(const QModelIndex &source_top_left,const QModelIndex &source_bottom_right);
|
||||
void sourceDataChanged(const QModelIndex &source_top_left,const QModelIndex &source_bottom_right);
|
||||
|
||||
void sourceAboutToBeReset();
|
||||
void sourceReset();
|
||||
void sourceAboutToBeReset();
|
||||
void sourceReset();
|
||||
|
||||
void sourceRowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
|
||||
void sourceRowsInserted(const QModelIndex &parent, int first, int last);
|
||||
void sourceRowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
|
||||
void sourceRowsInserted(const QModelIndex &parent, int first, int last);
|
||||
|
||||
void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
|
||||
void sourceRowsRemoved(const QModelIndex &parent, int first, int last);
|
||||
void sourceRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
|
||||
void sourceRowsRemoved(const QModelIndex &parent, int first, int last);
|
||||
|
||||
private:
|
||||
QList<Column> m_columns;
|
||||
FilterMap m_filters;
|
||||
BaseVersionList::RoleList roles;
|
||||
VersionFilterModel * filterModel;
|
||||
bool hasRecommended = false;
|
||||
bool hasLatest = false;
|
||||
QList<Column> m_columns;
|
||||
FilterMap m_filters;
|
||||
BaseVersionList::RoleList roles;
|
||||
VersionFilterModel * filterModel;
|
||||
bool hasRecommended = false;
|
||||
bool hasLatest = false;
|
||||
};
|
||||
|
@ -27,113 +27,113 @@
|
||||
// This is a hack, but I can't think of a better way to do this easily without screwing with QTextDocument...
|
||||
static QString getCreditsHtml(QStringList patrons)
|
||||
{
|
||||
QString creditsHtml = QObject::tr(
|
||||
"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/REC-html40/strict.dtd'>"
|
||||
"<html>"
|
||||
""
|
||||
"<head>"
|
||||
"<meta name='qrichtext' content='1' />"
|
||||
"<style type='text/css'>"
|
||||
"p { white-space: pre-wrap; margin-top:2px; margin-bottom:2px; }"
|
||||
"</style>"
|
||||
"</head>"
|
||||
""
|
||||
"<body style=' font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;'>"
|
||||
""
|
||||
"<h3>MultiMC Developers</h3>"
|
||||
"<p>Andrew Okin <<a href='mailto:forkk@forkk.net'>forkk@forkk.net</a>></p>"
|
||||
"<p>Petr Mrázek <<a href='mailto:peterix@gmail.com'>peterix@gmail.com</a>></p>"
|
||||
"<p>Sky Welch <<a href='mailto:multimc@bunnies.io'>multimc@bunnies.io</a>></p>"
|
||||
"<p>Jan (02JanDal) <<a href='mailto:02jandal@gmail.com'>02jandal@gmail.com</a>></p>"
|
||||
"<p>RoboSky <<a href='https://twitter.com/RoboSky_'>@RoboSky_</a>></p>"
|
||||
""
|
||||
"<h3>With thanks to</h3>"
|
||||
"<p>Orochimarufan <<a href='mailto:orochimarufan.x3@gmail.com'>orochimarufan.x3@gmail.com</a>></p>"
|
||||
"<p>TakSuyu <<a href='mailto:taksuyu@gmail.com'>taksuyu@gmail.com</a>></p>"
|
||||
"<p>Kilobyte <<a href='mailto:stiepen22@gmx.de'>stiepen22@gmx.de</a>></p>"
|
||||
"<p>Rootbear75 <<a href='https://twitter.com/rootbear75'>@rootbear75</a>></p>"
|
||||
""
|
||||
"<h3>Patrons</h3>"
|
||||
"%1"
|
||||
""
|
||||
"</body>"
|
||||
"</html>");
|
||||
if (patrons.isEmpty())
|
||||
return creditsHtml.arg(QObject::tr("<p>Loading...</p>"));
|
||||
else
|
||||
{
|
||||
QString patronsStr;
|
||||
for (QString patron : patrons)
|
||||
{
|
||||
patronsStr.append(QString("<p>%1</p>").arg(patron));
|
||||
}
|
||||
QString creditsHtml = QObject::tr(
|
||||
"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0//EN' 'http://www.w3.org/TR/REC-html40/strict.dtd'>"
|
||||
"<html>"
|
||||
""
|
||||
"<head>"
|
||||
"<meta name='qrichtext' content='1' />"
|
||||
"<style type='text/css'>"
|
||||
"p { white-space: pre-wrap; margin-top:2px; margin-bottom:2px; }"
|
||||
"</style>"
|
||||
"</head>"
|
||||
""
|
||||
"<body style=' font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;'>"
|
||||
""
|
||||
"<h3>MultiMC Developers</h3>"
|
||||
"<p>Andrew Okin <<a href='mailto:forkk@forkk.net'>forkk@forkk.net</a>></p>"
|
||||
"<p>Petr Mrázek <<a href='mailto:peterix@gmail.com'>peterix@gmail.com</a>></p>"
|
||||
"<p>Sky Welch <<a href='mailto:multimc@bunnies.io'>multimc@bunnies.io</a>></p>"
|
||||
"<p>Jan (02JanDal) <<a href='mailto:02jandal@gmail.com'>02jandal@gmail.com</a>></p>"
|
||||
"<p>RoboSky <<a href='https://twitter.com/RoboSky_'>@RoboSky_</a>></p>"
|
||||
""
|
||||
"<h3>With thanks to</h3>"
|
||||
"<p>Orochimarufan <<a href='mailto:orochimarufan.x3@gmail.com'>orochimarufan.x3@gmail.com</a>></p>"
|
||||
"<p>TakSuyu <<a href='mailto:taksuyu@gmail.com'>taksuyu@gmail.com</a>></p>"
|
||||
"<p>Kilobyte <<a href='mailto:stiepen22@gmx.de'>stiepen22@gmx.de</a>></p>"
|
||||
"<p>Rootbear75 <<a href='https://twitter.com/rootbear75'>@rootbear75</a>></p>"
|
||||
""
|
||||
"<h3>Patrons</h3>"
|
||||
"%1"
|
||||
""
|
||||
"</body>"
|
||||
"</html>");
|
||||
if (patrons.isEmpty())
|
||||
return creditsHtml.arg(QObject::tr("<p>Loading...</p>"));
|
||||
else
|
||||
{
|
||||
QString patronsStr;
|
||||
for (QString patron : patrons)
|
||||
{
|
||||
patronsStr.append(QString("<p>%1</p>").arg(patron));
|
||||
}
|
||||
|
||||
return creditsHtml.arg(patronsStr);
|
||||
}
|
||||
return creditsHtml.arg(patronsStr);
|
||||
}
|
||||
}
|
||||
|
||||
static QString getLicenseHtml()
|
||||
{
|
||||
HoeDown hoedown;
|
||||
QFile dataFile(":/documents/COPYING.md");
|
||||
dataFile.open(QIODevice::ReadOnly);
|
||||
QString output = hoedown.process(dataFile.readAll());
|
||||
return output;
|
||||
HoeDown hoedown;
|
||||
QFile dataFile(":/documents/COPYING.md");
|
||||
dataFile.open(QIODevice::ReadOnly);
|
||||
QString output = hoedown.process(dataFile.readAll());
|
||||
return output;
|
||||
}
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
QString chtml = getCreditsHtml(QStringList());
|
||||
ui->creditsText->setHtml(chtml);
|
||||
QString chtml = getCreditsHtml(QStringList());
|
||||
ui->creditsText->setHtml(chtml);
|
||||
|
||||
QString lhtml = getLicenseHtml();
|
||||
ui->licenseText->setHtml(lhtml);
|
||||
QString lhtml = getLicenseHtml();
|
||||
ui->licenseText->setHtml(lhtml);
|
||||
|
||||
ui->urlLabel->setOpenExternalLinks(true);
|
||||
ui->urlLabel->setOpenExternalLinks(true);
|
||||
|
||||
ui->icon->setPixmap(MMC->getThemedIcon("logo").pixmap(64));
|
||||
ui->title->setText("MultiMC 5");
|
||||
ui->icon->setPixmap(MMC->getThemedIcon("logo").pixmap(64));
|
||||
ui->title->setText("MultiMC 5");
|
||||
|
||||
ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString());
|
||||
ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM);
|
||||
ui->versionLabel->setText(tr("Version") +": " + BuildConfig.printableVersionString());
|
||||
ui->platformLabel->setText(tr("Platform") +": " + BuildConfig.BUILD_PLATFORM);
|
||||
|
||||
if (BuildConfig.VERSION_BUILD >= 0)
|
||||
ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(BuildConfig.VERSION_BUILD));
|
||||
else
|
||||
ui->buildNumLabel->setVisible(false);
|
||||
if (BuildConfig.VERSION_BUILD >= 0)
|
||||
ui->buildNumLabel->setText(tr("Build Number") +": " + QString::number(BuildConfig.VERSION_BUILD));
|
||||
else
|
||||
ui->buildNumLabel->setVisible(false);
|
||||
|
||||
if (!BuildConfig.VERSION_CHANNEL.isEmpty())
|
||||
ui->channelLabel->setText(tr("Channel") +": " + BuildConfig.VERSION_CHANNEL);
|
||||
else
|
||||
ui->channelLabel->setVisible(false);
|
||||
if (!BuildConfig.VERSION_CHANNEL.isEmpty())
|
||||
ui->channelLabel->setText(tr("Channel") +": " + BuildConfig.VERSION_CHANNEL);
|
||||
else
|
||||
ui->channelLabel->setVisible(false);
|
||||
|
||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||
connect(ui->closeButton, SIGNAL(clicked()), SLOT(close()));
|
||||
|
||||
connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt);
|
||||
connect(ui->aboutQt, &QPushButton::clicked, &QApplication::aboutQt);
|
||||
|
||||
loadPatronList();
|
||||
loadPatronList();
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AboutDialog::loadPatronList()
|
||||
{
|
||||
netJob.reset(new NetJob("Patreon Patron List"));
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl("http://files.multimc.org/patrons.txt"), &dataSink));
|
||||
connect(netJob.get(), &NetJob::succeeded, this, &AboutDialog::patronListLoaded);
|
||||
netJob->start();
|
||||
netJob.reset(new NetJob("Patreon Patron List"));
|
||||
netJob->addNetAction(Net::Download::makeByteArray(QUrl("http://files.multimc.org/patrons.txt"), &dataSink));
|
||||
connect(netJob.get(), &NetJob::succeeded, this, &AboutDialog::patronListLoaded);
|
||||
netJob->start();
|
||||
}
|
||||
|
||||
void AboutDialog::patronListLoaded()
|
||||
{
|
||||
QString patronListStr(dataSink);
|
||||
dataSink.clear();
|
||||
QString html = getCreditsHtml(patronListStr.split("\n", QString::SkipEmptyParts));
|
||||
ui->creditsText->setHtml(html);
|
||||
QString patronListStr(dataSink);
|
||||
dataSink.clear();
|
||||
QString html = getCreditsHtml(patronListStr.split("\n", QString::SkipEmptyParts));
|
||||
ui->creditsText->setHtml(html);
|
||||
}
|
||||
|
||||
|
@ -25,23 +25,23 @@ class AboutDialog;
|
||||
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AboutDialog(QWidget *parent = 0);
|
||||
~AboutDialog();
|
||||
explicit AboutDialog(QWidget *parent = 0);
|
||||
~AboutDialog();
|
||||
|
||||
public
|
||||
slots:
|
||||
/// Starts loading a list of Patreon patrons.
|
||||
void loadPatronList();
|
||||
|
||||
/// Slot for when the patron list loads successfully.
|
||||
void patronListLoaded();
|
||||
/// Starts loading a list of Patreon patrons.
|
||||
void loadPatronList();
|
||||
|
||||
/// Slot for when the patron list loads successfully.
|
||||
void patronListLoaded();
|
||||
|
||||
private:
|
||||
Ui::AboutDialog *ui;
|
||||
Ui::AboutDialog *ui;
|
||||
|
||||
NetJobPtr netJob;
|
||||
QByteArray dataSink;
|
||||
NetJobPtr netJob;
|
||||
QByteArray dataSink;
|
||||
};
|
||||
|
@ -29,87 +29,87 @@
|
||||
#include "InstanceList.h"
|
||||
|
||||
CopyInstanceDialog::CopyInstanceDialog(InstancePtr original, QWidget *parent)
|
||||
:QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original)
|
||||
:QDialog(parent), ui(new Ui::CopyInstanceDialog), m_original(original)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
InstIconKey = original->iconKey();
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
ui->instNameTextBox->setText(original->name());
|
||||
ui->instNameTextBox->setFocus();
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(m_original->group());
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
ui->copySavesCheckbox->setChecked(m_copySaves);
|
||||
InstIconKey = original->iconKey();
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
ui->instNameTextBox->setText(original->name());
|
||||
ui->instNameTextBox->setFocus();
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(m_original->group());
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
ui->copySavesCheckbox->setChecked(m_copySaves);
|
||||
}
|
||||
|
||||
CopyInstanceDialog::~CopyInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::updateDialogState()
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!instName().isEmpty());
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::instName() const
|
||||
{
|
||||
return ui->instNameTextBox->text();
|
||||
return ui->instNameTextBox->text();
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::iconKey() const
|
||||
{
|
||||
return InstIconKey;
|
||||
return InstIconKey;
|
||||
}
|
||||
|
||||
QString CopyInstanceDialog::instGroup() const
|
||||
{
|
||||
return ui->groupBox->currentText();
|
||||
return ui->groupBox->currentText();
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.execWithSelection(InstIconKey);
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.execWithSelection(InstIconKey);
|
||||
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
}
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
}
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
|
||||
{
|
||||
updateDialogState();
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
bool CopyInstanceDialog::shouldCopySaves() const
|
||||
{
|
||||
return m_copySaves;
|
||||
return m_copySaves;
|
||||
}
|
||||
|
||||
void CopyInstanceDialog::on_copySavesCheckbox_stateChanged(int state)
|
||||
{
|
||||
if(state == Qt::Unchecked)
|
||||
{
|
||||
m_copySaves = false;
|
||||
}
|
||||
else if(state == Qt::Checked)
|
||||
{
|
||||
m_copySaves = true;
|
||||
}
|
||||
if(state == Qt::Unchecked)
|
||||
{
|
||||
m_copySaves = false;
|
||||
}
|
||||
else if(state == Qt::Checked)
|
||||
{
|
||||
m_copySaves = true;
|
||||
}
|
||||
}
|
||||
|
@ -28,28 +28,28 @@ class CopyInstanceDialog;
|
||||
|
||||
class CopyInstanceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CopyInstanceDialog(InstancePtr original, QWidget *parent = 0);
|
||||
~CopyInstanceDialog();
|
||||
explicit CopyInstanceDialog(InstancePtr original, QWidget *parent = 0);
|
||||
~CopyInstanceDialog();
|
||||
|
||||
void updateDialogState();
|
||||
void updateDialogState();
|
||||
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
bool shouldCopySaves() const;
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
bool shouldCopySaves() const;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_iconButton_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
void on_copySavesCheckbox_stateChanged(int state);
|
||||
void on_iconButton_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
void on_copySavesCheckbox_stateChanged(int state);
|
||||
|
||||
private:
|
||||
Ui::CopyInstanceDialog *ui;
|
||||
QString InstIconKey;
|
||||
InstancePtr m_original;
|
||||
bool m_copySaves = true;
|
||||
Ui::CopyInstanceDialog *ui;
|
||||
QString InstIconKey;
|
||||
InstancePtr m_original;
|
||||
bool m_copySaves = true;
|
||||
};
|
||||
|
@ -18,18 +18,18 @@
|
||||
namespace CustomMessageBox
|
||||
{
|
||||
QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::Icon icon, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
QMessageBox::Icon icon, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
QMessageBox *messageBox = new QMessageBox(parent);
|
||||
messageBox->setWindowTitle(title);
|
||||
messageBox->setText(text);
|
||||
messageBox->setStandardButtons(buttons);
|
||||
messageBox->setDefaultButton(defaultButton);
|
||||
messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
messageBox->setIcon(icon);
|
||||
messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
QMessageBox *messageBox = new QMessageBox(parent);
|
||||
messageBox->setWindowTitle(title);
|
||||
messageBox->setText(text);
|
||||
messageBox->setStandardButtons(buttons);
|
||||
messageBox->setDefaultButton(defaultButton);
|
||||
messageBox->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
messageBox->setIcon(icon);
|
||||
messageBox->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
|
||||
return messageBox;
|
||||
return messageBox;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
namespace CustomMessageBox
|
||||
{
|
||||
QMessageBox *selectable(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::Icon icon = QMessageBox::NoIcon,
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::Icon icon = QMessageBox::NoIcon,
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
}
|
||||
|
@ -19,43 +19,43 @@
|
||||
#include <QUrl>
|
||||
|
||||
EditAccountDialog::EditAccountDialog(const QString &text, QWidget *parent, int flags)
|
||||
: QDialog(parent), ui(new Ui::EditAccountDialog)
|
||||
: QDialog(parent), ui(new Ui::EditAccountDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->label->setText(text);
|
||||
ui->label->setVisible(!text.isEmpty());
|
||||
ui->label->setText(text);
|
||||
ui->label->setVisible(!text.isEmpty());
|
||||
|
||||
ui->userTextBox->setEnabled(flags & UsernameField);
|
||||
ui->passTextBox->setEnabled(flags & PasswordField);
|
||||
ui->userTextBox->setEnabled(flags & UsernameField);
|
||||
ui->passTextBox->setEnabled(flags & PasswordField);
|
||||
}
|
||||
|
||||
EditAccountDialog::~EditAccountDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditAccountDialog::on_label_linkActivated(const QString &link)
|
||||
{
|
||||
DesktopServices::openUrl(QUrl(link));
|
||||
DesktopServices::openUrl(QUrl(link));
|
||||
}
|
||||
|
||||
void EditAccountDialog::setUsername(const QString & user) const
|
||||
{
|
||||
ui->userTextBox->setText(user);
|
||||
ui->userTextBox->setText(user);
|
||||
}
|
||||
|
||||
QString EditAccountDialog::username() const
|
||||
{
|
||||
return ui->userTextBox->text();
|
||||
return ui->userTextBox->text();
|
||||
}
|
||||
|
||||
void EditAccountDialog::setPassword(const QString & pass) const
|
||||
{
|
||||
ui->passTextBox->setText(pass);
|
||||
ui->passTextBox->setText(pass);
|
||||
}
|
||||
|
||||
QString EditAccountDialog::password() const
|
||||
{
|
||||
return ui->passTextBox->text();
|
||||
return ui->passTextBox->text();
|
||||
}
|
||||
|
@ -24,33 +24,33 @@ class EditAccountDialog;
|
||||
|
||||
class EditAccountDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0,
|
||||
int flags = UsernameField | PasswordField);
|
||||
~EditAccountDialog();
|
||||
explicit EditAccountDialog(const QString &text = "", QWidget *parent = 0,
|
||||
int flags = UsernameField | PasswordField);
|
||||
~EditAccountDialog();
|
||||
|
||||
void setUsername(const QString & user) const;
|
||||
void setPassword(const QString & pass) const;
|
||||
void setUsername(const QString & user) const;
|
||||
void setPassword(const QString & pass) const;
|
||||
|
||||
QString username() const;
|
||||
QString password() const;
|
||||
QString username() const;
|
||||
QString password() const;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
NoFlags = 0,
|
||||
enum Flags
|
||||
{
|
||||
NoFlags = 0,
|
||||
|
||||
//! Specifies that the dialog should have a username field.
|
||||
UsernameField,
|
||||
//! Specifies that the dialog should have a username field.
|
||||
UsernameField,
|
||||
|
||||
//! Specifies that the dialog should have a password field.
|
||||
PasswordField,
|
||||
};
|
||||
//! Specifies that the dialog should have a password field.
|
||||
PasswordField,
|
||||
};
|
||||
|
||||
private slots:
|
||||
void on_label_linkActivated(const QString &link);
|
||||
|
||||
private:
|
||||
Ui::EditAccountDialog *ui;
|
||||
Ui::EditAccountDialog *ui;
|
||||
};
|
||||
|
@ -33,456 +33,456 @@
|
||||
|
||||
class PackIgnoreProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PackIgnoreProxy(InstancePtr instance, QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_instance = instance;
|
||||
}
|
||||
// NOTE: Sadly, we have to do sorting ourselves.
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
if (!fsm)
|
||||
{
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
bool asc = sortOrder() == Qt::AscendingOrder ? true : false;
|
||||
PackIgnoreProxy(InstancePtr instance, QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_instance = instance;
|
||||
}
|
||||
// NOTE: Sadly, we have to do sorting ourselves.
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
if (!fsm)
|
||||
{
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
bool asc = sortOrder() == Qt::AscendingOrder ? true : false;
|
||||
|
||||
QFileInfo leftFileInfo = fsm->fileInfo(left);
|
||||
QFileInfo rightFileInfo = fsm->fileInfo(right);
|
||||
QFileInfo leftFileInfo = fsm->fileInfo(left);
|
||||
QFileInfo rightFileInfo = fsm->fileInfo(right);
|
||||
|
||||
if (!leftFileInfo.isDir() && rightFileInfo.isDir())
|
||||
{
|
||||
return !asc;
|
||||
}
|
||||
if (leftFileInfo.isDir() && !rightFileInfo.isDir())
|
||||
{
|
||||
return asc;
|
||||
}
|
||||
if (!leftFileInfo.isDir() && rightFileInfo.isDir())
|
||||
{
|
||||
return !asc;
|
||||
}
|
||||
if (leftFileInfo.isDir() && !rightFileInfo.isDir())
|
||||
{
|
||||
return asc;
|
||||
}
|
||||
|
||||
// sort and proxy model breaks the original model...
|
||||
if (sortColumn() == 0)
|
||||
{
|
||||
return Strings::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
if (sortColumn() == 1)
|
||||
{
|
||||
auto leftSize = leftFileInfo.size();
|
||||
auto rightSize = rightFileInfo.size();
|
||||
if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir()))
|
||||
{
|
||||
return Strings::naturalCompare(leftFileInfo.fileName(),
|
||||
rightFileInfo.fileName(),
|
||||
Qt::CaseInsensitive) < 0
|
||||
? asc
|
||||
: !asc;
|
||||
}
|
||||
return leftSize < rightSize;
|
||||
}
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
// sort and proxy model breaks the original model...
|
||||
if (sortColumn() == 0)
|
||||
{
|
||||
return Strings::naturalCompare(leftFileInfo.fileName(), rightFileInfo.fileName(),
|
||||
Qt::CaseInsensitive) < 0;
|
||||
}
|
||||
if (sortColumn() == 1)
|
||||
{
|
||||
auto leftSize = leftFileInfo.size();
|
||||
auto rightSize = rightFileInfo.size();
|
||||
if ((leftSize == rightSize) || (leftFileInfo.isDir() && rightFileInfo.isDir()))
|
||||
{
|
||||
return Strings::naturalCompare(leftFileInfo.fileName(),
|
||||
rightFileInfo.fileName(),
|
||||
Qt::CaseInsensitive) < 0
|
||||
? asc
|
||||
: !asc;
|
||||
}
|
||||
return leftSize < rightSize;
|
||||
}
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
auto sourceIndex = mapToSource(index);
|
||||
Qt::ItemFlags flags = sourceIndex.flags();
|
||||
if (index.column() == 0)
|
||||
{
|
||||
flags |= Qt::ItemIsUserCheckable;
|
||||
if (sourceIndex.model()->hasChildren(sourceIndex))
|
||||
{
|
||||
flags |= Qt::ItemIsTristate;
|
||||
}
|
||||
}
|
||||
auto sourceIndex = mapToSource(index);
|
||||
Qt::ItemFlags flags = sourceIndex.flags();
|
||||
if (index.column() == 0)
|
||||
{
|
||||
flags |= Qt::ItemIsUserCheckable;
|
||||
if (sourceIndex.model()->hasChildren(sourceIndex))
|
||||
{
|
||||
flags |= Qt::ItemIsTristate;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole)
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
if (!cover.isNull())
|
||||
{
|
||||
return QVariant(Qt::Unchecked);
|
||||
}
|
||||
else if (blocked.exists(blockedPath))
|
||||
{
|
||||
return QVariant(Qt::PartiallyChecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant(Qt::Checked);
|
||||
}
|
||||
}
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole)
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
if (!cover.isNull())
|
||||
{
|
||||
return QVariant(Qt::Unchecked);
|
||||
}
|
||||
else if (blocked.exists(blockedPath))
|
||||
{
|
||||
return QVariant(Qt::PartiallyChecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QVariant(Qt::Checked);
|
||||
}
|
||||
}
|
||||
|
||||
return sourceIndex.data(role);
|
||||
}
|
||||
return sourceIndex.data(role);
|
||||
}
|
||||
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole)
|
||||
{
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole)
|
||||
{
|
||||
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
|
||||
return setFilterState(index, state);
|
||||
}
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role = Qt::EditRole)
|
||||
{
|
||||
if (index.column() == 0 && role == Qt::CheckStateRole)
|
||||
{
|
||||
Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
|
||||
return setFilterState(index, state);
|
||||
}
|
||||
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role);
|
||||
}
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
return QSortFilterProxyModel::sourceModel()->setData(sourceIndex, value, role);
|
||||
}
|
||||
|
||||
QString relPath(const QString &path) const
|
||||
{
|
||||
QString prefix = QDir().absoluteFilePath(m_instance->instanceRoot());
|
||||
prefix += '/';
|
||||
if (!path.startsWith(prefix))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
return path.mid(prefix.size());
|
||||
}
|
||||
QString relPath(const QString &path) const
|
||||
{
|
||||
QString prefix = QDir().absoluteFilePath(m_instance->instanceRoot());
|
||||
prefix += '/';
|
||||
if (!path.startsWith(prefix))
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
return path.mid(prefix.size());
|
||||
}
|
||||
|
||||
bool setFilterState(QModelIndex index, Qt::CheckState state)
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
bool setFilterState(QModelIndex index, Qt::CheckState state)
|
||||
{
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
|
||||
if (!fsm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!fsm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
bool changed = false;
|
||||
if (state == Qt::Unchecked)
|
||||
{
|
||||
// blocking a path
|
||||
auto &node = blocked.insert(blockedPath);
|
||||
// get rid of all blocked nodes below
|
||||
node.clear();
|
||||
changed = true;
|
||||
}
|
||||
else if (state == Qt::Checked || state == Qt::PartiallyChecked)
|
||||
{
|
||||
if (!blocked.remove(blockedPath))
|
||||
{
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
qDebug() << "Blocked by cover" << cover;
|
||||
// uncover
|
||||
blocked.remove(cover);
|
||||
// block all contents, except for any cover
|
||||
QModelIndex rootIndex =
|
||||
fsm->index(FS::PathCombine(m_instance->instanceRoot(), cover));
|
||||
QModelIndex doing = rootIndex;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
while (1)
|
||||
{
|
||||
auto node = doing.child(row, 0);
|
||||
if (!node.isValid())
|
||||
{
|
||||
if (!todo.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing = todo.pop();
|
||||
row = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto relpath = relPath(fsm->filePath(node));
|
||||
if (blockedPath.startsWith(relpath)) // cover found?
|
||||
{
|
||||
// continue processing cover later
|
||||
todo.push(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// or just block this one.
|
||||
blocked.insert(relpath);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
// update the thing
|
||||
emit dataChanged(index, index, {Qt::CheckStateRole});
|
||||
// update everything above index
|
||||
QModelIndex up = index.parent();
|
||||
while (1)
|
||||
{
|
||||
if (!up.isValid())
|
||||
break;
|
||||
emit dataChanged(up, up, {Qt::CheckStateRole});
|
||||
up = up.parent();
|
||||
}
|
||||
// and everything below the index
|
||||
QModelIndex doing = index;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
while (1)
|
||||
{
|
||||
auto node = doing.child(row, 0);
|
||||
if (!node.isValid())
|
||||
{
|
||||
if (!todo.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing = todo.pop();
|
||||
row = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
emit dataChanged(node, node, {Qt::CheckStateRole});
|
||||
todo.push(node);
|
||||
row++;
|
||||
}
|
||||
// siblings and unrelated nodes are ignored
|
||||
}
|
||||
return true;
|
||||
}
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
bool changed = false;
|
||||
if (state == Qt::Unchecked)
|
||||
{
|
||||
// blocking a path
|
||||
auto &node = blocked.insert(blockedPath);
|
||||
// get rid of all blocked nodes below
|
||||
node.clear();
|
||||
changed = true;
|
||||
}
|
||||
else if (state == Qt::Checked || state == Qt::PartiallyChecked)
|
||||
{
|
||||
if (!blocked.remove(blockedPath))
|
||||
{
|
||||
auto cover = blocked.cover(blockedPath);
|
||||
qDebug() << "Blocked by cover" << cover;
|
||||
// uncover
|
||||
blocked.remove(cover);
|
||||
// block all contents, except for any cover
|
||||
QModelIndex rootIndex =
|
||||
fsm->index(FS::PathCombine(m_instance->instanceRoot(), cover));
|
||||
QModelIndex doing = rootIndex;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
while (1)
|
||||
{
|
||||
auto node = doing.child(row, 0);
|
||||
if (!node.isValid())
|
||||
{
|
||||
if (!todo.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing = todo.pop();
|
||||
row = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto relpath = relPath(fsm->filePath(node));
|
||||
if (blockedPath.startsWith(relpath)) // cover found?
|
||||
{
|
||||
// continue processing cover later
|
||||
todo.push(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// or just block this one.
|
||||
blocked.insert(relpath);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
// update the thing
|
||||
emit dataChanged(index, index, {Qt::CheckStateRole});
|
||||
// update everything above index
|
||||
QModelIndex up = index.parent();
|
||||
while (1)
|
||||
{
|
||||
if (!up.isValid())
|
||||
break;
|
||||
emit dataChanged(up, up, {Qt::CheckStateRole});
|
||||
up = up.parent();
|
||||
}
|
||||
// and everything below the index
|
||||
QModelIndex doing = index;
|
||||
int row = 0;
|
||||
QStack<QModelIndex> todo;
|
||||
while (1)
|
||||
{
|
||||
auto node = doing.child(row, 0);
|
||||
if (!node.isValid())
|
||||
{
|
||||
if (!todo.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
doing = todo.pop();
|
||||
row = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
emit dataChanged(node, node, {Qt::CheckStateRole});
|
||||
todo.push(node);
|
||||
row++;
|
||||
}
|
||||
// siblings and unrelated nodes are ignored
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shouldExpand(QModelIndex index)
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
if (!fsm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto found = blocked.find(blockedPath);
|
||||
if(found)
|
||||
{
|
||||
return !found->leaf();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool shouldExpand(QModelIndex index)
|
||||
{
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
QFileSystemModel *fsm = qobject_cast<QFileSystemModel *>(sourceModel());
|
||||
if (!fsm)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto blockedPath = relPath(fsm->filePath(sourceIndex));
|
||||
auto found = blocked.find(blockedPath);
|
||||
if(found)
|
||||
{
|
||||
return !found->leaf();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setBlockedPaths(QStringList paths)
|
||||
{
|
||||
beginResetModel();
|
||||
blocked.clear();
|
||||
blocked.insert(paths);
|
||||
endResetModel();
|
||||
}
|
||||
void setBlockedPaths(QStringList paths)
|
||||
{
|
||||
beginResetModel();
|
||||
blocked.clear();
|
||||
blocked.insert(paths);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
const SeparatorPrefixTree<'/'> & blockedPaths() const
|
||||
{
|
||||
return blocked;
|
||||
}
|
||||
const SeparatorPrefixTree<'/'> & blockedPaths() const
|
||||
{
|
||||
return blocked;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent)
|
||||
bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent)
|
||||
|
||||
// adjust the columns you want to filter out here
|
||||
// return false for those that will be hidden
|
||||
if (source_column == 2 || source_column == 3)
|
||||
return false;
|
||||
// adjust the columns you want to filter out here
|
||||
// return false for those that will be hidden
|
||||
if (source_column == 2 || source_column == 3)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InstancePtr m_instance;
|
||||
SeparatorPrefixTree<'/'> blocked;
|
||||
InstancePtr m_instance;
|
||||
SeparatorPrefixTree<'/'> blocked;
|
||||
};
|
||||
|
||||
ExportInstanceDialog::ExportInstanceDialog(InstancePtr instance, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance)
|
||||
: QDialog(parent), ui(new Ui::ExportInstanceDialog), m_instance(instance)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
auto model = new QFileSystemModel(this);
|
||||
proxyModel = new PackIgnoreProxy(m_instance, this);
|
||||
loadPackIgnore();
|
||||
proxyModel->setSourceModel(model);
|
||||
auto root = instance->instanceRoot();
|
||||
ui->treeView->setModel(proxyModel);
|
||||
ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root)));
|
||||
ui->treeView->sortByColumn(0, Qt::AscendingOrder);
|
||||
ui->setupUi(this);
|
||||
auto model = new QFileSystemModel(this);
|
||||
proxyModel = new PackIgnoreProxy(m_instance, this);
|
||||
loadPackIgnore();
|
||||
proxyModel->setSourceModel(model);
|
||||
auto root = instance->instanceRoot();
|
||||
ui->treeView->setModel(proxyModel);
|
||||
ui->treeView->setRootIndex(proxyModel->mapFromSource(model->index(root)));
|
||||
ui->treeView->sortByColumn(0, Qt::AscendingOrder);
|
||||
|
||||
connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int)));
|
||||
connect(proxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int)));
|
||||
|
||||
model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden);
|
||||
model->setRootPath(root);
|
||||
auto headerView = ui->treeView->header();
|
||||
headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
model->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Hidden);
|
||||
model->setRootPath(root);
|
||||
auto headerView = ui->treeView->header();
|
||||
headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
headerView->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
ExportInstanceDialog::~ExportInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
/// Save icon to instance's folder is needed
|
||||
void SaveIcon(InstancePtr m_instance)
|
||||
{
|
||||
auto iconKey = m_instance->iconKey();
|
||||
auto iconList = MMC->icons();
|
||||
auto mmcIcon = iconList->icon(iconKey);
|
||||
if(mmcIcon)
|
||||
{
|
||||
bool saveIcon = false;
|
||||
switch(mmcIcon->type())
|
||||
{
|
||||
case IconType::FileBased:
|
||||
case IconType::Transient:
|
||||
saveIcon = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(saveIcon)
|
||||
{
|
||||
auto & image = mmcIcon->m_images[mmcIcon->type()];
|
||||
auto & icon = image.icon;
|
||||
auto sizes = icon.availableSizes();
|
||||
if(sizes.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto areaOf = [](QSize size)
|
||||
{
|
||||
return size.width() * size.height();
|
||||
};
|
||||
QSize largest = sizes[0];
|
||||
// find variant with largest area
|
||||
for(auto size: sizes)
|
||||
{
|
||||
if(areaOf(largest) < areaOf(size))
|
||||
{
|
||||
largest = size;
|
||||
}
|
||||
}
|
||||
auto pixmap = icon.pixmap(largest);
|
||||
pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png"));
|
||||
}
|
||||
}
|
||||
auto iconKey = m_instance->iconKey();
|
||||
auto iconList = MMC->icons();
|
||||
auto mmcIcon = iconList->icon(iconKey);
|
||||
if(mmcIcon)
|
||||
{
|
||||
bool saveIcon = false;
|
||||
switch(mmcIcon->type())
|
||||
{
|
||||
case IconType::FileBased:
|
||||
case IconType::Transient:
|
||||
saveIcon = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(saveIcon)
|
||||
{
|
||||
auto & image = mmcIcon->m_images[mmcIcon->type()];
|
||||
auto & icon = image.icon;
|
||||
auto sizes = icon.availableSizes();
|
||||
if(sizes.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto areaOf = [](QSize size)
|
||||
{
|
||||
return size.width() * size.height();
|
||||
};
|
||||
QSize largest = sizes[0];
|
||||
// find variant with largest area
|
||||
for(auto size: sizes)
|
||||
{
|
||||
if(areaOf(largest) < areaOf(size))
|
||||
{
|
||||
largest = size;
|
||||
}
|
||||
}
|
||||
auto pixmap = icon.pixmap(largest);
|
||||
pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExportInstanceDialog::doExport()
|
||||
{
|
||||
auto name = FS::RemoveInvalidFilenameChars(m_instance->name());
|
||||
auto name = FS::RemoveInvalidFilenameChars(m_instance->name());
|
||||
|
||||
const QString output = QFileDialog::getSaveFileName(
|
||||
this, tr("Export %1").arg(m_instance->name()),
|
||||
FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr, QFileDialog::DontConfirmOverwrite);
|
||||
if (output.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (QFile::exists(output))
|
||||
{
|
||||
int ret =
|
||||
QMessageBox::question(this, tr("Overwrite?"),
|
||||
tr("This file already exists. Do you want to overwrite it?"),
|
||||
QMessageBox::No, QMessageBox::Yes);
|
||||
if (ret == QMessageBox::No)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const QString output = QFileDialog::getSaveFileName(
|
||||
this, tr("Export %1").arg(m_instance->name()),
|
||||
FS::PathCombine(QDir::homePath(), name + ".zip"), "Zip (*.zip)", nullptr, QFileDialog::DontConfirmOverwrite);
|
||||
if (output.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (QFile::exists(output))
|
||||
{
|
||||
int ret =
|
||||
QMessageBox::question(this, tr("Overwrite?"),
|
||||
tr("This file already exists. Do you want to overwrite it?"),
|
||||
QMessageBox::No, QMessageBox::Yes);
|
||||
if (ret == QMessageBox::No)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SaveIcon(m_instance);
|
||||
SaveIcon(m_instance);
|
||||
|
||||
auto & blocked = proxyModel->blockedPaths();
|
||||
using std::placeholders::_1;
|
||||
if (!JlCompress::compressDir(output, m_instance->instanceRoot(), name, std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1)))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Unable to export instance"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
auto & blocked = proxyModel->blockedPaths();
|
||||
using std::placeholders::_1;
|
||||
if (!JlCompress::compressDir(output, m_instance->instanceRoot(), name, std::bind(&SeparatorPrefixTree<'/'>::covers, blocked, _1)))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Error"), tr("Unable to export instance"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::done(int result)
|
||||
{
|
||||
savePackIgnore();
|
||||
if (result == QDialog::Accepted)
|
||||
{
|
||||
if (doExport())
|
||||
{
|
||||
QDialog::done(QDialog::Accepted);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
QDialog::done(result);
|
||||
savePackIgnore();
|
||||
if (result == QDialog::Accepted)
|
||||
{
|
||||
if (doExport())
|
||||
{
|
||||
QDialog::done(QDialog::Accepted);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
QDialog::done(result);
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::rowsInserted(QModelIndex parent, int top, int bottom)
|
||||
{
|
||||
//WARNING: possible off-by-one?
|
||||
for(int i = top; i < bottom; i++)
|
||||
{
|
||||
auto node = parent.child(i, 0);
|
||||
if(proxyModel->shouldExpand(node))
|
||||
{
|
||||
auto expNode = node.parent();
|
||||
if(!expNode.isValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ui->treeView->expand(node);
|
||||
}
|
||||
}
|
||||
//WARNING: possible off-by-one?
|
||||
for(int i = top; i < bottom; i++)
|
||||
{
|
||||
auto node = parent.child(i, 0);
|
||||
if(proxyModel->shouldExpand(node))
|
||||
{
|
||||
auto expNode = node.parent();
|
||||
if(!expNode.isValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ui->treeView->expand(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString ExportInstanceDialog::ignoreFileName()
|
||||
{
|
||||
return FS::PathCombine(m_instance->instanceRoot(), ".packignore");
|
||||
return FS::PathCombine(m_instance->instanceRoot(), ".packignore");
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::loadPackIgnore()
|
||||
{
|
||||
auto filename = ignoreFileName();
|
||||
QFile ignoreFile(filename);
|
||||
if(!ignoreFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto data = ignoreFile.readAll();
|
||||
auto string = QString::fromUtf8(data);
|
||||
proxyModel->setBlockedPaths(string.split('\n', QString::SkipEmptyParts));
|
||||
auto filename = ignoreFileName();
|
||||
QFile ignoreFile(filename);
|
||||
if(!ignoreFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto data = ignoreFile.readAll();
|
||||
auto string = QString::fromUtf8(data);
|
||||
proxyModel->setBlockedPaths(string.split('\n', QString::SkipEmptyParts));
|
||||
}
|
||||
|
||||
void ExportInstanceDialog::savePackIgnore()
|
||||
{
|
||||
auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8();
|
||||
auto filename = ignoreFileName();
|
||||
try
|
||||
{
|
||||
FS::write(filename, data);
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qWarning() << e.cause();
|
||||
}
|
||||
auto data = proxyModel->blockedPaths().toStringList().join('\n').toUtf8();
|
||||
auto filename = ignoreFileName();
|
||||
try
|
||||
{
|
||||
FS::write(filename, data);
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
qWarning() << e.cause();
|
||||
}
|
||||
}
|
||||
|
||||
#include "ExportInstanceDialog.moc"
|
||||
|
@ -30,25 +30,25 @@ class ExportInstanceDialog;
|
||||
|
||||
class ExportInstanceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExportInstanceDialog(InstancePtr instance, QWidget *parent = 0);
|
||||
~ExportInstanceDialog();
|
||||
explicit ExportInstanceDialog(InstancePtr instance, QWidget *parent = 0);
|
||||
~ExportInstanceDialog();
|
||||
|
||||
virtual void done(int result);
|
||||
virtual void done(int result);
|
||||
|
||||
private:
|
||||
bool doExport();
|
||||
void loadPackIgnore();
|
||||
void savePackIgnore();
|
||||
QString ignoreFileName();
|
||||
bool doExport();
|
||||
void loadPackIgnore();
|
||||
void savePackIgnore();
|
||||
QString ignoreFileName();
|
||||
|
||||
private:
|
||||
Ui::ExportInstanceDialog *ui;
|
||||
InstancePtr m_instance;
|
||||
PackIgnoreProxy * proxyModel;
|
||||
Ui::ExportInstanceDialog *ui;
|
||||
InstancePtr m_instance;
|
||||
PackIgnoreProxy * proxyModel;
|
||||
|
||||
private slots:
|
||||
void rowsInserted(QModelIndex parent, int top, int bottom);
|
||||
void rowsInserted(QModelIndex parent, int top, int bottom);
|
||||
};
|
||||
|
@ -28,135 +28,135 @@
|
||||
#include <DesktopServices.h>
|
||||
|
||||
IconPickerDialog::IconPickerDialog(QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::IconPickerDialog)
|
||||
: QDialog(parent), ui(new Ui::IconPickerDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
ui->setupUi(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->setViewMode(QListView::IconMode);
|
||||
contentsWidget->setFlow(QListView::LeftToRight);
|
||||
contentsWidget->setIconSize(QSize(48, 48));
|
||||
contentsWidget->setMovement(QListView::Static);
|
||||
contentsWidget->setResizeMode(QListView::Adjust);
|
||||
contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
contentsWidget->setSpacing(5);
|
||||
contentsWidget->setWordWrap(false);
|
||||
contentsWidget->setWrapping(true);
|
||||
contentsWidget->setUniformItemSizes(true);
|
||||
contentsWidget->setTextElideMode(Qt::ElideRight);
|
||||
contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
contentsWidget->setItemDelegate(new ListViewDelegate());
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->setViewMode(QListView::IconMode);
|
||||
contentsWidget->setFlow(QListView::LeftToRight);
|
||||
contentsWidget->setIconSize(QSize(48, 48));
|
||||
contentsWidget->setMovement(QListView::Static);
|
||||
contentsWidget->setResizeMode(QListView::Adjust);
|
||||
contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
contentsWidget->setSpacing(5);
|
||||
contentsWidget->setWordWrap(false);
|
||||
contentsWidget->setWrapping(true);
|
||||
contentsWidget->setUniformItemSizes(true);
|
||||
contentsWidget->setTextElideMode(Qt::ElideRight);
|
||||
contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
contentsWidget->setItemDelegate(new ListViewDelegate());
|
||||
|
||||
// contentsWidget->setAcceptDrops(true);
|
||||
contentsWidget->setDropIndicatorShown(true);
|
||||
contentsWidget->viewport()->setAcceptDrops(true);
|
||||
contentsWidget->setDragDropMode(QAbstractItemView::DropOnly);
|
||||
contentsWidget->setDefaultDropAction(Qt::CopyAction);
|
||||
// contentsWidget->setAcceptDrops(true);
|
||||
contentsWidget->setDropIndicatorShown(true);
|
||||
contentsWidget->viewport()->setAcceptDrops(true);
|
||||
contentsWidget->setDragDropMode(QAbstractItemView::DropOnly);
|
||||
contentsWidget->setDefaultDropAction(Qt::CopyAction);
|
||||
|
||||
contentsWidget->installEventFilter(this);
|
||||
contentsWidget->installEventFilter(this);
|
||||
|
||||
contentsWidget->setModel(MMC->icons().get());
|
||||
contentsWidget->setModel(MMC->icons().get());
|
||||
|
||||
// NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win.
|
||||
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole);
|
||||
auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole);
|
||||
// NOTE: ResetRole forces the button to be on the left, while the OK/Cancel ones are on the right. We win.
|
||||
auto buttonAdd = ui->buttonBox->addButton(tr("Add Icon"), QDialogButtonBox::ResetRole);
|
||||
auto buttonRemove = ui->buttonBox->addButton(tr("Remove Icon"), QDialogButtonBox::ResetRole);
|
||||
|
||||
connect(buttonAdd, SIGNAL(clicked(bool)), SLOT(addNewIcon()));
|
||||
connect(buttonRemove, SIGNAL(clicked(bool)), SLOT(removeSelectedIcon()));
|
||||
connect(buttonAdd, SIGNAL(clicked(bool)), SLOT(addNewIcon()));
|
||||
connect(buttonRemove, SIGNAL(clicked(bool)), SLOT(removeSelectedIcon()));
|
||||
|
||||
connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex)));
|
||||
connect(contentsWidget, SIGNAL(doubleClicked(QModelIndex)), SLOT(activated(QModelIndex)));
|
||||
|
||||
connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection)));
|
||||
connect(contentsWidget->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(selectionChanged(QItemSelection, QItemSelection)));
|
||||
|
||||
auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole);
|
||||
connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder);
|
||||
auto buttonFolder = ui->buttonBox->addButton(tr("Open Folder"), QDialogButtonBox::ResetRole);
|
||||
connect(buttonFolder, &QPushButton::clicked, this, &IconPickerDialog::openFolder);
|
||||
}
|
||||
|
||||
bool IconPickerDialog::eventFilter(QObject *obj, QEvent *evt)
|
||||
{
|
||||
if (obj != ui->iconView)
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
if (evt->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
removeSelectedIcon();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
addNewIcon();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
if (obj != ui->iconView)
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
if (evt->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(evt);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
removeSelectedIcon();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
addNewIcon();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QDialog::eventFilter(obj, evt);
|
||||
}
|
||||
|
||||
void IconPickerDialog::addNewIcon()
|
||||
{
|
||||
//: The title of the select icons open file dialog
|
||||
QString selectIcons = tr("Select Icons");
|
||||
//: The type of icon files
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(),
|
||||
tr("Icons") + "(*.png *.jpg *.jpeg *.ico *.svg)");
|
||||
MMC->icons()->installIcons(fileNames);
|
||||
//: The title of the select icons open file dialog
|
||||
QString selectIcons = tr("Select Icons");
|
||||
//: The type of icon files
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(),
|
||||
tr("Icons") + "(*.png *.jpg *.jpeg *.ico *.svg)");
|
||||
MMC->icons()->installIcons(fileNames);
|
||||
}
|
||||
|
||||
void IconPickerDialog::removeSelectedIcon()
|
||||
{
|
||||
MMC->icons()->deleteIcon(selectedIconKey);
|
||||
MMC->icons()->deleteIcon(selectedIconKey);
|
||||
}
|
||||
|
||||
void IconPickerDialog::activated(QModelIndex index)
|
||||
{
|
||||
selectedIconKey = index.data(Qt::UserRole).toString();
|
||||
accept();
|
||||
selectedIconKey = index.data(Qt::UserRole).toString();
|
||||
accept();
|
||||
}
|
||||
|
||||
void IconPickerDialog::selectionChanged(QItemSelection selected, QItemSelection deselected)
|
||||
{
|
||||
if (selected.empty())
|
||||
return;
|
||||
if (selected.empty())
|
||||
return;
|
||||
|
||||
QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
|
||||
if (!key.isEmpty())
|
||||
selectedIconKey = key;
|
||||
QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
|
||||
if (!key.isEmpty())
|
||||
selectedIconKey = key;
|
||||
}
|
||||
|
||||
int IconPickerDialog::execWithSelection(QString selection)
|
||||
{
|
||||
auto list = MMC->icons();
|
||||
auto contentsWidget = ui->iconView;
|
||||
selectedIconKey = selection;
|
||||
auto list = MMC->icons();
|
||||
auto contentsWidget = ui->iconView;
|
||||
selectedIconKey = selection;
|
||||
|
||||
int index_nr = list->getIconIndex(selection);
|
||||
auto model_index = list->index(index_nr);
|
||||
contentsWidget->selectionModel()->select(
|
||||
model_index, QItemSelectionModel::Current | QItemSelectionModel::Select);
|
||||
int index_nr = list->getIconIndex(selection);
|
||||
auto model_index = list->index(index_nr);
|
||||
contentsWidget->selectionModel()->select(
|
||||
model_index, QItemSelectionModel::Current | QItemSelectionModel::Select);
|
||||
|
||||
QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection,
|
||||
Q_ARG(QModelIndex, model_index));
|
||||
return QDialog::exec();
|
||||
QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection,
|
||||
Q_ARG(QModelIndex, model_index));
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void IconPickerDialog::delayed_scroll(QModelIndex model_index)
|
||||
{
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->scrollTo(model_index);
|
||||
auto contentsWidget = ui->iconView;
|
||||
contentsWidget->scrollTo(model_index);
|
||||
}
|
||||
|
||||
IconPickerDialog::~IconPickerDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void IconPickerDialog::openFolder()
|
||||
{
|
||||
DesktopServices::openDirectory(MMC->icons()->getDirectory(), true);
|
||||
DesktopServices::openDirectory(MMC->icons()->getDirectory(), true);
|
||||
}
|
||||
|
@ -24,26 +24,26 @@ class IconPickerDialog;
|
||||
|
||||
class IconPickerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit IconPickerDialog(QWidget *parent = 0);
|
||||
~IconPickerDialog();
|
||||
int execWithSelection(QString selection);
|
||||
QString selectedIconKey;
|
||||
explicit IconPickerDialog(QWidget *parent = 0);
|
||||
~IconPickerDialog();
|
||||
int execWithSelection(QString selection);
|
||||
QString selectedIconKey;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *, QEvent *);
|
||||
virtual bool eventFilter(QObject *, QEvent *);
|
||||
|
||||
private:
|
||||
Ui::IconPickerDialog *ui;
|
||||
Ui::IconPickerDialog *ui;
|
||||
|
||||
private
|
||||
slots:
|
||||
void selectionChanged(QItemSelection, QItemSelection);
|
||||
void activated(QModelIndex);
|
||||
void delayed_scroll(QModelIndex);
|
||||
void addNewIcon();
|
||||
void removeSelectedIcon();
|
||||
void openFolder();
|
||||
void selectionChanged(QItemSelection, QItemSelection);
|
||||
void activated(QModelIndex);
|
||||
void delayed_scroll(QModelIndex);
|
||||
void addNewIcon();
|
||||
void removeSelectedIcon();
|
||||
void openFolder();
|
||||
};
|
||||
|
@ -22,89 +22,89 @@
|
||||
|
||||
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui->setupUi(this);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
LoginDialog::~LoginDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Stage 1: User interaction
|
||||
void LoginDialog::accept()
|
||||
{
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
|
||||
// Setup the login task and start it
|
||||
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
|
||||
m_loginTask = m_account->login(nullptr, ui->passTextBox->text());
|
||||
connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &Task::succeeded, this,
|
||||
&LoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
// Setup the login task and start it
|
||||
m_account = MojangAccount::createFromUsername(ui->userTextBox->text());
|
||||
m_loginTask = m_account->login(nullptr, ui->passTextBox->text());
|
||||
connect(m_loginTask.get(), &Task::failed, this, &LoginDialog::onTaskFailed);
|
||||
connect(m_loginTask.get(), &Task::succeeded, this,
|
||||
&LoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &Task::status, this, &LoginDialog::onTaskStatus);
|
||||
connect(m_loginTask.get(), &Task::progress, this, &LoginDialog::onTaskProgress);
|
||||
m_loginTask->start();
|
||||
}
|
||||
|
||||
void LoginDialog::setUserInputsEnabled(bool enable)
|
||||
{
|
||||
ui->userTextBox->setEnabled(enable);
|
||||
ui->passTextBox->setEnabled(enable);
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
ui->userTextBox->setEnabled(enable);
|
||||
ui->passTextBox->setEnabled(enable);
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
// Enable the OK button only when both textboxes contain something.
|
||||
void LoginDialog::on_userTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->passTextBox->text().isEmpty());
|
||||
}
|
||||
void LoginDialog::on_passTextBox_textEdited(const QString &newText)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setEnabled(!newText.isEmpty() && !ui->userTextBox->text().isEmpty());
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskFailed(const QString &reason)
|
||||
{
|
||||
// Set message
|
||||
ui->label->setText("<span style='color:red'>" + reason + "</span>");
|
||||
// Set message
|
||||
ui->label->setText("<span style='color:red'>" + reason + "</span>");
|
||||
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskSucceeded()
|
||||
{
|
||||
QDialog::accept();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskStatus(const QString &status)
|
||||
{
|
||||
ui->label->setText(status);
|
||||
ui->label->setText(status);
|
||||
}
|
||||
|
||||
void LoginDialog::onTaskProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
MojangAccountPtr LoginDialog::newAccount(QWidget *parent, QString msg)
|
||||
{
|
||||
LoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
return dlg.m_account;
|
||||
}
|
||||
return 0;
|
||||
LoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
return dlg.m_account;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,32 +27,32 @@ class LoginDialog;
|
||||
|
||||
class LoginDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~LoginDialog();
|
||||
~LoginDialog();
|
||||
|
||||
static MojangAccountPtr newAccount(QWidget *parent, QString message);
|
||||
static MojangAccountPtr newAccount(QWidget *parent, QString message);
|
||||
|
||||
private:
|
||||
explicit LoginDialog(QWidget *parent = 0);
|
||||
explicit LoginDialog(QWidget *parent = 0);
|
||||
|
||||
void setUserInputsEnabled(bool enable);
|
||||
void setUserInputsEnabled(bool enable);
|
||||
|
||||
protected
|
||||
slots:
|
||||
void accept();
|
||||
void accept();
|
||||
|
||||
void onTaskFailed(const QString &reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString &status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
void onTaskFailed(const QString &reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString &status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
|
||||
void on_userTextBox_textEdited(const QString &newText);
|
||||
void on_passTextBox_textEdited(const QString &newText);
|
||||
void on_userTextBox_textEdited(const QString &newText);
|
||||
void on_passTextBox_textEdited(const QString &newText);
|
||||
|
||||
private:
|
||||
Ui::LoginDialog *ui;
|
||||
MojangAccountPtr m_account;
|
||||
std::shared_ptr<Task> m_loginTask;
|
||||
Ui::LoginDialog *ui;
|
||||
MojangAccountPtr m_account;
|
||||
std::shared_ptr<Task> m_loginTask;
|
||||
};
|
||||
|
@ -4,37 +4,37 @@
|
||||
|
||||
bool lastfirst(QModelIndexList &list, int &first, int &last)
|
||||
{
|
||||
if (list.isEmpty())
|
||||
return false;
|
||||
first = last = list[0].row();
|
||||
for (auto item : list)
|
||||
{
|
||||
int row = item.row();
|
||||
if (row < first)
|
||||
first = row;
|
||||
if (row > last)
|
||||
last = row;
|
||||
}
|
||||
return true;
|
||||
if (list.isEmpty())
|
||||
return false;
|
||||
first = last = list[0].row();
|
||||
for (auto item : list)
|
||||
{
|
||||
int row = item.row();
|
||||
if (row < first)
|
||||
first = row;
|
||||
if (row > last)
|
||||
last = row;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void showWebsiteForMod(QWidget *parentDlg, Mod &m)
|
||||
{
|
||||
QString url = m.homeurl();
|
||||
if (url.size())
|
||||
{
|
||||
// catch the cases where the protocol is missing
|
||||
if (!url.startsWith("http"))
|
||||
{
|
||||
url = "http://" + url;
|
||||
}
|
||||
DesktopServices::openUrl(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentDlg, QObject::tr("How sad!"),
|
||||
QObject::tr("The mod author didn't provide a website link for this mod."),
|
||||
QMessageBox::Warning);
|
||||
}
|
||||
QString url = m.homeurl();
|
||||
if (url.size())
|
||||
{
|
||||
// catch the cases where the protocol is missing
|
||||
if (!url.startsWith("http"))
|
||||
{
|
||||
url = "http://" + url;
|
||||
}
|
||||
DesktopServices::openUrl(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
parentDlg, QObject::tr("How sad!"),
|
||||
QObject::tr("The mod author didn't provide a website link for this mod."),
|
||||
QMessageBox::Warning);
|
||||
}
|
||||
}
|
||||
|
@ -35,72 +35,72 @@
|
||||
#include <meta/VersionList.h>
|
||||
|
||||
NewComponentDialog::NewComponentDialog(const QString & initialName, const QString & initialUid, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::NewComponentDialog)
|
||||
: QDialog(parent), ui(new Ui::NewComponentDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
ui->setupUi(this);
|
||||
resize(minimumSizeHint());
|
||||
|
||||
ui->nameTextBox->setText(initialName);
|
||||
ui->uidTextBox->setText(initialUid);
|
||||
ui->nameTextBox->setText(initialName);
|
||||
ui->uidTextBox->setText(initialUid);
|
||||
|
||||
connect(ui->nameTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
|
||||
connect(ui->uidTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
|
||||
connect(ui->nameTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
|
||||
connect(ui->uidTextBox, &QLineEdit::textChanged, this, &NewComponentDialog::updateDialogState);
|
||||
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
ui->nameTextBox->setFocus();
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
ui->nameTextBox->setFocus();
|
||||
|
||||
originalPlaceholderText = ui->uidTextBox->placeholderText();
|
||||
updateDialogState();
|
||||
originalPlaceholderText = ui->uidTextBox->placeholderText();
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
NewComponentDialog::~NewComponentDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewComponentDialog::updateDialogState()
|
||||
{
|
||||
auto protoUid = ui->nameTextBox->text().toLower();
|
||||
protoUid.remove(QRegularExpression("[^a-z]"));
|
||||
if(protoUid.isEmpty())
|
||||
{
|
||||
ui->uidTextBox->setPlaceholderText(originalPlaceholderText);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString suggestedUid = "org.multimc.custom." + protoUid;
|
||||
ui->uidTextBox->setPlaceholderText(suggestedUid);
|
||||
}
|
||||
bool allowOK = !name().isEmpty() && !uid().isEmpty() && !uidBlacklist.contains(uid());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
auto protoUid = ui->nameTextBox->text().toLower();
|
||||
protoUid.remove(QRegularExpression("[^a-z]"));
|
||||
if(protoUid.isEmpty())
|
||||
{
|
||||
ui->uidTextBox->setPlaceholderText(originalPlaceholderText);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString suggestedUid = "org.multimc.custom." + protoUid;
|
||||
ui->uidTextBox->setPlaceholderText(suggestedUid);
|
||||
}
|
||||
bool allowOK = !name().isEmpty() && !uid().isEmpty() && !uidBlacklist.contains(uid());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
}
|
||||
|
||||
QString NewComponentDialog::name() const
|
||||
{
|
||||
auto result = ui->nameTextBox->text();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
return QString();
|
||||
auto result = ui->nameTextBox->text();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString NewComponentDialog::uid() const
|
||||
{
|
||||
auto result = ui->uidTextBox->text();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
result = ui->uidTextBox->placeholderText();
|
||||
if(result.size() && result != originalPlaceholderText)
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
return QString();
|
||||
auto result = ui->uidTextBox->text();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
result = ui->uidTextBox->placeholderText();
|
||||
if(result.size() && result != originalPlaceholderText)
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void NewComponentDialog::setBlacklist(QStringList badUids)
|
||||
{
|
||||
uidBlacklist = badUids;
|
||||
uidBlacklist = badUids;
|
||||
}
|
||||
|
@ -27,22 +27,22 @@ class NewComponentDialog;
|
||||
|
||||
class NewComponentDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewComponentDialog(const QString & initialName = QString(), const QString & initialUid = QString(), QWidget *parent = 0);
|
||||
virtual ~NewComponentDialog();
|
||||
void setBlacklist(QStringList badUids);
|
||||
explicit NewComponentDialog(const QString & initialName = QString(), const QString & initialUid = QString(), QWidget *parent = 0);
|
||||
virtual ~NewComponentDialog();
|
||||
void setBlacklist(QStringList badUids);
|
||||
|
||||
QString name() const;
|
||||
QString uid() const;
|
||||
QString name() const;
|
||||
QString uid() const;
|
||||
|
||||
private slots:
|
||||
void updateDialogState();
|
||||
void updateDialogState();
|
||||
|
||||
private:
|
||||
Ui::NewComponentDialog *ui;
|
||||
Ui::NewComponentDialog *ui;
|
||||
|
||||
QString originalPlaceholderText;
|
||||
QStringList uidBlacklist;
|
||||
QString originalPlaceholderText;
|
||||
QStringList uidBlacklist;
|
||||
};
|
||||
|
@ -40,178 +40,178 @@
|
||||
#include <pages/modplatform/TechnicPage.h>
|
||||
|
||||
NewInstanceDialog::NewInstanceDialog(const QString & initialGroup, const QString & url, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::NewInstanceDialog)
|
||||
: QDialog(parent), ui(new Ui::NewInstanceDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowIcon(MMC->getThemedIcon("new"));
|
||||
setWindowIcon(MMC->getThemedIcon("new"));
|
||||
|
||||
InstIconKey = "default";
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
InstIconKey = "default";
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
groupList.push_front(initialGroup);
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(initialGroup);
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
auto groups = MMC->instances()->getGroups().toSet();
|
||||
auto groupList = QStringList(groups.toList());
|
||||
groupList.sort(Qt::CaseInsensitive);
|
||||
groupList.removeOne("");
|
||||
groupList.push_front(initialGroup);
|
||||
groupList.push_front("");
|
||||
ui->groupBox->addItems(groupList);
|
||||
int index = groupList.indexOf(initialGroup);
|
||||
if(index == -1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
ui->groupBox->setCurrentIndex(index);
|
||||
ui->groupBox->lineEdit()->setPlaceholderText(tr("No group"));
|
||||
|
||||
m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
m_buttons->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
m_buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
m_buttons->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
|
||||
|
||||
m_container = new PageContainer(this);
|
||||
m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
|
||||
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
||||
ui->verticalLayout->insertWidget(2, m_container);
|
||||
m_container = new PageContainer(this);
|
||||
m_container->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
|
||||
m_container->layout()->setContentsMargins(0, 0, 0, 0);
|
||||
ui->verticalLayout->insertWidget(2, m_container);
|
||||
|
||||
m_container->addButtons(m_buttons);
|
||||
m_buttons->setFocus();
|
||||
m_container->addButtons(m_buttons);
|
||||
m_buttons->setFocus();
|
||||
|
||||
if(!url.isEmpty())
|
||||
{
|
||||
m_container->selectPage("import");
|
||||
importPage->setUrl(url);
|
||||
}
|
||||
if(!url.isEmpty())
|
||||
{
|
||||
m_container->selectPage("import");
|
||||
importPage->setUrl(url);
|
||||
}
|
||||
|
||||
connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &NewInstanceDialog::accept);
|
||||
connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &NewInstanceDialog::reject);
|
||||
connect(m_buttons->button(QDialogButtonBox::Help), &QPushButton::clicked, m_container, &PageContainer::help);
|
||||
connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &NewInstanceDialog::accept);
|
||||
connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &NewInstanceDialog::reject);
|
||||
connect(m_buttons->button(QDialogButtonBox::Help), &QPushButton::clicked, m_container, &PageContainer::help);
|
||||
|
||||
updateDialogState();
|
||||
updateDialogState();
|
||||
|
||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("NewInstanceGeometry").toByteArray()));
|
||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("NewInstanceGeometry").toByteArray()));
|
||||
|
||||
}
|
||||
|
||||
void NewInstanceDialog::reject()
|
||||
{
|
||||
MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
|
||||
QDialog::reject();
|
||||
MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void NewInstanceDialog::accept()
|
||||
{
|
||||
MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
|
||||
importIconNow();
|
||||
QDialog::accept();
|
||||
MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
|
||||
importIconNow();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
QList<BasePage *> NewInstanceDialog::getPages()
|
||||
{
|
||||
importPage = new ImportPage(this);
|
||||
return
|
||||
{
|
||||
new VanillaPage(this),
|
||||
new FTBPage(this),
|
||||
importPage,
|
||||
new TwitchPage(this),
|
||||
new TechnicPage(this)
|
||||
};
|
||||
importPage = new ImportPage(this);
|
||||
return
|
||||
{
|
||||
new VanillaPage(this),
|
||||
new FTBPage(this),
|
||||
importPage,
|
||||
new TwitchPage(this),
|
||||
new TechnicPage(this)
|
||||
};
|
||||
}
|
||||
|
||||
QString NewInstanceDialog::dialogTitle()
|
||||
{
|
||||
return tr("New Instance");
|
||||
return tr("New Instance");
|
||||
}
|
||||
|
||||
NewInstanceDialog::~NewInstanceDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::setSuggestedPack(const QString& name, InstanceTask* task)
|
||||
{
|
||||
creationTask.reset(task);
|
||||
ui->instNameTextBox->setPlaceholderText(name);
|
||||
creationTask.reset(task);
|
||||
ui->instNameTextBox->setPlaceholderText(name);
|
||||
|
||||
auto allowOK = task && !instName().isEmpty();
|
||||
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
auto allowOK = task && !instName().isEmpty();
|
||||
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
}
|
||||
|
||||
void NewInstanceDialog::setSuggestedIconFromFile(const QString &path, const QString &name)
|
||||
{
|
||||
importIcon = true;
|
||||
importIconPath = path;
|
||||
importIconName = name;
|
||||
importIcon = true;
|
||||
importIconPath = path;
|
||||
importIconName = name;
|
||||
|
||||
//Hmm, for some reason they can be to small
|
||||
ui->iconButton->setIcon(QIcon(path));
|
||||
//Hmm, for some reason they can be to small
|
||||
ui->iconButton->setIcon(QIcon(path));
|
||||
}
|
||||
|
||||
InstanceTask * NewInstanceDialog::extractTask()
|
||||
{
|
||||
InstanceTask * extracted = creationTask.get();
|
||||
creationTask.release();
|
||||
extracted->setName(instName());
|
||||
extracted->setGroup(instGroup());
|
||||
extracted->setIcon(iconKey());
|
||||
return extracted;
|
||||
InstanceTask * extracted = creationTask.get();
|
||||
creationTask.release();
|
||||
extracted->setName(instName());
|
||||
extracted->setGroup(instGroup());
|
||||
extracted->setIcon(iconKey());
|
||||
return extracted;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::updateDialogState()
|
||||
{
|
||||
auto allowOK = creationTask && !instName().isEmpty();
|
||||
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
auto allowOK = creationTask && !instName().isEmpty();
|
||||
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(allowOK);
|
||||
}
|
||||
|
||||
QString NewInstanceDialog::instName() const
|
||||
{
|
||||
auto result = ui->instNameTextBox->text();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
result = ui->instNameTextBox->placeholderText();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
return QString();
|
||||
auto result = ui->instNameTextBox->text();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
result = ui->instNameTextBox->placeholderText();
|
||||
if(result.size())
|
||||
{
|
||||
return result.trimmed();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString NewInstanceDialog::instGroup() const
|
||||
{
|
||||
return ui->groupBox->currentText();
|
||||
return ui->groupBox->currentText();
|
||||
}
|
||||
QString NewInstanceDialog::iconKey() const
|
||||
{
|
||||
return InstIconKey;
|
||||
return InstIconKey;
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_iconButton_clicked()
|
||||
{
|
||||
importIconNow(); //so the user can switch back
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.execWithSelection(InstIconKey);
|
||||
importIconNow(); //so the user can switch back
|
||||
IconPickerDialog dlg(this);
|
||||
dlg.execWithSelection(InstIconKey);
|
||||
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
importIcon = false;
|
||||
}
|
||||
if (dlg.result() == QDialog::Accepted)
|
||||
{
|
||||
InstIconKey = dlg.selectedIconKey;
|
||||
ui->iconButton->setIcon(MMC->icons()->getIcon(InstIconKey));
|
||||
importIcon = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
|
||||
{
|
||||
updateDialogState();
|
||||
updateDialogState();
|
||||
}
|
||||
|
||||
void NewInstanceDialog::importIconNow()
|
||||
{
|
||||
if(importIcon) {
|
||||
MMC->icons()->installIcon(importIconPath, importIconName);
|
||||
InstIconKey = importIconName;
|
||||
importIcon = false;
|
||||
}
|
||||
MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
|
||||
if(importIcon) {
|
||||
MMC->icons()->installIcon(importIconPath, importIconName);
|
||||
InstIconKey = importIconName;
|
||||
importIcon = false;
|
||||
}
|
||||
MMC->settings()->set("NewInstanceGeometry", saveGeometry().toBase64());
|
||||
}
|
||||
|
@ -32,46 +32,46 @@ class ImportPage;
|
||||
|
||||
class NewInstanceDialog : public QDialog, public BasePageProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewInstanceDialog(const QString & initialGroup, const QString & url = QString(), QWidget *parent = 0);
|
||||
~NewInstanceDialog();
|
||||
explicit NewInstanceDialog(const QString & initialGroup, const QString & url = QString(), QWidget *parent = 0);
|
||||
~NewInstanceDialog();
|
||||
|
||||
void updateDialogState();
|
||||
void updateDialogState();
|
||||
|
||||
void setSuggestedPack(const QString & name = QString(), InstanceTask * task = nullptr);
|
||||
void setSuggestedIconFromFile(const QString &path, const QString &name);
|
||||
void setSuggestedPack(const QString & name = QString(), InstanceTask * task = nullptr);
|
||||
void setSuggestedIconFromFile(const QString &path, const QString &name);
|
||||
|
||||
InstanceTask * extractTask();
|
||||
InstanceTask * extractTask();
|
||||
|
||||
QString dialogTitle() override;
|
||||
QList<BasePage *> getPages() override;
|
||||
QString dialogTitle() override;
|
||||
QList<BasePage *> getPages() override;
|
||||
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
QString instName() const;
|
||||
QString instGroup() const;
|
||||
QString iconKey() const;
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
void accept() override;
|
||||
void reject() override;
|
||||
|
||||
private slots:
|
||||
void on_iconButton_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
void on_iconButton_clicked();
|
||||
void on_instNameTextBox_textChanged(const QString &arg1);
|
||||
|
||||
private:
|
||||
Ui::NewInstanceDialog *ui = nullptr;
|
||||
PageContainer * m_container = nullptr;
|
||||
QDialogButtonBox * m_buttons = nullptr;
|
||||
Ui::NewInstanceDialog *ui = nullptr;
|
||||
PageContainer * m_container = nullptr;
|
||||
QDialogButtonBox * m_buttons = nullptr;
|
||||
|
||||
QString InstIconKey;
|
||||
ImportPage *importPage = nullptr;
|
||||
std::unique_ptr<InstanceTask> creationTask;
|
||||
QString InstIconKey;
|
||||
ImportPage *importPage = nullptr;
|
||||
std::unique_ptr<InstanceTask> creationTask;
|
||||
|
||||
bool importIcon = false;
|
||||
QString importIconPath;
|
||||
QString importIconName;
|
||||
bool importIcon = false;
|
||||
QString importIconPath;
|
||||
QString importIconName;
|
||||
|
||||
void importIconNow();
|
||||
void importIconNow();
|
||||
};
|
||||
|
@ -5,82 +5,82 @@
|
||||
#include <QStyle>
|
||||
|
||||
NotificationDialog::NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent) :
|
||||
QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint),
|
||||
ui(new Ui::NotificationDialog)
|
||||
QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::CustomizeWindowHint),
|
||||
ui(new Ui::NotificationDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
QStyle::StandardPixmap icon;
|
||||
switch (entry.type)
|
||||
{
|
||||
case NotificationChecker::NotificationEntry::Critical:
|
||||
icon = QStyle::SP_MessageBoxCritical;
|
||||
break;
|
||||
case NotificationChecker::NotificationEntry::Warning:
|
||||
icon = QStyle::SP_MessageBoxWarning;
|
||||
break;
|
||||
default:
|
||||
case NotificationChecker::NotificationEntry::Information:
|
||||
icon = QStyle::SP_MessageBoxInformation;
|
||||
break;
|
||||
}
|
||||
ui->iconLabel->setPixmap(style()->standardPixmap(icon, 0, this));
|
||||
ui->messageLabel->setText(entry.message);
|
||||
QStyle::StandardPixmap icon;
|
||||
switch (entry.type)
|
||||
{
|
||||
case NotificationChecker::NotificationEntry::Critical:
|
||||
icon = QStyle::SP_MessageBoxCritical;
|
||||
break;
|
||||
case NotificationChecker::NotificationEntry::Warning:
|
||||
icon = QStyle::SP_MessageBoxWarning;
|
||||
break;
|
||||
default:
|
||||
case NotificationChecker::NotificationEntry::Information:
|
||||
icon = QStyle::SP_MessageBoxInformation;
|
||||
break;
|
||||
}
|
||||
ui->iconLabel->setPixmap(style()->standardPixmap(icon, 0, this));
|
||||
ui->messageLabel->setText(entry.message);
|
||||
|
||||
m_dontShowAgainText = tr("Don't show again");
|
||||
m_closeText = tr("Close");
|
||||
m_dontShowAgainText = tr("Don't show again");
|
||||
m_closeText = tr("Close");
|
||||
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime));
|
||||
ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime));
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime));
|
||||
ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime));
|
||||
|
||||
startTimer(1000);
|
||||
startTimer(1000);
|
||||
}
|
||||
|
||||
NotificationDialog::~NotificationDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NotificationDialog::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (m_dontShowAgainTime > 0)
|
||||
{
|
||||
m_dontShowAgainTime--;
|
||||
if (m_dontShowAgainTime == 0)
|
||||
{
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText);
|
||||
ui->dontShowAgainBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime));
|
||||
}
|
||||
}
|
||||
if (m_closeTime > 0)
|
||||
{
|
||||
m_closeTime--;
|
||||
if (m_closeTime == 0)
|
||||
{
|
||||
ui->closeBtn->setText(m_closeText);
|
||||
ui->closeBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime));
|
||||
}
|
||||
}
|
||||
if (m_dontShowAgainTime > 0)
|
||||
{
|
||||
m_dontShowAgainTime--;
|
||||
if (m_dontShowAgainTime == 0)
|
||||
{
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText);
|
||||
ui->dontShowAgainBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->dontShowAgainBtn->setText(m_dontShowAgainText + QString(" (%1)").arg(m_dontShowAgainTime));
|
||||
}
|
||||
}
|
||||
if (m_closeTime > 0)
|
||||
{
|
||||
m_closeTime--;
|
||||
if (m_closeTime == 0)
|
||||
{
|
||||
ui->closeBtn->setText(m_closeText);
|
||||
ui->closeBtn->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->closeBtn->setText(m_closeText + QString(" (%1)").arg(m_closeTime));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_closeTime == 0 && m_dontShowAgainTime == 0)
|
||||
{
|
||||
killTimer(event->timerId());
|
||||
}
|
||||
if (m_closeTime == 0 && m_dontShowAgainTime == 0)
|
||||
{
|
||||
killTimer(event->timerId());
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationDialog::on_dontShowAgainBtn_clicked()
|
||||
{
|
||||
done(DontShowAgain);
|
||||
done(DontShowAgain);
|
||||
}
|
||||
void NotificationDialog::on_closeBtn_clicked()
|
||||
{
|
||||
done(Normal);
|
||||
done(Normal);
|
||||
}
|
||||
|
@ -11,34 +11,34 @@ class NotificationDialog;
|
||||
|
||||
class NotificationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent = 0);
|
||||
~NotificationDialog();
|
||||
explicit NotificationDialog(const NotificationChecker::NotificationEntry &entry, QWidget *parent = 0);
|
||||
~NotificationDialog();
|
||||
|
||||
enum ExitCode
|
||||
{
|
||||
Normal,
|
||||
DontShowAgain
|
||||
};
|
||||
enum ExitCode
|
||||
{
|
||||
Normal,
|
||||
DontShowAgain
|
||||
};
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
Ui::NotificationDialog *ui;
|
||||
Ui::NotificationDialog *ui;
|
||||
|
||||
int m_dontShowAgainTime = 10;
|
||||
int m_closeTime = 5;
|
||||
int m_dontShowAgainTime = 10;
|
||||
int m_closeTime = 5;
|
||||
|
||||
QString m_dontShowAgainText;
|
||||
QString m_closeText;
|
||||
QString m_dontShowAgainText;
|
||||
QString m_closeText;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_dontShowAgainBtn_clicked();
|
||||
void on_closeBtn_clicked();
|
||||
void on_dontShowAgainBtn_clicked();
|
||||
void on_closeBtn_clicked();
|
||||
};
|
||||
|
||||
#endif // NOTIFICATIONDIALOG_H
|
||||
|
@ -26,91 +26,91 @@
|
||||
#include <MultiMC.h>
|
||||
|
||||
ProfileSelectDialog::ProfileSelectDialog(const QString &message, int flags, QWidget *parent)
|
||||
: QDialog(parent), ui(new Ui::ProfileSelectDialog)
|
||||
: QDialog(parent), ui(new Ui::ProfileSelectDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
m_accounts = MMC->accounts();
|
||||
auto view = ui->listView;
|
||||
//view->setModel(m_accounts.get());
|
||||
//view->hideColumn(MojangAccountList::ActiveColumn);
|
||||
view->setColumnCount(1);
|
||||
view->setRootIsDecorated(false);
|
||||
if(QTreeWidgetItem* header = view->headerItem())
|
||||
{
|
||||
header->setText(0, tr("Name"));
|
||||
}
|
||||
else
|
||||
{
|
||||
view->setHeaderLabel(tr("Name"));
|
||||
}
|
||||
QList <QTreeWidgetItem *> items;
|
||||
for (int i = 0; i < m_accounts->count(); i++)
|
||||
{
|
||||
MojangAccountPtr account = m_accounts->at(i);
|
||||
for (auto profile : account->profiles())
|
||||
{
|
||||
auto profileLabel = profile.name;
|
||||
if(account->isInUse())
|
||||
{
|
||||
profileLabel += tr(" (in use)");
|
||||
}
|
||||
auto item = new QTreeWidgetItem(view);
|
||||
item->setText(0, profileLabel);
|
||||
item->setIcon(0, SkinUtils::getFaceFromCache(profile.id));
|
||||
item->setData(0, MojangAccountList::PointerRole, QVariant::fromValue(account));
|
||||
items.append(item);
|
||||
}
|
||||
}
|
||||
view->addTopLevelItems(items);
|
||||
m_accounts = MMC->accounts();
|
||||
auto view = ui->listView;
|
||||
//view->setModel(m_accounts.get());
|
||||
//view->hideColumn(MojangAccountList::ActiveColumn);
|
||||
view->setColumnCount(1);
|
||||
view->setRootIsDecorated(false);
|
||||
if(QTreeWidgetItem* header = view->headerItem())
|
||||
{
|
||||
header->setText(0, tr("Name"));
|
||||
}
|
||||
else
|
||||
{
|
||||
view->setHeaderLabel(tr("Name"));
|
||||
}
|
||||
QList <QTreeWidgetItem *> items;
|
||||
for (int i = 0; i < m_accounts->count(); i++)
|
||||
{
|
||||
MojangAccountPtr account = m_accounts->at(i);
|
||||
for (auto profile : account->profiles())
|
||||
{
|
||||
auto profileLabel = profile.name;
|
||||
if(account->isInUse())
|
||||
{
|
||||
profileLabel += tr(" (in use)");
|
||||
}
|
||||
auto item = new QTreeWidgetItem(view);
|
||||
item->setText(0, profileLabel);
|
||||
item->setIcon(0, SkinUtils::getFaceFromCache(profile.id));
|
||||
item->setData(0, MojangAccountList::PointerRole, QVariant::fromValue(account));
|
||||
items.append(item);
|
||||
}
|
||||
}
|
||||
view->addTopLevelItems(items);
|
||||
|
||||
// Set the message label.
|
||||
ui->msgLabel->setVisible(!message.isEmpty());
|
||||
ui->msgLabel->setText(message);
|
||||
// Set the message label.
|
||||
ui->msgLabel->setVisible(!message.isEmpty());
|
||||
ui->msgLabel->setText(message);
|
||||
|
||||
// Flags...
|
||||
ui->globalDefaultCheck->setVisible(flags & GlobalDefaultCheckbox);
|
||||
ui->instDefaultCheck->setVisible(flags & InstanceDefaultCheckbox);
|
||||
qDebug() << flags;
|
||||
// Flags...
|
||||
ui->globalDefaultCheck->setVisible(flags & GlobalDefaultCheckbox);
|
||||
ui->instDefaultCheck->setVisible(flags & InstanceDefaultCheckbox);
|
||||
qDebug() << flags;
|
||||
|
||||
// Select the first entry in the list.
|
||||
ui->listView->setCurrentIndex(ui->listView->model()->index(0, 0));
|
||||
// Select the first entry in the list.
|
||||
ui->listView->setCurrentIndex(ui->listView->model()->index(0, 0));
|
||||
|
||||
connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_buttonBox_accepted()));
|
||||
connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(on_buttonBox_accepted()));
|
||||
}
|
||||
|
||||
ProfileSelectDialog::~ProfileSelectDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
MojangAccountPtr ProfileSelectDialog::selectedAccount() const
|
||||
{
|
||||
return m_selected;
|
||||
return m_selected;
|
||||
}
|
||||
|
||||
bool ProfileSelectDialog::useAsGlobalDefault() const
|
||||
{
|
||||
return ui->globalDefaultCheck->isChecked();
|
||||
return ui->globalDefaultCheck->isChecked();
|
||||
}
|
||||
|
||||
bool ProfileSelectDialog::useAsInstDefaullt() const
|
||||
{
|
||||
return ui->instDefaultCheck->isChecked();
|
||||
return ui->instDefaultCheck->isChecked();
|
||||
}
|
||||
|
||||
void ProfileSelectDialog::on_buttonBox_accepted()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
m_selected = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
}
|
||||
close();
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
m_selected = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
void ProfileSelectDialog::on_buttonBox_rejected()
|
||||
{
|
||||
close();
|
||||
close();
|
||||
}
|
||||
|
@ -28,63 +28,63 @@ class ProfileSelectDialog;
|
||||
|
||||
class ProfileSelectDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
NoFlags = 0,
|
||||
enum Flags
|
||||
{
|
||||
NoFlags = 0,
|
||||
|
||||
/*!
|
||||
* Shows a check box on the dialog that allows the user to specify that the account
|
||||
* they've selected should be used as the global default for all instances.
|
||||
*/
|
||||
GlobalDefaultCheckbox,
|
||||
/*!
|
||||
* Shows a check box on the dialog that allows the user to specify that the account
|
||||
* they've selected should be used as the global default for all instances.
|
||||
*/
|
||||
GlobalDefaultCheckbox,
|
||||
|
||||
/*!
|
||||
* Shows a check box on the dialog that allows the user to specify that the account
|
||||
* they've selected should be used as the default for the instance they are currently launching.
|
||||
* This is not currently implemented.
|
||||
*/
|
||||
InstanceDefaultCheckbox,
|
||||
};
|
||||
/*!
|
||||
* Shows a check box on the dialog that allows the user to specify that the account
|
||||
* they've selected should be used as the default for the instance they are currently launching.
|
||||
* This is not currently implemented.
|
||||
*/
|
||||
InstanceDefaultCheckbox,
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constructs a new account select dialog with the given parent and message.
|
||||
* The message will be shown at the top of the dialog. It is an empty string by default.
|
||||
*/
|
||||
explicit ProfileSelectDialog(const QString& message="", int flags=0, QWidget *parent = 0);
|
||||
~ProfileSelectDialog();
|
||||
/*!
|
||||
* Constructs a new account select dialog with the given parent and message.
|
||||
* The message will be shown at the top of the dialog. It is an empty string by default.
|
||||
*/
|
||||
explicit ProfileSelectDialog(const QString& message="", int flags=0, QWidget *parent = 0);
|
||||
~ProfileSelectDialog();
|
||||
|
||||
/*!
|
||||
* Gets a pointer to the account that the user selected.
|
||||
* This is null if the user clicked cancel or hasn't clicked OK yet.
|
||||
*/
|
||||
MojangAccountPtr selectedAccount() const;
|
||||
/*!
|
||||
* Gets a pointer to the account that the user selected.
|
||||
* This is null if the user clicked cancel or hasn't clicked OK yet.
|
||||
*/
|
||||
MojangAccountPtr selectedAccount() const;
|
||||
|
||||
/*!
|
||||
* Returns true if the user checked the "use as global default" checkbox.
|
||||
* If the checkbox wasn't shown, this function returns false.
|
||||
*/
|
||||
bool useAsGlobalDefault() const;
|
||||
/*!
|
||||
* Returns true if the user checked the "use as global default" checkbox.
|
||||
* If the checkbox wasn't shown, this function returns false.
|
||||
*/
|
||||
bool useAsGlobalDefault() const;
|
||||
|
||||
/*!
|
||||
* Returns true if the user checked the "use as instance default" checkbox.
|
||||
* If the checkbox wasn't shown, this function returns false.
|
||||
*/
|
||||
bool useAsInstDefaullt() const;
|
||||
/*!
|
||||
* Returns true if the user checked the "use as instance default" checkbox.
|
||||
* If the checkbox wasn't shown, this function returns false.
|
||||
*/
|
||||
bool useAsInstDefaullt() const;
|
||||
|
||||
public
|
||||
slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_buttonBox_rejected();
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
|
||||
//! The account that was selected when the user clicked OK.
|
||||
MojangAccountPtr m_selected;
|
||||
//! The account that was selected when the user clicked OK.
|
||||
MojangAccountPtr m_selected;
|
||||
|
||||
private:
|
||||
Ui::ProfileSelectDialog *ui;
|
||||
Ui::ProfileSelectDialog *ui;
|
||||
};
|
||||
|
@ -23,117 +23,117 @@
|
||||
|
||||
ProgressDialog::ProgressDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ProgressDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setSkipButton(false);
|
||||
changeProgress(0, 100);
|
||||
ui->setupUi(this);
|
||||
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setSkipButton(false);
|
||||
changeProgress(0, 100);
|
||||
}
|
||||
|
||||
void ProgressDialog::setSkipButton(bool present, QString label)
|
||||
{
|
||||
ui->skipButton->setAutoDefault(false);
|
||||
ui->skipButton->setDefault(false);
|
||||
ui->skipButton->setFocusPolicy(Qt::ClickFocus);
|
||||
ui->skipButton->setEnabled(present);
|
||||
ui->skipButton->setVisible(present);
|
||||
ui->skipButton->setText(label);
|
||||
updateSize();
|
||||
ui->skipButton->setAutoDefault(false);
|
||||
ui->skipButton->setDefault(false);
|
||||
ui->skipButton->setFocusPolicy(Qt::ClickFocus);
|
||||
ui->skipButton->setEnabled(present);
|
||||
ui->skipButton->setVisible(present);
|
||||
ui->skipButton->setText(label);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void ProgressDialog::on_skipButton_clicked(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked);
|
||||
task->abort();
|
||||
Q_UNUSED(checked);
|
||||
task->abort();
|
||||
}
|
||||
|
||||
ProgressDialog::~ProgressDialog()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ProgressDialog::updateSize()
|
||||
{
|
||||
QSize qSize = QSize(480, minimumSizeHint().height());
|
||||
resize(qSize);
|
||||
resize(qSize);
|
||||
setFixedSize(qSize);
|
||||
}
|
||||
|
||||
int ProgressDialog::execWithTask(Task *task)
|
||||
{
|
||||
this->task = task;
|
||||
QDialog::DialogCode result;
|
||||
this->task = task;
|
||||
QDialog::DialogCode result;
|
||||
|
||||
if(!task)
|
||||
{
|
||||
qDebug() << "Programmer error: progress dialog created with null task.";
|
||||
return Accepted;
|
||||
}
|
||||
if(!task)
|
||||
{
|
||||
qDebug() << "Programmer error: progress dialog created with null task.";
|
||||
return Accepted;
|
||||
}
|
||||
|
||||
if(handleImmediateResult(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if(handleImmediateResult(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// Connect signals.
|
||||
connect(task, SIGNAL(started()), SLOT(onTaskStarted()));
|
||||
connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString)));
|
||||
connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded()));
|
||||
connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString &)));
|
||||
connect(task, SIGNAL(progress(qint64, qint64)), SLOT(changeProgress(qint64, qint64)));
|
||||
// Connect signals.
|
||||
connect(task, SIGNAL(started()), SLOT(onTaskStarted()));
|
||||
connect(task, SIGNAL(failed(QString)), SLOT(onTaskFailed(QString)));
|
||||
connect(task, SIGNAL(succeeded()), SLOT(onTaskSucceeded()));
|
||||
connect(task, SIGNAL(status(QString)), SLOT(changeStatus(const QString &)));
|
||||
connect(task, SIGNAL(progress(qint64, qint64)), SLOT(changeProgress(qint64, qint64)));
|
||||
|
||||
// if this didn't connect to an already running task, invoke start
|
||||
if(!task->isRunning())
|
||||
{
|
||||
task->start();
|
||||
}
|
||||
if(task->isRunning())
|
||||
{
|
||||
changeProgress(task->getProgress(), task->getTotalProgress());
|
||||
changeStatus(task->getStatus());
|
||||
return QDialog::exec();
|
||||
}
|
||||
else if(handleImmediateResult(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QDialog::Rejected;
|
||||
}
|
||||
// if this didn't connect to an already running task, invoke start
|
||||
if(!task->isRunning())
|
||||
{
|
||||
task->start();
|
||||
}
|
||||
if(task->isRunning())
|
||||
{
|
||||
changeProgress(task->getProgress(), task->getTotalProgress());
|
||||
changeStatus(task->getStatus());
|
||||
return QDialog::exec();
|
||||
}
|
||||
else if(handleImmediateResult(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QDialog::Rejected;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: only provide the unique_ptr overloads
|
||||
int ProgressDialog::execWithTask(std::unique_ptr<Task> &&task)
|
||||
{
|
||||
connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater);
|
||||
return execWithTask(task.release());
|
||||
connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater);
|
||||
return execWithTask(task.release());
|
||||
}
|
||||
int ProgressDialog::execWithTask(std::unique_ptr<Task> &task)
|
||||
{
|
||||
connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater);
|
||||
return execWithTask(task.release());
|
||||
connect(this, &ProgressDialog::destroyed, task.get(), &Task::deleteLater);
|
||||
return execWithTask(task.release());
|
||||
}
|
||||
|
||||
bool ProgressDialog::handleImmediateResult(QDialog::DialogCode &result)
|
||||
{
|
||||
if(task->isFinished())
|
||||
{
|
||||
if(task->wasSuccessful())
|
||||
{
|
||||
result = QDialog::Accepted;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = QDialog::Rejected;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if(task->isFinished())
|
||||
{
|
||||
if(task->wasSuccessful())
|
||||
{
|
||||
result = QDialog::Accepted;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = QDialog::Rejected;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Task *ProgressDialog::getTask()
|
||||
{
|
||||
return task;
|
||||
return task;
|
||||
}
|
||||
|
||||
void ProgressDialog::onTaskStarted()
|
||||
@ -142,55 +142,55 @@ void ProgressDialog::onTaskStarted()
|
||||
|
||||
void ProgressDialog::onTaskFailed(QString failure)
|
||||
{
|
||||
reject();
|
||||
reject();
|
||||
}
|
||||
|
||||
void ProgressDialog::onTaskSucceeded()
|
||||
{
|
||||
accept();
|
||||
accept();
|
||||
}
|
||||
|
||||
void ProgressDialog::changeStatus(const QString &status)
|
||||
{
|
||||
ui->statusLabel->setText(status);
|
||||
updateSize();
|
||||
ui->statusLabel->setText(status);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
void ProgressDialog::changeProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->taskProgressBar->setMaximum(total);
|
||||
ui->taskProgressBar->setValue(current);
|
||||
ui->taskProgressBar->setMaximum(total);
|
||||
ui->taskProgressBar->setValue(current);
|
||||
}
|
||||
|
||||
void ProgressDialog::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if(ui->skipButton->isVisible())
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
on_skipButton_clicked(true);
|
||||
return;
|
||||
}
|
||||
else if(e->key() == Qt::Key_Tab)
|
||||
{
|
||||
ui->skipButton->setFocusPolicy(Qt::StrongFocus);
|
||||
ui->skipButton->setFocus();
|
||||
ui->skipButton->setAutoDefault(true);
|
||||
ui->skipButton->setDefault(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
QDialog::keyPressEvent(e);
|
||||
if(ui->skipButton->isVisible())
|
||||
{
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
on_skipButton_clicked(true);
|
||||
return;
|
||||
}
|
||||
else if(e->key() == Qt::Key_Tab)
|
||||
{
|
||||
ui->skipButton->setFocusPolicy(Qt::StrongFocus);
|
||||
ui->skipButton->setFocus();
|
||||
ui->skipButton->setAutoDefault(true);
|
||||
ui->skipButton->setDefault(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
QDialog::keyPressEvent(e);
|
||||
}
|
||||
|
||||
void ProgressDialog::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
if (task && task->isRunning())
|
||||
{
|
||||
e->ignore();
|
||||
}
|
||||
else
|
||||
{
|
||||
QDialog::closeEvent(e);
|
||||
}
|
||||
if (task && task->isRunning())
|
||||
{
|
||||
e->ignore();
|
||||
}
|
||||
else
|
||||
{
|
||||
QDialog::closeEvent(e);
|
||||
}
|
||||
}
|
||||
|
@ -27,45 +27,45 @@ class ProgressDialog;
|
||||
|
||||
class ProgressDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProgressDialog(QWidget *parent = 0);
|
||||
~ProgressDialog();
|
||||
explicit ProgressDialog(QWidget *parent = 0);
|
||||
~ProgressDialog();
|
||||
|
||||
void updateSize();
|
||||
void updateSize();
|
||||
|
||||
int execWithTask(Task *task);
|
||||
int execWithTask(std::unique_ptr<Task> &&task);
|
||||
int execWithTask(std::unique_ptr<Task> &task);
|
||||
int execWithTask(Task *task);
|
||||
int execWithTask(std::unique_ptr<Task> &&task);
|
||||
int execWithTask(std::unique_ptr<Task> &task);
|
||||
|
||||
void setSkipButton(bool present, QString label = QString());
|
||||
void setSkipButton(bool present, QString label = QString());
|
||||
|
||||
Task *getTask();
|
||||
Task *getTask();
|
||||
|
||||
public
|
||||
slots:
|
||||
void onTaskStarted();
|
||||
void onTaskFailed(QString failure);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStarted();
|
||||
void onTaskFailed(QString failure);
|
||||
void onTaskSucceeded();
|
||||
|
||||
void changeStatus(const QString &status);
|
||||
void changeProgress(qint64 current, qint64 total);
|
||||
void changeStatus(const QString &status);
|
||||
void changeProgress(qint64 current, qint64 total);
|
||||
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_skipButton_clicked(bool checked);
|
||||
void on_skipButton_clicked(bool checked);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
virtual void closeEvent(QCloseEvent *e);
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
virtual void closeEvent(QCloseEvent *e);
|
||||
|
||||
private:
|
||||
bool handleImmediateResult(QDialog::DialogCode &result);
|
||||
bool handleImmediateResult(QDialog::DialogCode &result);
|
||||
|
||||
private:
|
||||
Ui::ProgressDialog *ui;
|
||||
Ui::ProgressDialog *ui;
|
||||
|
||||
Task *task;
|
||||
Task *task;
|
||||
};
|
||||
|
@ -9,106 +9,106 @@
|
||||
|
||||
void SkinUploadDialog::on_buttonBox_rejected()
|
||||
{
|
||||
close();
|
||||
close();
|
||||
}
|
||||
|
||||
void SkinUploadDialog::on_buttonBox_accepted()
|
||||
{
|
||||
AuthSessionPtr session = std::make_shared<AuthSession>();
|
||||
auto login = m_acct->login(session);
|
||||
ProgressDialog prog(this);
|
||||
if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted)
|
||||
{
|
||||
//FIXME: recover with password prompt
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to login!"), QMessageBox::Warning)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
QString fileName;
|
||||
QString input = ui->skinPathTextBox->text();
|
||||
QRegExp urlPrefixMatcher("^([a-z]+)://.+$");
|
||||
bool isLocalFile = false;
|
||||
// it has an URL prefix -> it is an URL
|
||||
if(urlPrefixMatcher.exactMatch(input))
|
||||
{
|
||||
QUrl fileURL = input;
|
||||
if(fileURL.isValid())
|
||||
{
|
||||
// local?
|
||||
if(fileURL.isLocalFile())
|
||||
{
|
||||
isLocalFile = true;
|
||||
fileName = fileURL.toLocalFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
this,
|
||||
tr("Skin Upload"),
|
||||
tr("Using remote URLs for setting skins is not implemented yet."),
|
||||
QMessageBox::Warning
|
||||
)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
this,
|
||||
tr("Skin Upload"),
|
||||
tr("You cannot use an invalid URL for uploading skins."),
|
||||
QMessageBox::Warning
|
||||
)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just assume it's a path then
|
||||
isLocalFile = true;
|
||||
fileName = ui->skinPathTextBox->text();
|
||||
}
|
||||
if (isLocalFile && !QFile::exists(fileName))
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Skin file does not exist!"), QMessageBox::Warning)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
SkinUpload::Model model = SkinUpload::STEVE;
|
||||
if (ui->steveBtn->isChecked())
|
||||
{
|
||||
model = SkinUpload::STEVE;
|
||||
}
|
||||
else if (ui->alexBtn->isChecked())
|
||||
{
|
||||
model = SkinUpload::ALEX;
|
||||
}
|
||||
SkinUploadPtr upload = std::make_shared<SkinUpload>(this, session, FS::read(fileName), model);
|
||||
if (prog.execWithTask((Task*)upload.get()) != QDialog::Accepted)
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to upload skin!"), QMessageBox::Warning)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Success"), QMessageBox::Information)->exec();
|
||||
close();
|
||||
AuthSessionPtr session = std::make_shared<AuthSession>();
|
||||
auto login = m_acct->login(session);
|
||||
ProgressDialog prog(this);
|
||||
if (prog.execWithTask((Task*)login.get()) != QDialog::Accepted)
|
||||
{
|
||||
//FIXME: recover with password prompt
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to login!"), QMessageBox::Warning)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
QString fileName;
|
||||
QString input = ui->skinPathTextBox->text();
|
||||
QRegExp urlPrefixMatcher("^([a-z]+)://.+$");
|
||||
bool isLocalFile = false;
|
||||
// it has an URL prefix -> it is an URL
|
||||
if(urlPrefixMatcher.exactMatch(input))
|
||||
{
|
||||
QUrl fileURL = input;
|
||||
if(fileURL.isValid())
|
||||
{
|
||||
// local?
|
||||
if(fileURL.isLocalFile())
|
||||
{
|
||||
isLocalFile = true;
|
||||
fileName = fileURL.toLocalFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
this,
|
||||
tr("Skin Upload"),
|
||||
tr("Using remote URLs for setting skins is not implemented yet."),
|
||||
QMessageBox::Warning
|
||||
)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CustomMessageBox::selectable(
|
||||
this,
|
||||
tr("Skin Upload"),
|
||||
tr("You cannot use an invalid URL for uploading skins."),
|
||||
QMessageBox::Warning
|
||||
)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// just assume it's a path then
|
||||
isLocalFile = true;
|
||||
fileName = ui->skinPathTextBox->text();
|
||||
}
|
||||
if (isLocalFile && !QFile::exists(fileName))
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Skin file does not exist!"), QMessageBox::Warning)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
SkinUpload::Model model = SkinUpload::STEVE;
|
||||
if (ui->steveBtn->isChecked())
|
||||
{
|
||||
model = SkinUpload::STEVE;
|
||||
}
|
||||
else if (ui->alexBtn->isChecked())
|
||||
{
|
||||
model = SkinUpload::ALEX;
|
||||
}
|
||||
SkinUploadPtr upload = std::make_shared<SkinUpload>(this, session, FS::read(fileName), model);
|
||||
if (prog.execWithTask((Task*)upload.get()) != QDialog::Accepted)
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Failed to upload skin!"), QMessageBox::Warning)->exec();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
CustomMessageBox::selectable(this, tr("Skin Upload"), tr("Success"), QMessageBox::Information)->exec();
|
||||
close();
|
||||
}
|
||||
|
||||
void SkinUploadDialog::on_skinBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), "*.png");
|
||||
if (raw_path.isEmpty() || !QFileInfo::exists(raw_path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString cooked_path = FS::NormalizePath(raw_path);
|
||||
ui->skinPathTextBox->setText(cooked_path);
|
||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Select Skin Texture"), QString(), "*.png");
|
||||
if (raw_path.isEmpty() || !QFileInfo::exists(raw_path))
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString cooked_path = FS::NormalizePath(raw_path);
|
||||
ui->skinPathTextBox->setText(cooked_path);
|
||||
}
|
||||
|
||||
SkinUploadDialog::SkinUploadDialog(MojangAccountPtr acct, QWidget *parent)
|
||||
:QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog)
|
||||
:QDialog(parent), m_acct(acct), ui(new Ui::SkinUploadDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
@ -5,25 +5,25 @@
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SkinUploadDialog;
|
||||
class SkinUploadDialog;
|
||||
}
|
||||
|
||||
class SkinUploadDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SkinUploadDialog(MojangAccountPtr acct, QWidget *parent = 0);
|
||||
virtual ~SkinUploadDialog() {};
|
||||
explicit SkinUploadDialog(MojangAccountPtr acct, QWidget *parent = 0);
|
||||
virtual ~SkinUploadDialog() {};
|
||||
|
||||
public slots:
|
||||
void on_buttonBox_accepted();
|
||||
void on_buttonBox_accepted();
|
||||
|
||||
void on_buttonBox_rejected();
|
||||
void on_buttonBox_rejected();
|
||||
|
||||
void on_skinBrowseBtn_clicked();
|
||||
void on_skinBrowseBtn_clicked();
|
||||
|
||||
protected:
|
||||
MojangAccountPtr m_acct;
|
||||
MojangAccountPtr m_acct;
|
||||
|
||||
private:
|
||||
Ui::SkinUploadDialog *ui;
|
||||
Ui::SkinUploadDialog *ui;
|
||||
};
|
||||
|
@ -10,20 +10,20 @@
|
||||
|
||||
UpdateDialog::UpdateDialog(bool hasUpdate, QWidget *parent) : QDialog(parent), ui(new Ui::UpdateDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
if(hasUpdate)
|
||||
{
|
||||
ui->label->setText(tr("A new %1 update is available!").arg(channel));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel));
|
||||
ui->btnUpdateNow->setHidden(true);
|
||||
ui->btnUpdateLater->setText(tr("Close"));
|
||||
}
|
||||
loadChangelog();
|
||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("UpdateDialogGeometry").toByteArray()));
|
||||
ui->setupUi(this);
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
if(hasUpdate)
|
||||
{
|
||||
ui->label->setText(tr("A new %1 update is available!").arg(channel));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->label->setText(tr("No %1 updates found. You are running the latest version.").arg(channel));
|
||||
ui->btnUpdateNow->setHidden(true);
|
||||
ui->btnUpdateLater->setText(tr("Close"));
|
||||
}
|
||||
loadChangelog();
|
||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("UpdateDialogGeometry").toByteArray()));
|
||||
}
|
||||
|
||||
UpdateDialog::~UpdateDialog()
|
||||
@ -32,150 +32,150 @@ UpdateDialog::~UpdateDialog()
|
||||
|
||||
void UpdateDialog::loadChangelog()
|
||||
{
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
dljob.reset(new NetJob("Changelog"));
|
||||
QString url;
|
||||
if(channel == "stable")
|
||||
{
|
||||
url = QString("https://raw.githubusercontent.com/MultiMC/MultiMC5/%1/changelog.md").arg(channel);
|
||||
m_changelogType = CHANGELOG_MARKDOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
url = QString("https://api.github.com/repos/MultiMC/MultiMC5/compare/%1...%2").arg(BuildConfig.GIT_COMMIT, channel);
|
||||
m_changelogType = CHANGELOG_COMMITS;
|
||||
}
|
||||
dljob->addNetAction(Net::Download::makeByteArray(QUrl(url), &changelogData));
|
||||
connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded);
|
||||
connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed);
|
||||
dljob->start();
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
dljob.reset(new NetJob("Changelog"));
|
||||
QString url;
|
||||
if(channel == "stable")
|
||||
{
|
||||
url = QString("https://raw.githubusercontent.com/MultiMC/MultiMC5/%1/changelog.md").arg(channel);
|
||||
m_changelogType = CHANGELOG_MARKDOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
url = QString("https://api.github.com/repos/MultiMC/MultiMC5/compare/%1...%2").arg(BuildConfig.GIT_COMMIT, channel);
|
||||
m_changelogType = CHANGELOG_COMMITS;
|
||||
}
|
||||
dljob->addNetAction(Net::Download::makeByteArray(QUrl(url), &changelogData));
|
||||
connect(dljob.get(), &NetJob::succeeded, this, &UpdateDialog::changelogLoaded);
|
||||
connect(dljob.get(), &NetJob::failed, this, &UpdateDialog::changelogFailed);
|
||||
dljob->start();
|
||||
}
|
||||
|
||||
QString reprocessMarkdown(QByteArray markdown)
|
||||
{
|
||||
HoeDown hoedown;
|
||||
QString output = hoedown.process(markdown);
|
||||
HoeDown hoedown;
|
||||
QString output = hoedown.process(markdown);
|
||||
|
||||
// HACK: easier than customizing hoedown
|
||||
output.replace(QRegExp("GH-([0-9]+)"), "<a href=\"https://github.com/MultiMC/MultiMC5/issues/\\1\">GH-\\1</a>");
|
||||
qDebug() << output;
|
||||
return output;
|
||||
// HACK: easier than customizing hoedown
|
||||
output.replace(QRegExp("GH-([0-9]+)"), "<a href=\"https://github.com/MultiMC/MultiMC5/issues/\\1\">GH-\\1</a>");
|
||||
qDebug() << output;
|
||||
return output;
|
||||
}
|
||||
|
||||
QString reprocessCommits(QByteArray json)
|
||||
{
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
try
|
||||
{
|
||||
QString result;
|
||||
auto document = Json::requireDocument(json);
|
||||
auto rootobject = Json::requireObject(document);
|
||||
auto status = Json::requireString(rootobject, "status");
|
||||
auto diff_url = Json::requireString(rootobject, "html_url");
|
||||
auto channel = MMC->settings()->get("UpdateChannel").toString();
|
||||
try
|
||||
{
|
||||
QString result;
|
||||
auto document = Json::requireDocument(json);
|
||||
auto rootobject = Json::requireObject(document);
|
||||
auto status = Json::requireString(rootobject, "status");
|
||||
auto diff_url = Json::requireString(rootobject, "html_url");
|
||||
|
||||
auto print_commits = [&]()
|
||||
{
|
||||
result += "<table cellspacing=0 cellpadding=2 style='border-width: 1px; border-style: solid'>";
|
||||
auto commitarray = Json::requireArray(rootobject, "commits");
|
||||
for(int i = commitarray.size() - 1; i >= 0; i--)
|
||||
{
|
||||
const auto & commitval = commitarray[i];
|
||||
auto commitobj = Json::requireObject(commitval);
|
||||
auto parents_info = Json::ensureArray(commitobj, "parents");
|
||||
// NOTE: this ignores merge commits, because they have more than one parent
|
||||
if(parents_info.size() > 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto commit_url = Json::requireString(commitobj, "html_url");
|
||||
auto commit_info = Json::requireObject(commitobj, "commit");
|
||||
auto commit_message = Json::requireString(commit_info, "message");
|
||||
auto lines = commit_message.split('\n');
|
||||
QRegularExpression regexp("(?<prefix>(GH-(?<issuenr>[0-9]+))|(NOISSUE)|(SCRATCH))? *(?<rest>.*) *");
|
||||
auto match = regexp.match(lines.takeFirst(), 0, QRegularExpression::NormalMatch);
|
||||
auto issuenr = match.captured("issuenr");
|
||||
auto prefix = match.captured("prefix");
|
||||
auto rest = match.captured("rest");
|
||||
result += "<tr><td>";
|
||||
if(issuenr.length())
|
||||
{
|
||||
result += QString("<a href=\"https://github.com/MultiMC/MultiMC5/issues/%1\">GH-%2</a>").arg(issuenr, issuenr);
|
||||
}
|
||||
else if(prefix.length())
|
||||
{
|
||||
result += QString("<a href=\"%1\">%2</a>").arg(commit_url, prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += QString("<a href=\"%1\">NOISSUE</a>").arg(commit_url);
|
||||
}
|
||||
result += "</td>";
|
||||
lines.prepend(rest);
|
||||
result += "<td><p>" + lines.join("<br />") + "</p></td></tr>";
|
||||
}
|
||||
result += "</table>";
|
||||
};
|
||||
auto print_commits = [&]()
|
||||
{
|
||||
result += "<table cellspacing=0 cellpadding=2 style='border-width: 1px; border-style: solid'>";
|
||||
auto commitarray = Json::requireArray(rootobject, "commits");
|
||||
for(int i = commitarray.size() - 1; i >= 0; i--)
|
||||
{
|
||||
const auto & commitval = commitarray[i];
|
||||
auto commitobj = Json::requireObject(commitval);
|
||||
auto parents_info = Json::ensureArray(commitobj, "parents");
|
||||
// NOTE: this ignores merge commits, because they have more than one parent
|
||||
if(parents_info.size() > 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto commit_url = Json::requireString(commitobj, "html_url");
|
||||
auto commit_info = Json::requireObject(commitobj, "commit");
|
||||
auto commit_message = Json::requireString(commit_info, "message");
|
||||
auto lines = commit_message.split('\n');
|
||||
QRegularExpression regexp("(?<prefix>(GH-(?<issuenr>[0-9]+))|(NOISSUE)|(SCRATCH))? *(?<rest>.*) *");
|
||||
auto match = regexp.match(lines.takeFirst(), 0, QRegularExpression::NormalMatch);
|
||||
auto issuenr = match.captured("issuenr");
|
||||
auto prefix = match.captured("prefix");
|
||||
auto rest = match.captured("rest");
|
||||
result += "<tr><td>";
|
||||
if(issuenr.length())
|
||||
{
|
||||
result += QString("<a href=\"https://github.com/MultiMC/MultiMC5/issues/%1\">GH-%2</a>").arg(issuenr, issuenr);
|
||||
}
|
||||
else if(prefix.length())
|
||||
{
|
||||
result += QString("<a href=\"%1\">%2</a>").arg(commit_url, prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += QString("<a href=\"%1\">NOISSUE</a>").arg(commit_url);
|
||||
}
|
||||
result += "</td>";
|
||||
lines.prepend(rest);
|
||||
result += "<td><p>" + lines.join("<br />") + "</p></td></tr>";
|
||||
}
|
||||
result += "</table>";
|
||||
};
|
||||
|
||||
if(status == "identical")
|
||||
{
|
||||
return QObject::tr("<p>There are no code changes between your current version and latest %1.</p>").arg(channel);
|
||||
}
|
||||
else if(status == "ahead")
|
||||
{
|
||||
result += QObject::tr("<p>Following commits were added since last update:</p>");
|
||||
print_commits();
|
||||
}
|
||||
else if(status == "diverged")
|
||||
{
|
||||
auto commit_ahead = Json::requireInteger(rootobject, "ahead_by");
|
||||
auto commit_behind = Json::requireInteger(rootobject, "behind_by");
|
||||
result += QObject::tr("<p>The update removes %1 commits and adds the following %2:</p>").arg(commit_behind).arg(commit_ahead);
|
||||
print_commits();
|
||||
}
|
||||
result += QObject::tr("<p>You can <a href=\"%1\">look at the changes on github</a>.</p>").arg(diff_url);
|
||||
return result;
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
qWarning() << "Got an unparseable commit log from github:" << e.what();
|
||||
qDebug() << json;
|
||||
}
|
||||
return QString();
|
||||
if(status == "identical")
|
||||
{
|
||||
return QObject::tr("<p>There are no code changes between your current version and latest %1.</p>").arg(channel);
|
||||
}
|
||||
else if(status == "ahead")
|
||||
{
|
||||
result += QObject::tr("<p>Following commits were added since last update:</p>");
|
||||
print_commits();
|
||||
}
|
||||
else if(status == "diverged")
|
||||
{
|
||||
auto commit_ahead = Json::requireInteger(rootobject, "ahead_by");
|
||||
auto commit_behind = Json::requireInteger(rootobject, "behind_by");
|
||||
result += QObject::tr("<p>The update removes %1 commits and adds the following %2:</p>").arg(commit_behind).arg(commit_ahead);
|
||||
print_commits();
|
||||
}
|
||||
result += QObject::tr("<p>You can <a href=\"%1\">look at the changes on github</a>.</p>").arg(diff_url);
|
||||
return result;
|
||||
}
|
||||
catch (const JSONValidationError &e)
|
||||
{
|
||||
qWarning() << "Got an unparseable commit log from github:" << e.what();
|
||||
qDebug() << json;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void UpdateDialog::changelogLoaded()
|
||||
{
|
||||
QString result;
|
||||
switch(m_changelogType)
|
||||
{
|
||||
case CHANGELOG_COMMITS:
|
||||
result = reprocessCommits(changelogData);
|
||||
break;
|
||||
case CHANGELOG_MARKDOWN:
|
||||
result = reprocessMarkdown(changelogData);
|
||||
break;
|
||||
}
|
||||
changelogData.clear();
|
||||
ui->changelogBrowser->setHtml(result);
|
||||
QString result;
|
||||
switch(m_changelogType)
|
||||
{
|
||||
case CHANGELOG_COMMITS:
|
||||
result = reprocessCommits(changelogData);
|
||||
break;
|
||||
case CHANGELOG_MARKDOWN:
|
||||
result = reprocessMarkdown(changelogData);
|
||||
break;
|
||||
}
|
||||
changelogData.clear();
|
||||
ui->changelogBrowser->setHtml(result);
|
||||
}
|
||||
|
||||
void UpdateDialog::changelogFailed(QString reason)
|
||||
{
|
||||
ui->changelogBrowser->setHtml(tr("<p align=\"center\" <span style=\"font-size:22pt;\">Failed to fetch changelog... Error: %1</span></p>").arg(reason));
|
||||
ui->changelogBrowser->setHtml(tr("<p align=\"center\" <span style=\"font-size:22pt;\">Failed to fetch changelog... Error: %1</span></p>").arg(reason));
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateLater_clicked()
|
||||
{
|
||||
reject();
|
||||
reject();
|
||||
}
|
||||
|
||||
void UpdateDialog::on_btnUpdateNow_clicked()
|
||||
{
|
||||
done(UPDATE_NOW);
|
||||
done(UPDATE_NOW);
|
||||
}
|
||||
|
||||
void UpdateDialog::closeEvent(QCloseEvent* evt)
|
||||
{
|
||||
MMC->settings()->set("UpdateDialogGeometry", saveGeometry().toBase64());
|
||||
QDialog::closeEvent(evt);
|
||||
MMC->settings()->set("UpdateDialogGeometry", saveGeometry().toBase64());
|
||||
QDialog::closeEvent(evt);
|
||||
}
|
||||
|
@ -25,43 +25,43 @@ class UpdateDialog;
|
||||
|
||||
enum UpdateAction
|
||||
{
|
||||
UPDATE_LATER = QDialog::Rejected,
|
||||
UPDATE_NOW = QDialog::Accepted,
|
||||
UPDATE_LATER = QDialog::Rejected,
|
||||
UPDATE_NOW = QDialog::Accepted,
|
||||
};
|
||||
|
||||
enum ChangelogType
|
||||
{
|
||||
CHANGELOG_MARKDOWN,
|
||||
CHANGELOG_COMMITS
|
||||
CHANGELOG_MARKDOWN,
|
||||
CHANGELOG_COMMITS
|
||||
};
|
||||
|
||||
class UpdateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0);
|
||||
~UpdateDialog();
|
||||
explicit UpdateDialog(bool hasUpdate = true, QWidget *parent = 0);
|
||||
~UpdateDialog();
|
||||
|
||||
public slots:
|
||||
void on_btnUpdateNow_clicked();
|
||||
void on_btnUpdateLater_clicked();
|
||||
void on_btnUpdateNow_clicked();
|
||||
void on_btnUpdateLater_clicked();
|
||||
|
||||
/// Starts loading the changelog
|
||||
void loadChangelog();
|
||||
/// Starts loading the changelog
|
||||
void loadChangelog();
|
||||
|
||||
/// Slot for when the chengelog loads successfully.
|
||||
void changelogLoaded();
|
||||
/// Slot for when the chengelog loads successfully.
|
||||
void changelogLoaded();
|
||||
|
||||
/// Slot for when the chengelog fails to load...
|
||||
void changelogFailed(QString reason);
|
||||
/// Slot for when the chengelog fails to load...
|
||||
void changelogFailed(QString reason);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent * ) override;
|
||||
void closeEvent(QCloseEvent * ) override;
|
||||
|
||||
private:
|
||||
Ui::UpdateDialog *ui;
|
||||
QByteArray changelogData;
|
||||
NetJobPtr dljob;
|
||||
ChangelogType m_changelogType = CHANGELOG_MARKDOWN;
|
||||
Ui::UpdateDialog *ui;
|
||||
QByteArray changelogData;
|
||||
NetJobPtr dljob;
|
||||
ChangelogType m_changelogType = CHANGELOG_MARKDOWN;
|
||||
};
|
||||
|
@ -33,109 +33,109 @@
|
||||
#include <widgets/VersionSelectWidget.h>
|
||||
|
||||
VersionSelectDialog::VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent, bool cancelable)
|
||||
: QDialog(parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setObjectName(QStringLiteral("VersionSelectDialog"));
|
||||
resize(400, 347);
|
||||
m_verticalLayout = new QVBoxLayout(this);
|
||||
m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
|
||||
setObjectName(QStringLiteral("VersionSelectDialog"));
|
||||
resize(400, 347);
|
||||
m_verticalLayout = new QVBoxLayout(this);
|
||||
m_verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
|
||||
|
||||
m_versionWidget = new VersionSelectWidget(parent);
|
||||
m_verticalLayout->addWidget(m_versionWidget);
|
||||
m_versionWidget = new VersionSelectWidget(parent);
|
||||
m_verticalLayout->addWidget(m_versionWidget);
|
||||
|
||||
m_horizontalLayout = new QHBoxLayout();
|
||||
m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
m_horizontalLayout = new QHBoxLayout();
|
||||
m_horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
|
||||
|
||||
m_refreshButton = new QPushButton(this);
|
||||
m_refreshButton->setObjectName(QStringLiteral("refreshButton"));
|
||||
m_horizontalLayout->addWidget(m_refreshButton);
|
||||
m_refreshButton = new QPushButton(this);
|
||||
m_refreshButton->setObjectName(QStringLiteral("refreshButton"));
|
||||
m_horizontalLayout->addWidget(m_refreshButton);
|
||||
|
||||
m_buttonBox = new QDialogButtonBox(this);
|
||||
m_buttonBox->setObjectName(QStringLiteral("buttonBox"));
|
||||
m_buttonBox->setOrientation(Qt::Horizontal);
|
||||
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
||||
m_horizontalLayout->addWidget(m_buttonBox);
|
||||
m_buttonBox = new QDialogButtonBox(this);
|
||||
m_buttonBox->setObjectName(QStringLiteral("buttonBox"));
|
||||
m_buttonBox->setOrientation(Qt::Horizontal);
|
||||
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
||||
m_horizontalLayout->addWidget(m_buttonBox);
|
||||
|
||||
m_verticalLayout->addLayout(m_horizontalLayout);
|
||||
m_verticalLayout->addLayout(m_horizontalLayout);
|
||||
|
||||
retranslate();
|
||||
retranslate();
|
||||
|
||||
QObject::connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
QObject::connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
QMetaObject::connectSlotsByName(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
setWindowTitle(title);
|
||||
QMetaObject::connectSlotsByName(this);
|
||||
setWindowModality(Qt::WindowModal);
|
||||
setWindowTitle(title);
|
||||
|
||||
m_vlist = vlist;
|
||||
m_vlist = vlist;
|
||||
|
||||
if (!cancelable)
|
||||
{
|
||||
m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
||||
}
|
||||
if (!cancelable)
|
||||
{
|
||||
m_buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void VersionSelectDialog::retranslate()
|
||||
{
|
||||
// FIXME: overrides custom title given in constructor!
|
||||
setWindowTitle(tr("Choose Version"));
|
||||
m_refreshButton->setToolTip(tr("Reloads the version list."));
|
||||
m_refreshButton->setText(tr("&Refresh"));
|
||||
// FIXME: overrides custom title given in constructor!
|
||||
setWindowTitle(tr("Choose Version"));
|
||||
m_refreshButton->setToolTip(tr("Reloads the version list."));
|
||||
m_refreshButton->setText(tr("&Refresh"));
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setCurrentVersion(const QString& version)
|
||||
{
|
||||
m_currentVersion = version;
|
||||
m_versionWidget->setCurrentVersion(version);
|
||||
m_currentVersion = version;
|
||||
m_versionWidget->setCurrentVersion(version);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setEmptyString(QString emptyString)
|
||||
{
|
||||
m_versionWidget->setEmptyString(emptyString);
|
||||
m_versionWidget->setEmptyString(emptyString);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setEmptyErrorString(QString emptyErrorString)
|
||||
{
|
||||
m_versionWidget->setEmptyErrorString(emptyErrorString);
|
||||
m_versionWidget->setEmptyErrorString(emptyErrorString);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setResizeOn(int column)
|
||||
{
|
||||
resizeOnColumn = column;
|
||||
resizeOnColumn = column;
|
||||
}
|
||||
|
||||
int VersionSelectDialog::exec()
|
||||
{
|
||||
QDialog::open();
|
||||
m_versionWidget->initialize(m_vlist);
|
||||
if(resizeOnColumn != -1)
|
||||
{
|
||||
m_versionWidget->setResizeOn(resizeOnColumn);
|
||||
}
|
||||
return QDialog::exec();
|
||||
QDialog::open();
|
||||
m_versionWidget->initialize(m_vlist);
|
||||
if(resizeOnColumn != -1)
|
||||
{
|
||||
m_versionWidget->setResizeOn(resizeOnColumn);
|
||||
}
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::selectRecommended()
|
||||
{
|
||||
m_versionWidget->selectRecommended();
|
||||
m_versionWidget->selectRecommended();
|
||||
}
|
||||
|
||||
BaseVersionPtr VersionSelectDialog::selectedVersion() const
|
||||
{
|
||||
return m_versionWidget->selectedVersion();
|
||||
return m_versionWidget->selectedVersion();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::on_refreshButton_clicked()
|
||||
{
|
||||
m_versionWidget->loadList();
|
||||
m_versionWidget->loadList();
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setExactFilter(BaseVersionList::ModelRoles role, QString filter)
|
||||
{
|
||||
m_versionWidget->setExactFilter(role, filter);
|
||||
m_versionWidget->setExactFilter(role, filter);
|
||||
}
|
||||
|
||||
void VersionSelectDialog::setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter)
|
||||
{
|
||||
m_versionWidget->setFuzzyFilter(role, filter);
|
||||
m_versionWidget->setFuzzyFilter(role, filter);
|
||||
}
|
||||
|
@ -36,43 +36,43 @@ class VersionProxyModel;
|
||||
|
||||
class VersionSelectDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true);
|
||||
virtual ~VersionSelectDialog() {};
|
||||
explicit VersionSelectDialog(BaseVersionList *vlist, QString title, QWidget *parent = 0, bool cancelable = true);
|
||||
virtual ~VersionSelectDialog() {};
|
||||
|
||||
int exec() override;
|
||||
int exec() override;
|
||||
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
BaseVersionPtr selectedVersion() const;
|
||||
|
||||
void setCurrentVersion(const QString & version);
|
||||
void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter);
|
||||
void setExactFilter(BaseVersionList::ModelRoles role, QString filter);
|
||||
void setEmptyString(QString emptyString);
|
||||
void setEmptyErrorString(QString emptyErrorString);
|
||||
void setResizeOn(int column);
|
||||
void setCurrentVersion(const QString & version);
|
||||
void setFuzzyFilter(BaseVersionList::ModelRoles role, QString filter);
|
||||
void setExactFilter(BaseVersionList::ModelRoles role, QString filter);
|
||||
void setEmptyString(QString emptyString);
|
||||
void setEmptyErrorString(QString emptyErrorString);
|
||||
void setResizeOn(int column);
|
||||
|
||||
private slots:
|
||||
void on_refreshButton_clicked();
|
||||
void on_refreshButton_clicked();
|
||||
|
||||
private:
|
||||
void retranslate();
|
||||
void selectRecommended();
|
||||
void retranslate();
|
||||
void selectRecommended();
|
||||
|
||||
private:
|
||||
QString m_currentVersion;
|
||||
VersionSelectWidget *m_versionWidget = nullptr;
|
||||
QVBoxLayout *m_verticalLayout = nullptr;
|
||||
QHBoxLayout *m_horizontalLayout = nullptr;
|
||||
QPushButton *m_refreshButton = nullptr;
|
||||
QDialogButtonBox *m_buttonBox = nullptr;
|
||||
QString m_currentVersion;
|
||||
VersionSelectWidget *m_versionWidget = nullptr;
|
||||
QVBoxLayout *m_verticalLayout = nullptr;
|
||||
QHBoxLayout *m_horizontalLayout = nullptr;
|
||||
QPushButton *m_refreshButton = nullptr;
|
||||
QDialogButtonBox *m_buttonBox = nullptr;
|
||||
|
||||
BaseVersionList *m_vlist = nullptr;
|
||||
BaseVersionList *m_vlist = nullptr;
|
||||
|
||||
VersionProxyModel *m_proxyModel = nullptr;
|
||||
VersionProxyModel *m_proxyModel = nullptr;
|
||||
|
||||
int resizeOnColumn = -1;
|
||||
int resizeOnColumn = -1;
|
||||
|
||||
Task * loadTask = nullptr;
|
||||
Task * loadTask = nullptr;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,126 +23,126 @@
|
||||
|
||||
struct GroupViewRoles
|
||||
{
|
||||
enum
|
||||
{
|
||||
GroupRole = Qt::UserRole,
|
||||
ProgressValueRole,
|
||||
ProgressMaximumRole
|
||||
};
|
||||
enum
|
||||
{
|
||||
GroupRole = Qt::UserRole,
|
||||
ProgressValueRole,
|
||||
ProgressMaximumRole
|
||||
};
|
||||
};
|
||||
|
||||
class GroupView : public QAbstractItemView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GroupView(QWidget *parent = 0);
|
||||
~GroupView();
|
||||
GroupView(QWidget *parent = 0);
|
||||
~GroupView();
|
||||
|
||||
void setModel(QAbstractItemModel *model) override;
|
||||
void setModel(QAbstractItemModel *model) override;
|
||||
|
||||
/// return geometry rectangle occupied by the specified model item
|
||||
QRect geometryRect(const QModelIndex &index) const;
|
||||
/// return visual rectangle occupied by the specified model item
|
||||
virtual QRect visualRect(const QModelIndex &index) const override;
|
||||
/// get the model index at the specified visual point
|
||||
virtual QModelIndex indexAt(const QPoint &point) const override;
|
||||
QString groupNameAt(const QPoint &point);
|
||||
void setSelection(const QRect &rect,
|
||||
const QItemSelectionModel::SelectionFlags commands) override;
|
||||
/// return geometry rectangle occupied by the specified model item
|
||||
QRect geometryRect(const QModelIndex &index) const;
|
||||
/// return visual rectangle occupied by the specified model item
|
||||
virtual QRect visualRect(const QModelIndex &index) const override;
|
||||
/// get the model index at the specified visual point
|
||||
virtual QModelIndex indexAt(const QPoint &point) const override;
|
||||
QString groupNameAt(const QPoint &point);
|
||||
void setSelection(const QRect &rect,
|
||||
const QItemSelectionModel::SelectionFlags commands) override;
|
||||
|
||||
virtual int horizontalOffset() const override;
|
||||
virtual int verticalOffset() const override;
|
||||
virtual void scrollContentsBy(int dx, int dy) override;
|
||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
virtual int horizontalOffset() const override;
|
||||
virtual int verticalOffset() const override;
|
||||
virtual void scrollContentsBy(int dx, int dy) override;
|
||||
virtual void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
|
||||
|
||||
virtual QModelIndex moveCursor(CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
virtual QModelIndex moveCursor(CursorAction cursorAction,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
virtual QRegion visualRegionForSelection(const QItemSelection &selection) const override;
|
||||
|
||||
int spacing() const
|
||||
{
|
||||
return m_spacing;
|
||||
};
|
||||
int spacing() const
|
||||
{
|
||||
return m_spacing;
|
||||
};
|
||||
|
||||
public slots:
|
||||
virtual void updateGeometries() override;
|
||||
virtual void updateGeometries() override;
|
||||
|
||||
protected slots:
|
||||
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles) override;
|
||||
virtual void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override;
|
||||
void modelReset();
|
||||
void rowsRemoved();
|
||||
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles) override;
|
||||
virtual void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override;
|
||||
void modelReset();
|
||||
void rowsRemoved();
|
||||
|
||||
signals:
|
||||
void droppedURLs(QList<QUrl> urls);
|
||||
void droppedURLs(QList<QUrl> urls);
|
||||
|
||||
protected:
|
||||
virtual bool isIndexHidden(const QModelIndex &index) const override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
virtual bool isIndexHidden(const QModelIndex &index) const override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
void dropEvent(QDropEvent *event) override;
|
||||
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
|
||||
void updateScrollbar();
|
||||
void updateScrollbar();
|
||||
|
||||
private:
|
||||
friend struct VisualGroup;
|
||||
QList<VisualGroup *> m_groups;
|
||||
friend struct VisualGroup;
|
||||
QList<VisualGroup *> m_groups;
|
||||
|
||||
// geometry
|
||||
int m_leftMargin = 5;
|
||||
int m_rightMargin = 5;
|
||||
int m_bottomMargin = 5;
|
||||
int m_categoryMargin = 5;
|
||||
int m_spacing = 5;
|
||||
int m_itemWidth = 100;
|
||||
int m_currentItemsPerRow = -1;
|
||||
int m_currentCursorColumn= -1;
|
||||
mutable QCache<int, QRect> geometryCache;
|
||||
// geometry
|
||||
int m_leftMargin = 5;
|
||||
int m_rightMargin = 5;
|
||||
int m_bottomMargin = 5;
|
||||
int m_categoryMargin = 5;
|
||||
int m_spacing = 5;
|
||||
int m_itemWidth = 100;
|
||||
int m_currentItemsPerRow = -1;
|
||||
int m_currentCursorColumn= -1;
|
||||
mutable QCache<int, QRect> geometryCache;
|
||||
|
||||
// point where the currently active mouse action started in geometry coordinates
|
||||
QPoint m_pressedPosition;
|
||||
QPersistentModelIndex m_pressedIndex;
|
||||
bool m_pressedAlreadySelected;
|
||||
VisualGroup *m_pressedCategory;
|
||||
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
||||
QPoint m_lastDragPosition;
|
||||
// point where the currently active mouse action started in geometry coordinates
|
||||
QPoint m_pressedPosition;
|
||||
QPersistentModelIndex m_pressedIndex;
|
||||
bool m_pressedAlreadySelected;
|
||||
VisualGroup *m_pressedCategory;
|
||||
QItemSelectionModel::SelectionFlag m_ctrlDragSelectionFlag;
|
||||
QPoint m_lastDragPosition;
|
||||
|
||||
VisualGroup *category(const QModelIndex &index) const;
|
||||
VisualGroup *category(const QString &cat) const;
|
||||
VisualGroup *categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const;
|
||||
VisualGroup *category(const QModelIndex &index) const;
|
||||
VisualGroup *category(const QString &cat) const;
|
||||
VisualGroup *categoryAt(const QPoint &pos, VisualGroup::HitResults & result) const;
|
||||
|
||||
int itemsPerRow() const
|
||||
{
|
||||
return m_currentItemsPerRow;
|
||||
};
|
||||
int contentWidth() const;
|
||||
int itemsPerRow() const
|
||||
{
|
||||
return m_currentItemsPerRow;
|
||||
};
|
||||
int contentWidth() const;
|
||||
|
||||
private: /* methods */
|
||||
int itemWidth() const;
|
||||
int calculateItemsPerRow() const;
|
||||
int verticalScrollToValue(const QModelIndex &index, const QRect &rect,
|
||||
QListView::ScrollHint hint) const;
|
||||
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
|
||||
QList<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices,
|
||||
QRect *r) const;
|
||||
int itemWidth() const;
|
||||
int calculateItemsPerRow() const;
|
||||
int verticalScrollToValue(const QModelIndex &index, const QRect &rect,
|
||||
QListView::ScrollHint hint) const;
|
||||
QPixmap renderToPixmap(const QModelIndexList &indices, QRect *r) const;
|
||||
QList<QPair<QRect, QModelIndex>> draggablePaintPairs(const QModelIndexList &indices,
|
||||
QRect *r) const;
|
||||
|
||||
bool isDragEventAccepted(QDropEvent *event);
|
||||
bool isDragEventAccepted(QDropEvent *event);
|
||||
|
||||
QPair<VisualGroup *, int> rowDropPos(const QPoint &pos);
|
||||
QPair<VisualGroup *, int> rowDropPos(const QPoint &pos);
|
||||
|
||||
QPoint offset() const;
|
||||
QPoint offset() const;
|
||||
};
|
||||
|
@ -24,25 +24,25 @@ GroupedProxyModel::GroupedProxyModel(QObject *parent) : QSortFilterProxyModel(pa
|
||||
|
||||
bool GroupedProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
const QString leftCategory = left.data(GroupViewRoles::GroupRole).toString();
|
||||
const QString rightCategory = right.data(GroupViewRoles::GroupRole).toString();
|
||||
if (leftCategory == rightCategory)
|
||||
{
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: real group sorting happens in GroupView::updateGeometries(), see LocaleString
|
||||
auto result = leftCategory.localeAwareCompare(rightCategory);
|
||||
if(result == 0)
|
||||
{
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
return result < 0;
|
||||
}
|
||||
const QString leftCategory = left.data(GroupViewRoles::GroupRole).toString();
|
||||
const QString rightCategory = right.data(GroupViewRoles::GroupRole).toString();
|
||||
if (leftCategory == rightCategory)
|
||||
{
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: real group sorting happens in GroupView::updateGeometries(), see LocaleString
|
||||
auto result = leftCategory.localeAwareCompare(rightCategory);
|
||||
if(result == 0)
|
||||
{
|
||||
return subSortLessThan(left, right);
|
||||
}
|
||||
return result < 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool GroupedProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
return left.row() < right.row();
|
||||
return left.row() < right.row();
|
||||
}
|
||||
|
@ -19,12 +19,12 @@
|
||||
|
||||
class GroupedProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GroupedProxyModel(QObject *parent = 0);
|
||||
GroupedProxyModel(QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
virtual bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
};
|
||||
|
@ -27,25 +27,25 @@
|
||||
|
||||
// Origin: Qt
|
||||
static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
|
||||
qreal &widthUsed)
|
||||
qreal &widthUsed)
|
||||
{
|
||||
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();
|
||||
widthUsed = qMax(widthUsed, line.naturalTextWidth());
|
||||
}
|
||||
textLayout.endLayout();
|
||||
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();
|
||||
widthUsed = qMax(widthUsed, line.naturalTextWidth());
|
||||
}
|
||||
textLayout.endLayout();
|
||||
}
|
||||
|
||||
ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent)
|
||||
@ -53,291 +53,291 @@ ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent
|
||||
}
|
||||
|
||||
void drawSelectionRect(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QRect &rect)
|
||||
const QRect &rect)
|
||||
{
|
||||
if ((option.state & QStyle::State_Selected))
|
||||
painter->fillRect(rect, option.palette.brush(QPalette::Highlight));
|
||||
else
|
||||
{
|
||||
QColor backgroundColor = option.palette.color(QPalette::Background);
|
||||
backgroundColor.setAlpha(160);
|
||||
painter->fillRect(rect, QBrush(backgroundColor));
|
||||
}
|
||||
if ((option.state & QStyle::State_Selected))
|
||||
painter->fillRect(rect, option.palette.brush(QPalette::Highlight));
|
||||
else
|
||||
{
|
||||
QColor backgroundColor = option.palette.color(QPalette::Background);
|
||||
backgroundColor.setAlpha(160);
|
||||
painter->fillRect(rect, QBrush(backgroundColor));
|
||||
}
|
||||
}
|
||||
|
||||
void drawFocusRect(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect)
|
||||
{
|
||||
if (!(option.state & QStyle::State_HasFocus))
|
||||
return;
|
||||
QStyleOptionFocusRect opt;
|
||||
opt.direction = option.direction;
|
||||
opt.fontMetrics = option.fontMetrics;
|
||||
opt.palette = option.palette;
|
||||
opt.rect = rect;
|
||||
// opt.state = option.state | QStyle::State_KeyboardFocusChange |
|
||||
// QStyle::State_Item;
|
||||
auto col = option.state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base;
|
||||
opt.backgroundColor = option.palette.color(col);
|
||||
// Apparently some widget styles expect this hint to not be set
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
if (!(option.state & QStyle::State_HasFocus))
|
||||
return;
|
||||
QStyleOptionFocusRect opt;
|
||||
opt.direction = option.direction;
|
||||
opt.fontMetrics = option.fontMetrics;
|
||||
opt.palette = option.palette;
|
||||
opt.rect = rect;
|
||||
// opt.state = option.state | QStyle::State_KeyboardFocusChange |
|
||||
// QStyle::State_Item;
|
||||
auto col = option.state & QStyle::State_Selected ? QPalette::Highlight : QPalette::Base;
|
||||
opt.backgroundColor = option.palette.color(col);
|
||||
// Apparently some widget styles expect this hint to not be set
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
|
||||
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
|
||||
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
|
||||
|
||||
style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget);
|
||||
style->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, painter, option.widget);
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
}
|
||||
|
||||
// TODO this can be made a lot prettier
|
||||
void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const int value, const int maximum)
|
||||
const int value, const int maximum)
|
||||
{
|
||||
if (maximum == 0 || value == maximum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (maximum == 0 || value == maximum)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
painter->save();
|
||||
painter->save();
|
||||
|
||||
qreal percent = (qreal)value / (qreal)maximum;
|
||||
QColor color = option.palette.color(QPalette::Dark);
|
||||
color.setAlphaF(0.70f);
|
||||
painter->setBrush(color);
|
||||
painter->setPen(QPen(QBrush(), 0));
|
||||
painter->drawPie(option.rect, 90 * 16, -percent * 360 * 16);
|
||||
qreal percent = (qreal)value / (qreal)maximum;
|
||||
QColor color = option.palette.color(QPalette::Dark);
|
||||
color.setAlphaF(0.70f);
|
||||
painter->setBrush(color);
|
||||
painter->setPen(QPen(QBrush(), 0));
|
||||
painter->drawPie(option.rect, 90 * 16, -percent * 360 * 16);
|
||||
|
||||
painter->restore();
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void drawBadges(QPainter *painter, const QStyleOptionViewItem &option, BaseInstance *instance, QIcon::Mode mode, QIcon::State state)
|
||||
{
|
||||
QList<QString> pixmaps;
|
||||
if (instance->isRunning())
|
||||
{
|
||||
pixmaps.append("status-running");
|
||||
}
|
||||
else if (instance->hasCrashed() || instance->hasVersionBroken())
|
||||
{
|
||||
pixmaps.append("status-bad");
|
||||
}
|
||||
if (instance->hasUpdateAvailable())
|
||||
{
|
||||
pixmaps.append("checkupdate");
|
||||
}
|
||||
QList<QString> pixmaps;
|
||||
if (instance->isRunning())
|
||||
{
|
||||
pixmaps.append("status-running");
|
||||
}
|
||||
else if (instance->hasCrashed() || instance->hasVersionBroken())
|
||||
{
|
||||
pixmaps.append("status-bad");
|
||||
}
|
||||
if (instance->hasUpdateAvailable())
|
||||
{
|
||||
pixmaps.append("checkupdate");
|
||||
}
|
||||
|
||||
static const int itemSide = 24;
|
||||
static const int spacing = 1;
|
||||
const int itemsPerRow = qMax(1, qFloor(double(option.rect.width() + spacing) / double(itemSide + spacing)));
|
||||
const int rows = qCeil((double)pixmaps.size() / (double)itemsPerRow);
|
||||
QListIterator<QString> it(pixmaps);
|
||||
painter->translate(option.rect.topLeft());
|
||||
for (int y = 0; y < rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < itemsPerRow; ++x)
|
||||
{
|
||||
if (!it.hasNext())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// FIXME: inject this.
|
||||
auto icon = XdgIcon::fromTheme(it.next());
|
||||
// opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
const QPixmap pixmap;
|
||||
// itemSide
|
||||
QRect badgeRect(
|
||||
option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
|
||||
y * itemSide + qMax(y - 1, 0) * spacing,
|
||||
itemSide,
|
||||
itemSide
|
||||
);
|
||||
icon.paint(painter, badgeRect, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
}
|
||||
painter->translate(-option.rect.topLeft());
|
||||
static const int itemSide = 24;
|
||||
static const int spacing = 1;
|
||||
const int itemsPerRow = qMax(1, qFloor(double(option.rect.width() + spacing) / double(itemSide + spacing)));
|
||||
const int rows = qCeil((double)pixmaps.size() / (double)itemsPerRow);
|
||||
QListIterator<QString> it(pixmaps);
|
||||
painter->translate(option.rect.topLeft());
|
||||
for (int y = 0; y < rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < itemsPerRow; ++x)
|
||||
{
|
||||
if (!it.hasNext())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// FIXME: inject this.
|
||||
auto icon = XdgIcon::fromTheme(it.next());
|
||||
// opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
const QPixmap pixmap;
|
||||
// itemSide
|
||||
QRect badgeRect(
|
||||
option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
|
||||
y * itemSide + qMax(y - 1, 0) * spacing,
|
||||
itemSide,
|
||||
itemSide
|
||||
);
|
||||
icon.paint(painter, badgeRect, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
}
|
||||
painter->translate(-option.rect.topLeft());
|
||||
}
|
||||
|
||||
static QSize viewItemTextSize(const QStyleOptionViewItem *option)
|
||||
{
|
||||
QStyle *style = option->widget ? option->widget->style() : QApplication::style();
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setFont(option->font);
|
||||
textLayout.setText(option->text);
|
||||
const int textMargin =
|
||||
style->pixelMetric(QStyle::PM_FocusFrameHMargin, option, option->widget) + 1;
|
||||
QRect bounds(0, 0, 100 - 2 * textMargin, 600);
|
||||
qreal height = 0, widthUsed = 0;
|
||||
viewItemTextLayout(textLayout, bounds.width(), height, widthUsed);
|
||||
const QSize size(qCeil(widthUsed), qCeil(height));
|
||||
return QSize(size.width() + 2 * textMargin, size.height());
|
||||
QStyle *style = option->widget ? option->widget->style() : QApplication::style();
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setFont(option->font);
|
||||
textLayout.setText(option->text);
|
||||
const int textMargin =
|
||||
style->pixelMetric(QStyle::PM_FocusFrameHMargin, option, option->widget) + 1;
|
||||
QRect bounds(0, 0, 100 - 2 * textMargin, 600);
|
||||
qreal height = 0, widthUsed = 0;
|
||||
viewItemTextLayout(textLayout, bounds.width(), height, widthUsed);
|
||||
const QSize size(qCeil(widthUsed), qCeil(height));
|
||||
return QSize(size.width() + 2 * textMargin, size.height());
|
||||
}
|
||||
|
||||
void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
painter->save();
|
||||
painter->setClipRect(opt.rect);
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
painter->save();
|
||||
painter->setClipRect(opt.rect);
|
||||
|
||||
opt.features |= QStyleOptionViewItem::WrapText;
|
||||
opt.text = index.data().toString();
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
opt.features |= QStyleOptionViewItem::WrapText;
|
||||
opt.text = index.data().toString();
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
|
||||
// const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize);
|
||||
const int iconSize = 48;
|
||||
QRect iconbox = opt.rect;
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, opt.widget) + 1;
|
||||
QRect textRect = opt.rect;
|
||||
QRect textHighlightRect = textRect;
|
||||
// clip the decoration on top, remove width padding
|
||||
textRect.adjust(textMargin, iconSize + textMargin + 5, -textMargin, 0);
|
||||
// const int iconSize = style->pixelMetric(QStyle::PM_IconViewIconSize);
|
||||
const int iconSize = 48;
|
||||
QRect iconbox = opt.rect;
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, opt.widget) + 1;
|
||||
QRect textRect = opt.rect;
|
||||
QRect textHighlightRect = textRect;
|
||||
// clip the decoration on top, remove width padding
|
||||
textRect.adjust(textMargin, iconSize + textMargin + 5, -textMargin, 0);
|
||||
|
||||
textHighlightRect.adjust(0, iconSize + 5, 0, 0);
|
||||
textHighlightRect.adjust(0, iconSize + 5, 0, 0);
|
||||
|
||||
// draw background
|
||||
{
|
||||
// FIXME: unused
|
||||
// QSize textSize = viewItemTextSize ( &opt );
|
||||
QPalette::ColorGroup cg;
|
||||
QStyleOptionViewItem opt2(opt);
|
||||
// draw background
|
||||
{
|
||||
// FIXME: unused
|
||||
// QSize textSize = viewItemTextSize ( &opt );
|
||||
QPalette::ColorGroup cg;
|
||||
QStyleOptionViewItem opt2(opt);
|
||||
|
||||
if ((opt.widget && opt.widget->isEnabled()) || (opt.state & QStyle::State_Enabled))
|
||||
{
|
||||
if (!(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
else
|
||||
cg = QPalette::Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cg = QPalette::Disabled;
|
||||
}
|
||||
opt2.palette.setCurrentColorGroup(cg);
|
||||
if ((opt.widget && opt.widget->isEnabled()) || (opt.state & QStyle::State_Enabled))
|
||||
{
|
||||
if (!(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
else
|
||||
cg = QPalette::Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cg = QPalette::Disabled;
|
||||
}
|
||||
opt2.palette.setCurrentColorGroup(cg);
|
||||
|
||||
// fill in background, if any
|
||||
// fill in background, if any
|
||||
|
||||
if (opt.backgroundBrush.style() != Qt::NoBrush)
|
||||
{
|
||||
QPointF oldBO = painter->brushOrigin();
|
||||
painter->setBrushOrigin(opt.rect.topLeft());
|
||||
painter->fillRect(opt.rect, opt.backgroundBrush);
|
||||
painter->setBrushOrigin(oldBO);
|
||||
}
|
||||
if (opt.backgroundBrush.style() != Qt::NoBrush)
|
||||
{
|
||||
QPointF oldBO = painter->brushOrigin();
|
||||
painter->setBrushOrigin(opt.rect.topLeft());
|
||||
painter->fillRect(opt.rect, opt.backgroundBrush);
|
||||
painter->setBrushOrigin(oldBO);
|
||||
}
|
||||
|
||||
drawSelectionRect(painter, opt2, textHighlightRect);
|
||||
drawSelectionRect(painter, opt2, textHighlightRect);
|
||||
|
||||
/*
|
||||
if (opt.showDecorationSelected)
|
||||
{
|
||||
drawSelectionRect(painter, opt2, opt.rect);
|
||||
drawFocusRect(painter, opt2, opt.rect);
|
||||
// painter->fillRect ( opt.rect, opt.palette.brush ( cg, QPalette::Highlight ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (opt.showDecorationSelected)
|
||||
{
|
||||
drawSelectionRect(painter, opt2, opt.rect);
|
||||
drawFocusRect(painter, opt2, opt.rect);
|
||||
// painter->fillRect ( opt.rect, opt.palette.brush ( cg, QPalette::Highlight ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// if ( opt.state & QStyle::State_Selected )
|
||||
{
|
||||
// QRect textRect = subElementRect ( QStyle::SE_ItemViewItemText, opt,
|
||||
// opt.widget );
|
||||
// painter->fillRect ( textHighlightRect, opt.palette.brush ( cg,
|
||||
// QPalette::Highlight ) );
|
||||
drawSelectionRect(painter, opt2, textHighlightRect);
|
||||
drawFocusRect(painter, opt2, textHighlightRect);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
// if ( opt.state & QStyle::State_Selected )
|
||||
{
|
||||
// QRect textRect = subElementRect ( QStyle::SE_ItemViewItemText, opt,
|
||||
// opt.widget );
|
||||
// painter->fillRect ( textHighlightRect, opt.palette.brush ( cg,
|
||||
// QPalette::Highlight ) );
|
||||
drawSelectionRect(painter, opt2, textHighlightRect);
|
||||
drawFocusRect(painter, opt2, textHighlightRect);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// icon mode and state, also used for badges
|
||||
QIcon::Mode mode = QIcon::Normal;
|
||||
if (!(opt.state & QStyle::State_Enabled))
|
||||
mode = QIcon::Disabled;
|
||||
else if (opt.state & QStyle::State_Selected)
|
||||
mode = QIcon::Selected;
|
||||
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
|
||||
// icon mode and state, also used for badges
|
||||
QIcon::Mode mode = QIcon::Normal;
|
||||
if (!(opt.state & QStyle::State_Enabled))
|
||||
mode = QIcon::Disabled;
|
||||
else if (opt.state & QStyle::State_Selected)
|
||||
mode = QIcon::Selected;
|
||||
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
|
||||
|
||||
// draw the icon
|
||||
{
|
||||
iconbox.setHeight(iconSize);
|
||||
opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
// set the text colors
|
||||
QPalette::ColorGroup cg =
|
||||
opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
if (opt.state & QStyle::State_Selected)
|
||||
{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
// draw the icon
|
||||
{
|
||||
iconbox.setHeight(iconSize);
|
||||
opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
|
||||
}
|
||||
// set the text colors
|
||||
QPalette::ColorGroup cg =
|
||||
opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||
if (cg == QPalette::Normal && !(opt.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
if (opt.state & QStyle::State_Selected)
|
||||
{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(opt.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
|
||||
// draw the text
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
textOption.setTextDirection(opt.direction);
|
||||
textOption.setAlignment(QStyle::visualAlignment(opt.direction, opt.displayAlignment));
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setFont(opt.font);
|
||||
textLayout.setText(opt.text);
|
||||
// draw the text
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||
textOption.setTextDirection(opt.direction);
|
||||
textOption.setAlignment(QStyle::visualAlignment(opt.direction, opt.displayAlignment));
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setFont(opt.font);
|
||||
textLayout.setText(opt.text);
|
||||
|
||||
qreal width, height;
|
||||
viewItemTextLayout(textLayout, textRect.width(), height, width);
|
||||
qreal width, height;
|
||||
viewItemTextLayout(textLayout, textRect.width(), height, width);
|
||||
|
||||
const int lineCount = textLayout.lineCount();
|
||||
const int lineCount = textLayout.lineCount();
|
||||
|
||||
const QRect layoutRect = QStyle::alignedRect(
|
||||
opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect);
|
||||
const QPointF position = layoutRect.topLeft();
|
||||
for (int i = 0; i < lineCount; ++i)
|
||||
{
|
||||
const QTextLine line = textLayout.lineAt(i);
|
||||
line.draw(painter, position);
|
||||
}
|
||||
const QRect layoutRect = QStyle::alignedRect(
|
||||
opt.direction, opt.displayAlignment, QSize(textRect.width(), int(height)), textRect);
|
||||
const QPointF position = layoutRect.topLeft();
|
||||
for (int i = 0; i < lineCount; ++i)
|
||||
{
|
||||
const QTextLine line = textLayout.lineAt(i);
|
||||
line.draw(painter, position);
|
||||
}
|
||||
|
||||
// FIXME: this really has no business of being here. Make generic.
|
||||
auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole)
|
||||
.value<void *>();
|
||||
if (instance)
|
||||
{
|
||||
drawBadges(painter, opt, instance, mode, state);
|
||||
}
|
||||
// FIXME: this really has no business of being here. Make generic.
|
||||
auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole)
|
||||
.value<void *>();
|
||||
if (instance)
|
||||
{
|
||||
drawBadges(painter, opt, instance, mode, state);
|
||||
}
|
||||
|
||||
drawProgressOverlay(painter, opt, index.data(GroupViewRoles::ProgressValueRole).toInt(),
|
||||
index.data(GroupViewRoles::ProgressMaximumRole).toInt());
|
||||
drawProgressOverlay(painter, opt, index.data(GroupViewRoles::ProgressValueRole).toInt(),
|
||||
index.data(GroupViewRoles::ProgressMaximumRole).toInt());
|
||||
|
||||
painter->restore();
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.features |= QStyleOptionViewItem::WrapText;
|
||||
opt.text = index.data().toString();
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.features |= QStyleOptionViewItem::WrapText;
|
||||
opt.text = index.data().toString();
|
||||
opt.textElideMode = Qt::ElideRight;
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;
|
||||
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
const int textMargin =
|
||||
style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1;
|
||||
int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables
|
||||
QSize szz = viewItemTextSize(&opt);
|
||||
height += szz.height();
|
||||
// FIXME: maybe the icon items could scale and keep proportions?
|
||||
QSize sz(100, height);
|
||||
return sz;
|
||||
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||
const int textMargin =
|
||||
style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, opt.widget) + 1;
|
||||
int height = 48 + textMargin * 2 + 5; // TODO: turn constants into variables
|
||||
QSize szz = viewItemTextSize(&opt);
|
||||
height += szz.height();
|
||||
// FIXME: maybe the icon items could scale and keep proportions?
|
||||
QSize sz(100, height);
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,10 @@
|
||||
class ListViewDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit ListViewDelegate(QObject *parent = 0);
|
||||
explicit ListViewDelegate(QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
};
|
||||
|
@ -28,290 +28,290 @@ VisualGroup::VisualGroup(const QString &text, GroupView *view) : view(view), tex
|
||||
}
|
||||
|
||||
VisualGroup::VisualGroup(const VisualGroup *other)
|
||||
: view(other->view), text(other->text), collapsed(other->collapsed)
|
||||
: view(other->view), text(other->text), collapsed(other->collapsed)
|
||||
{
|
||||
}
|
||||
|
||||
void VisualGroup::update()
|
||||
{
|
||||
auto temp_items = items();
|
||||
auto itemsPerRow = view->itemsPerRow();
|
||||
auto temp_items = items();
|
||||
auto itemsPerRow = view->itemsPerRow();
|
||||
|
||||
int numRows = qMax(1, qCeil((qreal)temp_items.size() / (qreal)itemsPerRow));
|
||||
rows = QVector<VisualRow>(numRows);
|
||||
int numRows = qMax(1, qCeil((qreal)temp_items.size() / (qreal)itemsPerRow));
|
||||
rows = QVector<VisualRow>(numRows);
|
||||
|
||||
int maxRowHeight = 0;
|
||||
int positionInRow = 0;
|
||||
int currentRow = 0;
|
||||
int offsetFromTop = 0;
|
||||
for (auto item: temp_items)
|
||||
{
|
||||
if(positionInRow == itemsPerRow)
|
||||
{
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
currentRow ++;
|
||||
offsetFromTop += maxRowHeight + 5;
|
||||
positionInRow = 0;
|
||||
maxRowHeight = 0;
|
||||
}
|
||||
auto itemHeight = view->itemDelegate()->sizeHint(view->viewOptions(), item).height();
|
||||
if(itemHeight > maxRowHeight)
|
||||
{
|
||||
maxRowHeight = itemHeight;
|
||||
}
|
||||
rows[currentRow].items.append(item);
|
||||
positionInRow++;
|
||||
}
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
int maxRowHeight = 0;
|
||||
int positionInRow = 0;
|
||||
int currentRow = 0;
|
||||
int offsetFromTop = 0;
|
||||
for (auto item: temp_items)
|
||||
{
|
||||
if(positionInRow == itemsPerRow)
|
||||
{
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
currentRow ++;
|
||||
offsetFromTop += maxRowHeight + 5;
|
||||
positionInRow = 0;
|
||||
maxRowHeight = 0;
|
||||
}
|
||||
auto itemHeight = view->itemDelegate()->sizeHint(view->viewOptions(), item).height();
|
||||
if(itemHeight > maxRowHeight)
|
||||
{
|
||||
maxRowHeight = itemHeight;
|
||||
}
|
||||
rows[currentRow].items.append(item);
|
||||
positionInRow++;
|
||||
}
|
||||
rows[currentRow].height = maxRowHeight;
|
||||
rows[currentRow].top = offsetFromTop;
|
||||
}
|
||||
|
||||
QPair<int, int> VisualGroup::positionOf(const QModelIndex &index) const
|
||||
{
|
||||
int y = 0;
|
||||
for (auto & row: rows)
|
||||
{
|
||||
for(auto x = 0; x < row.items.size(); x++)
|
||||
{
|
||||
if(row.items[x] == index)
|
||||
{
|
||||
return qMakePair(x,y);
|
||||
}
|
||||
}
|
||||
y++;
|
||||
}
|
||||
qWarning() << "Item" << index.row() << index.data(Qt::DisplayRole).toString() << "not found in visual group" << text;
|
||||
return qMakePair(0, 0);
|
||||
int y = 0;
|
||||
for (auto & row: rows)
|
||||
{
|
||||
for(auto x = 0; x < row.items.size(); x++)
|
||||
{
|
||||
if(row.items[x] == index)
|
||||
{
|
||||
return qMakePair(x,y);
|
||||
}
|
||||
}
|
||||
y++;
|
||||
}
|
||||
qWarning() << "Item" << index.row() << index.data(Qt::DisplayRole).toString() << "not found in visual group" << text;
|
||||
return qMakePair(0, 0);
|
||||
}
|
||||
|
||||
int VisualGroup::rowTopOf(const QModelIndex &index) const
|
||||
{
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].top;
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].top;
|
||||
}
|
||||
|
||||
int VisualGroup::rowHeightOf(const QModelIndex &index) const
|
||||
{
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].height;
|
||||
auto position = positionOf(index);
|
||||
return rows[position.second].height;
|
||||
}
|
||||
|
||||
VisualGroup::HitResults VisualGroup::hitScan(const QPoint &pos) const
|
||||
{
|
||||
VisualGroup::HitResults results = VisualGroup::NoHit;
|
||||
int y_start = verticalPosition();
|
||||
int body_start = y_start + headerHeight();
|
||||
int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5?
|
||||
int y = pos.y();
|
||||
// int x = pos.x();
|
||||
if (y < y_start)
|
||||
{
|
||||
results = VisualGroup::NoHit;
|
||||
}
|
||||
else if (y < body_start)
|
||||
{
|
||||
results = VisualGroup::HeaderHit;
|
||||
int collapseSize = headerHeight() - 4;
|
||||
VisualGroup::HitResults results = VisualGroup::NoHit;
|
||||
int y_start = verticalPosition();
|
||||
int body_start = y_start + headerHeight();
|
||||
int body_end = body_start + contentHeight() + 5; // FIXME: wtf is this 5?
|
||||
int y = pos.y();
|
||||
// int x = pos.x();
|
||||
if (y < y_start)
|
||||
{
|
||||
results = VisualGroup::NoHit;
|
||||
}
|
||||
else if (y < body_start)
|
||||
{
|
||||
results = VisualGroup::HeaderHit;
|
||||
int collapseSize = headerHeight() - 4;
|
||||
|
||||
// the icon
|
||||
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize);
|
||||
if (iconRect.contains(pos))
|
||||
{
|
||||
results |= VisualGroup::CheckboxHit;
|
||||
}
|
||||
}
|
||||
else if (y < body_end)
|
||||
{
|
||||
results |= VisualGroup::BodyHit;
|
||||
}
|
||||
return results;
|
||||
// the icon
|
||||
QRect iconRect = QRect(view->m_leftMargin + 2, 2 + y_start, collapseSize, collapseSize);
|
||||
if (iconRect.contains(pos))
|
||||
{
|
||||
results |= VisualGroup::CheckboxHit;
|
||||
}
|
||||
}
|
||||
else if (y < body_end)
|
||||
{
|
||||
results |= VisualGroup::BodyHit;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void VisualGroup::drawHeader(QPainter *painter, const QStyleOptionViewItem &option)
|
||||
{
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
const QRect optRect = option.rect;
|
||||
QFont font(QApplication::font());
|
||||
font.setBold(true);
|
||||
const QFontMetrics fontMetrics = QFontMetrics(font);
|
||||
const QRect optRect = option.rect;
|
||||
QFont font(QApplication::font());
|
||||
font.setBold(true);
|
||||
const QFontMetrics fontMetrics = QFontMetrics(font);
|
||||
|
||||
QColor outlineColor = option.palette.text().color();
|
||||
outlineColor.setAlphaF(0.35);
|
||||
QColor outlineColor = option.palette.text().color();
|
||||
outlineColor.setAlphaF(0.35);
|
||||
|
||||
//BEGIN: top left corner
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(outlineColor);
|
||||
const QPointF topLeft(optRect.topLeft());
|
||||
QRectF arc(topLeft, QSizeF(4, 4));
|
||||
arc.translate(0.5, 0.5);
|
||||
painter->drawArc(arc, 1440, 1440);
|
||||
painter->restore();
|
||||
}
|
||||
//END: top left corner
|
||||
//BEGIN: top left corner
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(outlineColor);
|
||||
const QPointF topLeft(optRect.topLeft());
|
||||
QRectF arc(topLeft, QSizeF(4, 4));
|
||||
arc.translate(0.5, 0.5);
|
||||
painter->drawArc(arc, 1440, 1440);
|
||||
painter->restore();
|
||||
}
|
||||
//END: top left corner
|
||||
|
||||
//BEGIN: left vertical line
|
||||
{
|
||||
QPoint start(optRect.topLeft());
|
||||
start.ry() += 3;
|
||||
QPoint verticalGradBottom(optRect.topLeft());
|
||||
verticalGradBottom.ry() += fontMetrics.height() + 5;
|
||||
QLinearGradient gradient(start, verticalGradBottom);
|
||||
gradient.setColorAt(0, outlineColor);
|
||||
gradient.setColorAt(1, Qt::transparent);
|
||||
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
|
||||
}
|
||||
//END: left vertical line
|
||||
//BEGIN: left vertical line
|
||||
{
|
||||
QPoint start(optRect.topLeft());
|
||||
start.ry() += 3;
|
||||
QPoint verticalGradBottom(optRect.topLeft());
|
||||
verticalGradBottom.ry() += fontMetrics.height() + 5;
|
||||
QLinearGradient gradient(start, verticalGradBottom);
|
||||
gradient.setColorAt(0, outlineColor);
|
||||
gradient.setColorAt(1, Qt::transparent);
|
||||
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
|
||||
}
|
||||
//END: left vertical line
|
||||
|
||||
//BEGIN: horizontal line
|
||||
{
|
||||
QPoint start(optRect.topLeft());
|
||||
start.rx() += 3;
|
||||
QPoint horizontalGradTop(optRect.topLeft());
|
||||
horizontalGradTop.rx() += optRect.width() - 6;
|
||||
painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor);
|
||||
}
|
||||
//END: horizontal line
|
||||
//BEGIN: horizontal line
|
||||
{
|
||||
QPoint start(optRect.topLeft());
|
||||
start.rx() += 3;
|
||||
QPoint horizontalGradTop(optRect.topLeft());
|
||||
horizontalGradTop.rx() += optRect.width() - 6;
|
||||
painter->fillRect(QRect(start, QSize(optRect.width() - 6, 1)), outlineColor);
|
||||
}
|
||||
//END: horizontal line
|
||||
|
||||
//BEGIN: top right corner
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(outlineColor);
|
||||
QPointF topRight(optRect.topRight());
|
||||
topRight.rx() -= 4;
|
||||
QRectF arc(topRight, QSizeF(4, 4));
|
||||
arc.translate(0.5, 0.5);
|
||||
painter->drawArc(arc, 0, 1440);
|
||||
painter->restore();
|
||||
}
|
||||
//END: top right corner
|
||||
//BEGIN: top right corner
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(outlineColor);
|
||||
QPointF topRight(optRect.topRight());
|
||||
topRight.rx() -= 4;
|
||||
QRectF arc(topRight, QSizeF(4, 4));
|
||||
arc.translate(0.5, 0.5);
|
||||
painter->drawArc(arc, 0, 1440);
|
||||
painter->restore();
|
||||
}
|
||||
//END: top right corner
|
||||
|
||||
//BEGIN: right vertical line
|
||||
{
|
||||
QPoint start(optRect.topRight());
|
||||
start.ry() += 3;
|
||||
QPoint verticalGradBottom(optRect.topRight());
|
||||
verticalGradBottom.ry() += fontMetrics.height() + 5;
|
||||
QLinearGradient gradient(start, verticalGradBottom);
|
||||
gradient.setColorAt(0, outlineColor);
|
||||
gradient.setColorAt(1, Qt::transparent);
|
||||
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
|
||||
}
|
||||
//END: right vertical line
|
||||
//BEGIN: right vertical line
|
||||
{
|
||||
QPoint start(optRect.topRight());
|
||||
start.ry() += 3;
|
||||
QPoint verticalGradBottom(optRect.topRight());
|
||||
verticalGradBottom.ry() += fontMetrics.height() + 5;
|
||||
QLinearGradient gradient(start, verticalGradBottom);
|
||||
gradient.setColorAt(0, outlineColor);
|
||||
gradient.setColorAt(1, Qt::transparent);
|
||||
painter->fillRect(QRect(start, QSize(1, fontMetrics.height() + 5)), gradient);
|
||||
}
|
||||
//END: right vertical line
|
||||
|
||||
//BEGIN: checkboxy thing
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
painter->setFont(font);
|
||||
QColor penColor(option.palette.text().color());
|
||||
penColor.setAlphaF(0.6);
|
||||
painter->setPen(penColor);
|
||||
QRect iconSubRect(option.rect);
|
||||
iconSubRect.setTop(iconSubRect.top() + 7);
|
||||
iconSubRect.setLeft(iconSubRect.left() + 7);
|
||||
//BEGIN: checkboxy thing
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
painter->setFont(font);
|
||||
QColor penColor(option.palette.text().color());
|
||||
penColor.setAlphaF(0.6);
|
||||
painter->setPen(penColor);
|
||||
QRect iconSubRect(option.rect);
|
||||
iconSubRect.setTop(iconSubRect.top() + 7);
|
||||
iconSubRect.setLeft(iconSubRect.left() + 7);
|
||||
|
||||
int sizing = fontMetrics.height();
|
||||
int even = ( (sizing - 1) % 2 );
|
||||
int sizing = fontMetrics.height();
|
||||
int even = ( (sizing - 1) % 2 );
|
||||
|
||||
iconSubRect.setHeight(sizing - even);
|
||||
iconSubRect.setWidth(sizing - even);
|
||||
painter->drawRect(iconSubRect);
|
||||
iconSubRect.setHeight(sizing - even);
|
||||
iconSubRect.setWidth(sizing - even);
|
||||
painter->drawRect(iconSubRect);
|
||||
|
||||
|
||||
/*
|
||||
if(collapsed)
|
||||
painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "+");
|
||||
else
|
||||
painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "-");
|
||||
*/
|
||||
painter->setBrush(option.palette.text());
|
||||
painter->fillRect(iconSubRect.x(), iconSubRect.y() + iconSubRect.height() / 2,
|
||||
iconSubRect.width(), 2, penColor);
|
||||
if (collapsed)
|
||||
{
|
||||
painter->fillRect(iconSubRect.x() + iconSubRect.width() / 2, iconSubRect.y(), 2,
|
||||
iconSubRect.height(), penColor);
|
||||
}
|
||||
/*
|
||||
if(collapsed)
|
||||
painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "+");
|
||||
else
|
||||
painter->drawText(iconSubRect, Qt::AlignHCenter | Qt::AlignVCenter, "-");
|
||||
*/
|
||||
painter->setBrush(option.palette.text());
|
||||
painter->fillRect(iconSubRect.x(), iconSubRect.y() + iconSubRect.height() / 2,
|
||||
iconSubRect.width(), 2, penColor);
|
||||
if (collapsed)
|
||||
{
|
||||
painter->fillRect(iconSubRect.x() + iconSubRect.width() / 2, iconSubRect.y(), 2,
|
||||
iconSubRect.height(), penColor);
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
//END: checkboxy thing
|
||||
painter->restore();
|
||||
}
|
||||
//END: checkboxy thing
|
||||
|
||||
//BEGIN: text
|
||||
{
|
||||
QRect textRect(option.rect);
|
||||
textRect.setTop(textRect.top() + 7);
|
||||
textRect.setLeft(textRect.left() + 7 + fontMetrics.height() + 7);
|
||||
textRect.setHeight(fontMetrics.height());
|
||||
textRect.setRight(textRect.right() - 7);
|
||||
//BEGIN: text
|
||||
{
|
||||
QRect textRect(option.rect);
|
||||
textRect.setTop(textRect.top() + 7);
|
||||
textRect.setLeft(textRect.left() + 7 + fontMetrics.height() + 7);
|
||||
textRect.setHeight(fontMetrics.height());
|
||||
textRect.setRight(textRect.right() - 7);
|
||||
|
||||
painter->save();
|
||||
painter->setFont(font);
|
||||
QColor penColor(option.palette.text().color());
|
||||
penColor.setAlphaF(0.6);
|
||||
painter->setPen(penColor);
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
painter->restore();
|
||||
}
|
||||
//END: text
|
||||
painter->save();
|
||||
painter->setFont(font);
|
||||
QColor penColor(option.palette.text().color());
|
||||
penColor.setAlphaF(0.6);
|
||||
painter->setPen(penColor);
|
||||
painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
painter->restore();
|
||||
}
|
||||
//END: text
|
||||
}
|
||||
|
||||
int VisualGroup::totalHeight() const
|
||||
{
|
||||
return headerHeight() + 5 + contentHeight(); // FIXME: wtf is that '5'?
|
||||
return headerHeight() + 5 + contentHeight(); // FIXME: wtf is that '5'?
|
||||
}
|
||||
|
||||
int VisualGroup::headerHeight() const
|
||||
{
|
||||
QFont font(QApplication::font());
|
||||
QFont font(QApplication::font());
|
||||
font.setBold(true);
|
||||
QFontMetrics fontMetrics(font);
|
||||
|
||||
const int height = fontMetrics.height() + 1 /* 1 pixel-width gradient */
|
||||
+ 11 /* top and bottom separation */;
|
||||
return height;
|
||||
/*
|
||||
int raw = view->viewport()->fontMetrics().height() + 4;
|
||||
// add english. maybe. depends on font height.
|
||||
if (raw % 2 == 0)
|
||||
raw++;
|
||||
return std::min(raw, 25);
|
||||
*/
|
||||
/*
|
||||
int raw = view->viewport()->fontMetrics().height() + 4;
|
||||
// add english. maybe. depends on font height.
|
||||
if (raw % 2 == 0)
|
||||
raw++;
|
||||
return std::min(raw, 25);
|
||||
*/
|
||||
}
|
||||
|
||||
int VisualGroup::contentHeight() const
|
||||
{
|
||||
if (collapsed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
auto last = rows[numRows() - 1];
|
||||
return last.top + last.height;
|
||||
if (collapsed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
auto last = rows[numRows() - 1];
|
||||
return last.top + last.height;
|
||||
}
|
||||
|
||||
int VisualGroup::numRows() const
|
||||
{
|
||||
return rows.size();
|
||||
return rows.size();
|
||||
}
|
||||
|
||||
int VisualGroup::verticalPosition() const
|
||||
{
|
||||
return m_verticalPosition;
|
||||
return m_verticalPosition;
|
||||
}
|
||||
|
||||
QList<QModelIndex> VisualGroup::items() const
|
||||
{
|
||||
QList<QModelIndex> indices;
|
||||
for (int i = 0; i < view->model()->rowCount(); ++i)
|
||||
{
|
||||
const QModelIndex index = view->model()->index(i, 0);
|
||||
if (index.data(GroupViewRoles::GroupRole).toString() == text)
|
||||
{
|
||||
indices.append(index);
|
||||
}
|
||||
}
|
||||
return indices;
|
||||
QList<QModelIndex> indices;
|
||||
for (int i = 0; i < view->model()->rowCount(); ++i)
|
||||
{
|
||||
const QModelIndex index = view->model()->index(i, 0);
|
||||
if (index.data(GroupViewRoles::GroupRole).toString() == text)
|
||||
{
|
||||
indices.append(index);
|
||||
}
|
||||
}
|
||||
return indices;
|
||||
}
|
||||
|
@ -26,81 +26,81 @@ class QModelIndex;
|
||||
|
||||
struct VisualRow
|
||||
{
|
||||
QList<QModelIndex> items;
|
||||
int height = 0;
|
||||
int top = 0;
|
||||
inline int size() const
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
inline QModelIndex &operator[](int i)
|
||||
{
|
||||
return items[i];
|
||||
}
|
||||
QList<QModelIndex> items;
|
||||
int height = 0;
|
||||
int top = 0;
|
||||
inline int size() const
|
||||
{
|
||||
return items.size();
|
||||
}
|
||||
inline QModelIndex &operator[](int i)
|
||||
{
|
||||
return items[i];
|
||||
}
|
||||
};
|
||||
|
||||
struct VisualGroup
|
||||
{
|
||||
/* constructors */
|
||||
VisualGroup(const QString &text, GroupView *view);
|
||||
VisualGroup(const VisualGroup *other);
|
||||
VisualGroup(const QString &text, GroupView *view);
|
||||
VisualGroup(const VisualGroup *other);
|
||||
|
||||
/* data */
|
||||
GroupView *view = nullptr;
|
||||
QString text;
|
||||
bool collapsed = false;
|
||||
QVector<VisualRow> rows;
|
||||
int firstItemIndex = 0;
|
||||
int m_verticalPosition = 0;
|
||||
GroupView *view = nullptr;
|
||||
QString text;
|
||||
bool collapsed = false;
|
||||
QVector<VisualRow> rows;
|
||||
int firstItemIndex = 0;
|
||||
int m_verticalPosition = 0;
|
||||
|
||||
/* logic */
|
||||
/// update the internal list of items and flow them into the rows.
|
||||
void update();
|
||||
/// update the internal list of items and flow them into the rows.
|
||||
void update();
|
||||
|
||||
/// draw the header at y-position.
|
||||
void drawHeader(QPainter *painter, const QStyleOptionViewItem &option);
|
||||
/// draw the header at y-position.
|
||||
void drawHeader(QPainter *painter, const QStyleOptionViewItem &option);
|
||||
|
||||
/// height of the group, in total. includes a small bit of padding.
|
||||
int totalHeight() const;
|
||||
/// height of the group, in total. includes a small bit of padding.
|
||||
int totalHeight() const;
|
||||
|
||||
/// height of the group header, in pixels
|
||||
int headerHeight() const;
|
||||
/// height of the group header, in pixels
|
||||
int headerHeight() const;
|
||||
|
||||
/// height of the group content, in pixels
|
||||
int contentHeight() const;
|
||||
/// height of the group content, in pixels
|
||||
int contentHeight() const;
|
||||
|
||||
/// the number of visual rows this group has
|
||||
int numRows() const;
|
||||
/// the number of visual rows this group has
|
||||
int numRows() const;
|
||||
|
||||
/// actually calculate the above value
|
||||
int calculateNumRows() const;
|
||||
/// actually calculate the above value
|
||||
int calculateNumRows() const;
|
||||
|
||||
/// the height at which this group starts, in pixels
|
||||
int verticalPosition() const;
|
||||
/// the height at which this group starts, in pixels
|
||||
int verticalPosition() const;
|
||||
|
||||
/// relative geometry - top of the row of the given item
|
||||
int rowTopOf(const QModelIndex &index) const;
|
||||
/// relative geometry - top of the row of the given item
|
||||
int rowTopOf(const QModelIndex &index) const;
|
||||
|
||||
/// height of the row of the given item
|
||||
int rowHeightOf(const QModelIndex &index) const;
|
||||
/// height of the row of the given item
|
||||
int rowHeightOf(const QModelIndex &index) const;
|
||||
|
||||
/// x/y position of the given item inside the group (in items!)
|
||||
QPair<int, int> positionOf(const QModelIndex &index) const;
|
||||
/// x/y position of the given item inside the group (in items!)
|
||||
QPair<int, int> positionOf(const QModelIndex &index) const;
|
||||
|
||||
enum HitResult
|
||||
{
|
||||
NoHit = 0x0,
|
||||
TextHit = 0x1,
|
||||
CheckboxHit = 0x2,
|
||||
HeaderHit = 0x4,
|
||||
BodyHit = 0x8
|
||||
};
|
||||
Q_DECLARE_FLAGS(HitResults, HitResult)
|
||||
enum HitResult
|
||||
{
|
||||
NoHit = 0x0,
|
||||
TextHit = 0x1,
|
||||
CheckboxHit = 0x2,
|
||||
HeaderHit = 0x4,
|
||||
BodyHit = 0x8
|
||||
};
|
||||
Q_DECLARE_FLAGS(HitResults, HitResult)
|
||||
|
||||
/// shoot! BANG! what did we hit?
|
||||
HitResults hitScan (const QPoint &pos) const;
|
||||
/// shoot! BANG! what did we hit?
|
||||
HitResults hitScan (const QPoint &pos) const;
|
||||
|
||||
QList<QModelIndex> items() const;
|
||||
QList<QModelIndex> items() const;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(VisualGroup::HitResults)
|
||||
|
@ -1,20 +1,20 @@
|
||||
set(CMAKE_MODULE_PATH "@CMAKE_MODULE_PATH@")
|
||||
|
||||
file(GLOB_RECURSE QTPLUGINS "${CMAKE_INSTALL_PREFIX}/@PLUGIN_DEST_DIR@/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
|
||||
file(GLOB_RECURSE QTPLUGINS "${CMAKE_INSTALL_PREFIX}/@PLUGIN_DEST_DIR@/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
|
||||
function(gp_resolved_file_type_override resolved_file type_var)
|
||||
if(resolved_file MATCHES "^/(usr/)?lib/libQt")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libxcb-")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libicu")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libpng")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libproxy")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif((resolved_file MATCHES "^/(usr/)?lib(.+)?/libstdc\\+\\+") AND (UNIX AND NOT APPLE))
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
endif()
|
||||
if(resolved_file MATCHES "^/(usr/)?lib/libQt")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libxcb-")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libicu")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libpng")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif(resolved_file MATCHES "^/(usr/)?lib(.+)?/libproxy")
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
elseif((resolved_file MATCHES "^/(usr/)?lib(.+)?/libstdc\\+\\+") AND (UNIX AND NOT APPLE))
|
||||
set(${type_var} other PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(gp_tool "@CMAKE_GP_TOOL@")
|
||||
|
@ -16,46 +16,46 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef BREAK_INFINITE_LOOP
|
||||
while(true)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
}
|
||||
while(true)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
}
|
||||
#endif
|
||||
#ifdef BREAK_EXCEPTION
|
||||
throw 42;
|
||||
throw 42;
|
||||
#endif
|
||||
#ifdef BREAK_RETURN
|
||||
return 42;
|
||||
return 42;
|
||||
#endif
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
#endif
|
||||
|
||||
// initialize Qt
|
||||
MultiMC app(argc, argv);
|
||||
// initialize Qt
|
||||
MultiMC app(argc, argv);
|
||||
|
||||
switch (app.status())
|
||||
{
|
||||
case MultiMC::StartingUp:
|
||||
case MultiMC::Initialized:
|
||||
{
|
||||
Q_INIT_RESOURCE(multimc);
|
||||
Q_INIT_RESOURCE(backgrounds);
|
||||
Q_INIT_RESOURCE(assets);
|
||||
switch (app.status())
|
||||
{
|
||||
case MultiMC::StartingUp:
|
||||
case MultiMC::Initialized:
|
||||
{
|
||||
Q_INIT_RESOURCE(multimc);
|
||||
Q_INIT_RESOURCE(backgrounds);
|
||||
Q_INIT_RESOURCE(assets);
|
||||
|
||||
Q_INIT_RESOURCE(pe_dark);
|
||||
Q_INIT_RESOURCE(pe_light);
|
||||
Q_INIT_RESOURCE(pe_blue);
|
||||
Q_INIT_RESOURCE(pe_colored);
|
||||
Q_INIT_RESOURCE(OSX);
|
||||
Q_INIT_RESOURCE(iOS);
|
||||
Q_INIT_RESOURCE(flat);
|
||||
return app.exec();
|
||||
}
|
||||
case MultiMC::Failed:
|
||||
return 1;
|
||||
case MultiMC::Succeeded:
|
||||
return 0;
|
||||
}
|
||||
Q_INIT_RESOURCE(pe_dark);
|
||||
Q_INIT_RESOURCE(pe_light);
|
||||
Q_INIT_RESOURCE(pe_blue);
|
||||
Q_INIT_RESOURCE(pe_colored);
|
||||
Q_INIT_RESOURCE(OSX);
|
||||
Q_INIT_RESOURCE(iOS);
|
||||
Q_INIT_RESOURCE(flat);
|
||||
return app.exec();
|
||||
}
|
||||
case MultiMC::Failed:
|
||||
return 1;
|
||||
case MultiMC::Succeeded:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,10 @@
|
||||
# Basic start script for running MultiMC with the libs packaged with it.
|
||||
|
||||
function printerror {
|
||||
printf "$1"
|
||||
if which zenity >/dev/null; then zenity --error --text="$1" &>/dev/null;
|
||||
elif which kdialog >/dev/null; then kdialog --error "$1" &>/dev/null;
|
||||
fi
|
||||
printf "$1"
|
||||
if which zenity >/dev/null; then zenity --error --text="$1" &>/dev/null;
|
||||
elif which kdialog >/dev/null; then kdialog --error "$1" &>/dev/null;
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
@ -28,66 +28,66 @@ export QT_FONTPATH="${MMC_DIR}/fonts"
|
||||
# Detect missing dependencies...
|
||||
DEPS_LIST=`ldd "${MMC_DIR}"/plugins/*/*.so 2>/dev/null | grep "not found" | sort -u | awk -vORS=", " '{ print $1 }'`
|
||||
if [ "x$DEPS_LIST" = "x" ]; then
|
||||
# We have all our dependencies. Run MultiMC.
|
||||
echo "No missing dependencies found."
|
||||
# We have all our dependencies. Run MultiMC.
|
||||
echo "No missing dependencies found."
|
||||
|
||||
# Just to be sure...
|
||||
chmod +x "${MMC_DIR}/bin/MultiMC"
|
||||
# Just to be sure...
|
||||
chmod +x "${MMC_DIR}/bin/MultiMC"
|
||||
|
||||
# Run MultiMC
|
||||
"${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" "$@"
|
||||
# Run MultiMC
|
||||
"${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" "$@"
|
||||
|
||||
# Run MultiMC in valgrind
|
||||
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" "$@"
|
||||
# Run MultiMC in valgrind
|
||||
# valgrind --log-file="valgrind.log" --leak-check=full --track-origins=yes "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" "$@"
|
||||
|
||||
# Run MultiMC with callgrind, delay instrumentation
|
||||
# valgrind --log-file="valgrind.log" --tool=callgrind --instr-atstart=no "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" "$@"
|
||||
# use callgrind_control -i on/off to profile actions
|
||||
# Run MultiMC with callgrind, delay instrumentation
|
||||
# valgrind --log-file="valgrind.log" --tool=callgrind --instr-atstart=no "${MMC_DIR}/bin/MultiMC" -d "${MMC_DIR}" "$@"
|
||||
# use callgrind_control -i on/off to profile actions
|
||||
|
||||
# Exit with MultiMC's exit code.
|
||||
exit $?
|
||||
# Exit with MultiMC's exit code.
|
||||
exit $?
|
||||
else
|
||||
# apt
|
||||
if which apt-file &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do apt-file -l search $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo apt-get install $COMMAND_LIBS"
|
||||
# pacman
|
||||
elif which pkgfile &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pkgfile $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo pacman -S $COMMAND_LIBS"
|
||||
# dnf
|
||||
elif which dnf &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do dnf whatprovides -q $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | grep -v 'Repo' | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo dnf install $COMMAND_LIBS"
|
||||
# yum
|
||||
elif which yum &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do yum whatprovides $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo yum install $COMMAND_LIBS"
|
||||
# zypper
|
||||
elif which zypper &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do zypper wp $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo zypper install $COMMAND_LIBS"
|
||||
# emerge
|
||||
elif which pfl &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pfl $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo emerge $COMMAND_LIBS"
|
||||
fi
|
||||
# apt
|
||||
if which apt-file &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do apt-file -l search $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo apt-get install $COMMAND_LIBS"
|
||||
# pacman
|
||||
elif which pkgfile &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pkgfile $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo pacman -S $COMMAND_LIBS"
|
||||
# dnf
|
||||
elif which dnf &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do dnf whatprovides -q $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | grep -v 'Repo' | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo dnf install $COMMAND_LIBS"
|
||||
# yum
|
||||
elif which yum &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do yum whatprovides $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo yum install $COMMAND_LIBS"
|
||||
# zypper
|
||||
elif which zypper &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do zypper wp $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo zypper install $COMMAND_LIBS"
|
||||
# emerge
|
||||
elif which pfl &>/dev/null; then
|
||||
LIBRARIES=`echo "$DEPS_LIST" | grep -oP "[^, ]*" | sort -u`
|
||||
COMMAND_LIBS=`for LIBRARY in $LIBRARIES; do pfl $LIBRARY; done`
|
||||
COMMAND_LIBS=`echo "$COMMAND_LIBS" | sort -u | awk -vORS=" " '{ print $1 }'`
|
||||
INSTALL_CMD="sudo emerge $COMMAND_LIBS"
|
||||
fi
|
||||
|
||||
MESSAGE="Error: MultiMC is missing the following libraries that it needs to work correctly:\n\t${DEPS_LIST}\nPlease install them from your distribution's package manager."
|
||||
MESSAGE="$MESSAGE\n\nHint (please apply common sense): $INSTALL_CMD\n"
|
||||
MESSAGE="Error: MultiMC is missing the following libraries that it needs to work correctly:\n\t${DEPS_LIST}\nPlease install them from your distribution's package manager."
|
||||
MESSAGE="$MESSAGE\n\nHint (please apply common sense): $INSTALL_CMD\n"
|
||||
|
||||
printerror "$MESSAGE"
|
||||
exit 1
|
||||
printerror "$MESSAGE"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -26,35 +26,35 @@
|
||||
#include "widgets/PageContainer.h"
|
||||
|
||||
PageDialog::PageDialog(BasePageProvider *pageProvider, QString defaultId, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(pageProvider->dialogTitle());
|
||||
m_container = new PageContainer(pageProvider, defaultId, this);
|
||||
setWindowTitle(pageProvider->dialogTitle());
|
||||
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);
|
||||
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);
|
||||
m_container->addButtons(buttons);
|
||||
QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close);
|
||||
buttons->button(QDialogButtonBox::Close)->setDefault(true);
|
||||
m_container->addButtons(buttons);
|
||||
|
||||
connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close()));
|
||||
connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), m_container, SLOT(help()));
|
||||
connect(buttons->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close()));
|
||||
connect(buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()), m_container, SLOT(help()));
|
||||
|
||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray()));
|
||||
restoreGeometry(QByteArray::fromBase64(MMC->settings()->get("PagedGeometry").toByteArray()));
|
||||
}
|
||||
|
||||
void PageDialog::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
qDebug() << "Paged dialog close requested";
|
||||
if (m_container->prepareToClose())
|
||||
{
|
||||
qDebug() << "Paged dialog close approved";
|
||||
MMC->settings()->set("PagedGeometry", saveGeometry().toBase64());
|
||||
qDebug() << "Paged dialog geometry saved";
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
qDebug() << "Paged dialog close requested";
|
||||
if (m_container->prepareToClose())
|
||||
{
|
||||
qDebug() << "Paged dialog close approved";
|
||||
MMC->settings()->set("PagedGeometry", saveGeometry().toBase64());
|
||||
qDebug() << "Paged dialog geometry saved";
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
}
|
||||
|
@ -21,15 +21,15 @@
|
||||
class PageContainer;
|
||||
class PageDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PageDialog(BasePageProvider *pageProvider, QString defaultId = QString(), QWidget *parent = 0);
|
||||
virtual ~PageDialog() {}
|
||||
explicit PageDialog(BasePageProvider *pageProvider, QString defaultId = QString(), QWidget *parent = 0);
|
||||
virtual ~PageDialog() {}
|
||||
|
||||
private
|
||||
slots:
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
|
||||
private:
|
||||
PageContainer * m_container;
|
||||
PageContainer * m_container;
|
||||
};
|
||||
|
@ -24,35 +24,35 @@
|
||||
class BasePage
|
||||
{
|
||||
public:
|
||||
virtual ~BasePage() {}
|
||||
virtual QString id() const = 0;
|
||||
virtual QString displayName() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
virtual bool apply() { return true; }
|
||||
virtual bool shouldDisplay() const { return true; }
|
||||
virtual QString helpPage() const { return QString(); }
|
||||
void opened()
|
||||
{
|
||||
isOpened = true;
|
||||
openedImpl();
|
||||
}
|
||||
void closed()
|
||||
{
|
||||
isOpened = false;
|
||||
closedImpl();
|
||||
}
|
||||
virtual void openedImpl() {}
|
||||
virtual void closedImpl() {}
|
||||
virtual void setParentContainer(BasePageContainer * container)
|
||||
{
|
||||
m_container = container;
|
||||
};
|
||||
virtual ~BasePage() {}
|
||||
virtual QString id() const = 0;
|
||||
virtual QString displayName() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
virtual bool apply() { return true; }
|
||||
virtual bool shouldDisplay() const { return true; }
|
||||
virtual QString helpPage() const { return QString(); }
|
||||
void opened()
|
||||
{
|
||||
isOpened = true;
|
||||
openedImpl();
|
||||
}
|
||||
void closed()
|
||||
{
|
||||
isOpened = false;
|
||||
closedImpl();
|
||||
}
|
||||
virtual void openedImpl() {}
|
||||
virtual void closedImpl() {}
|
||||
virtual void setParentContainer(BasePageContainer * container)
|
||||
{
|
||||
m_container = container;
|
||||
};
|
||||
public:
|
||||
int stackIndex = -1;
|
||||
int listIndex = -1;
|
||||
int stackIndex = -1;
|
||||
int listIndex = -1;
|
||||
protected:
|
||||
BasePageContainer * m_container = nullptr;
|
||||
bool isOpened = false;
|
||||
BasePageContainer * m_container = nullptr;
|
||||
bool isOpened = false;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<BasePage> BasePagePtr;
|
||||
|
@ -3,8 +3,8 @@
|
||||
class BasePageContainer
|
||||
{
|
||||
public:
|
||||
virtual ~BasePageContainer(){};
|
||||
virtual bool selectPage(QString pageId) = 0;
|
||||
virtual void refreshContainer() = 0;
|
||||
virtual bool requestClose() = 0;
|
||||
virtual ~BasePageContainer(){};
|
||||
virtual bool selectPage(QString pageId) = 0;
|
||||
virtual void refreshContainer() = 0;
|
||||
virtual bool requestClose() = 0;
|
||||
};
|
||||
|
@ -22,47 +22,47 @@
|
||||
class BasePageProvider
|
||||
{
|
||||
public:
|
||||
virtual QList<BasePage *> getPages() = 0;
|
||||
virtual QString dialogTitle() = 0;
|
||||
virtual QList<BasePage *> getPages() = 0;
|
||||
virtual QString dialogTitle() = 0;
|
||||
};
|
||||
|
||||
class GenericPageProvider : public BasePageProvider
|
||||
{
|
||||
typedef std::function<BasePage *()> PageCreator;
|
||||
typedef std::function<BasePage *()> PageCreator;
|
||||
public:
|
||||
explicit GenericPageProvider(const QString &dialogTitle)
|
||||
: m_dialogTitle(dialogTitle)
|
||||
{
|
||||
}
|
||||
virtual ~GenericPageProvider() {}
|
||||
explicit GenericPageProvider(const QString &dialogTitle)
|
||||
: m_dialogTitle(dialogTitle)
|
||||
{
|
||||
}
|
||||
virtual ~GenericPageProvider() {}
|
||||
|
||||
QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> pages;
|
||||
for (PageCreator creator : m_creators)
|
||||
{
|
||||
pages.append(creator());
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
QString dialogTitle() override { return m_dialogTitle; }
|
||||
QList<BasePage *> getPages() override
|
||||
{
|
||||
QList<BasePage *> pages;
|
||||
for (PageCreator creator : m_creators)
|
||||
{
|
||||
pages.append(creator());
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
QString dialogTitle() override { return m_dialogTitle; }
|
||||
|
||||
void setDialogTitle(const QString &title)
|
||||
{
|
||||
m_dialogTitle = title;
|
||||
}
|
||||
void addPageCreator(PageCreator page)
|
||||
{
|
||||
m_creators.append(page);
|
||||
}
|
||||
void setDialogTitle(const QString &title)
|
||||
{
|
||||
m_dialogTitle = title;
|
||||
}
|
||||
void addPageCreator(PageCreator page)
|
||||
{
|
||||
m_creators.append(page);
|
||||
}
|
||||
|
||||
template<typename PageClass>
|
||||
void addPage()
|
||||
{
|
||||
addPageCreator([](){return new PageClass();});
|
||||
}
|
||||
template<typename PageClass>
|
||||
void addPage()
|
||||
{
|
||||
addPageCreator([](){return new PageClass();});
|
||||
}
|
||||
|
||||
private:
|
||||
QList<PageCreator> m_creators;
|
||||
QString m_dialogTitle;
|
||||
QList<PageCreator> m_creators;
|
||||
QString m_dialogTitle;
|
||||
};
|
||||
|
@ -34,120 +34,120 @@
|
||||
#include "MultiMC.h"
|
||||
|
||||
AccountListPage::AccountListPage(QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::AccountListPage)
|
||||
: QWidget(parent), ui(new Ui::AccountListPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_accounts = MMC->accounts();
|
||||
m_accounts = MMC->accounts();
|
||||
|
||||
ui->listView->setModel(m_accounts.get());
|
||||
ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
ui->listView->setModel(m_accounts.get());
|
||||
ui->listView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
// Expand the account column
|
||||
ui->listView->header()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
// Expand the account column
|
||||
ui->listView->header()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
|
||||
QItemSelectionModel *selectionModel = ui->listView->selectionModel();
|
||||
QItemSelectionModel *selectionModel = ui->listView->selectionModel();
|
||||
|
||||
connect(selectionModel, &QItemSelectionModel::selectionChanged,
|
||||
[this](const QItemSelection &sel, const QItemSelection &dsel)
|
||||
{ updateButtonStates(); });
|
||||
connect(selectionModel, &QItemSelectionModel::selectionChanged,
|
||||
[this](const QItemSelection &sel, const QItemSelection &dsel)
|
||||
{ updateButtonStates(); });
|
||||
|
||||
connect(m_accounts.get(), SIGNAL(listChanged()), SLOT(listChanged()));
|
||||
connect(m_accounts.get(), SIGNAL(activeAccountChanged()), SLOT(listChanged()));
|
||||
connect(m_accounts.get(), SIGNAL(listChanged()), SLOT(listChanged()));
|
||||
connect(m_accounts.get(), SIGNAL(activeAccountChanged()), SLOT(listChanged()));
|
||||
|
||||
updateButtonStates();
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
AccountListPage::~AccountListPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AccountListPage::listChanged()
|
||||
{
|
||||
updateButtonStates();
|
||||
updateButtonStates();
|
||||
}
|
||||
|
||||
void AccountListPage::on_addAccountBtn_clicked()
|
||||
{
|
||||
addAccount(tr("Please enter your Mojang or Minecraft account username and password to add "
|
||||
"your account."));
|
||||
addAccount(tr("Please enter your Mojang or Minecraft account username and password to add "
|
||||
"your account."));
|
||||
}
|
||||
|
||||
void AccountListPage::on_rmAccountBtn_clicked()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
m_accounts->removeAccount(selected);
|
||||
}
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
m_accounts->removeAccount(selected);
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_setDefaultBtn_clicked()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MojangAccountPtr account =
|
||||
selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
m_accounts->setActiveAccount(account->username());
|
||||
}
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MojangAccountPtr account =
|
||||
selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
m_accounts->setActiveAccount(account->username());
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_noDefaultBtn_clicked()
|
||||
{
|
||||
m_accounts->setActiveAccount("");
|
||||
m_accounts->setActiveAccount("");
|
||||
}
|
||||
|
||||
void AccountListPage::updateButtonStates()
|
||||
{
|
||||
// If there is no selection, disable buttons that require something selected.
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
// If there is no selection, disable buttons that require something selected.
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
|
||||
ui->rmAccountBtn->setEnabled(selection.size() > 0);
|
||||
ui->setDefaultBtn->setEnabled(selection.size() > 0);
|
||||
ui->uploadSkinBtn->setEnabled(selection.size() > 0);
|
||||
ui->rmAccountBtn->setEnabled(selection.size() > 0);
|
||||
ui->setDefaultBtn->setEnabled(selection.size() > 0);
|
||||
ui->uploadSkinBtn->setEnabled(selection.size() > 0);
|
||||
|
||||
ui->noDefaultBtn->setDown(m_accounts->activeAccount().get() == nullptr);
|
||||
ui->noDefaultBtn->setDown(m_accounts->activeAccount().get() == nullptr);
|
||||
}
|
||||
|
||||
void AccountListPage::addAccount(const QString &errMsg)
|
||||
{
|
||||
// TODO: The login dialog isn't quite done yet
|
||||
MojangAccountPtr account = LoginDialog::newAccount(this, errMsg);
|
||||
// TODO: The login dialog isn't quite done yet
|
||||
MojangAccountPtr account = LoginDialog::newAccount(this, errMsg);
|
||||
|
||||
if (account != nullptr)
|
||||
{
|
||||
m_accounts->addAccount(account);
|
||||
if (m_accounts->count() == 1)
|
||||
m_accounts->setActiveAccount(account->username());
|
||||
if (account != nullptr)
|
||||
{
|
||||
m_accounts->addAccount(account);
|
||||
if (m_accounts->count() == 1)
|
||||
m_accounts->setActiveAccount(account->username());
|
||||
|
||||
// Grab associated player skins
|
||||
auto job = new NetJob("Player skins: " + account->username());
|
||||
// Grab associated player skins
|
||||
auto job = new NetJob("Player skins: " + account->username());
|
||||
|
||||
for (AccountProfile profile : account->profiles())
|
||||
{
|
||||
auto meta = Env::getInstance().metacache()->resolveEntry("skins", profile.id + ".png");
|
||||
auto action = Net::Download::makeCached(QUrl("https://" + URLConstants::SKINS_BASE + profile.id + ".png"), meta);
|
||||
job->addNetAction(action);
|
||||
meta->setStale(true);
|
||||
}
|
||||
for (AccountProfile profile : account->profiles())
|
||||
{
|
||||
auto meta = Env::getInstance().metacache()->resolveEntry("skins", profile.id + ".png");
|
||||
auto action = Net::Download::makeCached(QUrl("https://" + URLConstants::SKINS_BASE + profile.id + ".png"), meta);
|
||||
job->addNetAction(action);
|
||||
meta->setStale(true);
|
||||
}
|
||||
|
||||
job->start();
|
||||
}
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
|
||||
void AccountListPage::on_uploadSkinBtn_clicked()
|
||||
{
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
SkinUploadDialog dialog(account, this);
|
||||
dialog.exec();
|
||||
}
|
||||
QModelIndexList selection = ui->listView->selectionModel()->selectedIndexes();
|
||||
if (selection.size() > 0)
|
||||
{
|
||||
QModelIndex selected = selection.first();
|
||||
MojangAccountPtr account = selected.data(MojangAccountList::PointerRole).value<MojangAccountPtr>();
|
||||
SkinUploadDialog dialog(account, this);
|
||||
dialog.exec();
|
||||
}
|
||||
}
|
||||
|
@ -32,57 +32,57 @@ class AuthenticateTask;
|
||||
|
||||
class AccountListPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AccountListPage(QWidget *parent = 0);
|
||||
~AccountListPage();
|
||||
explicit AccountListPage(QWidget *parent = 0);
|
||||
~AccountListPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Accounts");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
auto icon = MMC->getThemedIcon("accounts");
|
||||
if(icon.isNull())
|
||||
{
|
||||
icon = MMC->getThemedIcon("noaccount");
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "accounts";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Getting-Started#adding-an-account";
|
||||
}
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Accounts");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
auto icon = MMC->getThemedIcon("accounts");
|
||||
if(icon.isNull())
|
||||
{
|
||||
icon = MMC->getThemedIcon("noaccount");
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "accounts";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Getting-Started#adding-an-account";
|
||||
}
|
||||
|
||||
public
|
||||
slots:
|
||||
void on_addAccountBtn_clicked();
|
||||
void on_addAccountBtn_clicked();
|
||||
|
||||
void on_rmAccountBtn_clicked();
|
||||
void on_rmAccountBtn_clicked();
|
||||
|
||||
void on_setDefaultBtn_clicked();
|
||||
void on_setDefaultBtn_clicked();
|
||||
|
||||
void on_noDefaultBtn_clicked();
|
||||
void on_noDefaultBtn_clicked();
|
||||
|
||||
void on_uploadSkinBtn_clicked();
|
||||
void on_uploadSkinBtn_clicked();
|
||||
|
||||
void listChanged();
|
||||
void listChanged();
|
||||
|
||||
//! Updates the states of the dialog's buttons.
|
||||
void updateButtonStates();
|
||||
//! Updates the states of the dialog's buttons.
|
||||
void updateButtonStates();
|
||||
|
||||
protected:
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
std::shared_ptr<MojangAccountList> m_accounts;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void addAccount(const QString& errMsg="");
|
||||
void addAccount(const QString& errMsg="");
|
||||
|
||||
private:
|
||||
Ui::AccountListPage *ui;
|
||||
Ui::AccountListPage *ui;
|
||||
};
|
||||
|
@ -6,17 +6,17 @@
|
||||
CustomCommandsPage::CustomCommandsPage(QWidget* parent): QWidget(parent)
|
||||
{
|
||||
|
||||
auto verticalLayout = new QVBoxLayout(this);
|
||||
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
|
||||
verticalLayout->setContentsMargins(0, 0, 0, 0);
|
||||
auto verticalLayout = new QVBoxLayout(this);
|
||||
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
|
||||
verticalLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
auto tabWidget = new QTabWidget(this);
|
||||
tabWidget->setObjectName(QStringLiteral("tabWidget"));
|
||||
commands = new CustomCommands(this);
|
||||
tabWidget->addTab(commands, "Foo");
|
||||
tabWidget->tabBar()->hide();
|
||||
verticalLayout->addWidget(tabWidget);
|
||||
loadSettings();
|
||||
auto tabWidget = new QTabWidget(this);
|
||||
tabWidget->setObjectName(QStringLiteral("tabWidget"));
|
||||
commands = new CustomCommands(this);
|
||||
tabWidget->addTab(commands, "Foo");
|
||||
tabWidget->tabBar()->hide();
|
||||
verticalLayout->addWidget(tabWidget);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
CustomCommandsPage::~CustomCommandsPage()
|
||||
@ -25,26 +25,26 @@ CustomCommandsPage::~CustomCommandsPage()
|
||||
|
||||
bool CustomCommandsPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CustomCommandsPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
s->set("PreLaunchCommand", commands->prelaunchCommand());
|
||||
s->set("WrapperCommand", commands->wrapperCommand());
|
||||
s->set("PostExitCommand", commands->postexitCommand());
|
||||
auto s = MMC->settings();
|
||||
s->set("PreLaunchCommand", commands->prelaunchCommand());
|
||||
s->set("WrapperCommand", commands->wrapperCommand());
|
||||
s->set("PostExitCommand", commands->postexitCommand());
|
||||
}
|
||||
|
||||
void CustomCommandsPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
commands->initialize(
|
||||
false,
|
||||
true,
|
||||
s->get("PreLaunchCommand").toString(),
|
||||
s->get("WrapperCommand").toString(),
|
||||
s->get("PostExitCommand").toString()
|
||||
);
|
||||
auto s = MMC->settings();
|
||||
commands->initialize(
|
||||
false,
|
||||
true,
|
||||
s->get("PreLaunchCommand").toString(),
|
||||
s->get("WrapperCommand").toString(),
|
||||
s->get("PostExitCommand").toString()
|
||||
);
|
||||
}
|
||||
|
@ -24,32 +24,32 @@
|
||||
|
||||
class CustomCommandsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CustomCommandsPage(QWidget *parent = 0);
|
||||
~CustomCommandsPage();
|
||||
explicit CustomCommandsPage(QWidget *parent = 0);
|
||||
~CustomCommandsPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Custom Commands");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("custom-commands");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "custom-commands";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Custom-commands";
|
||||
}
|
||||
bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Custom Commands");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("custom-commands");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "custom-commands";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Custom-commands";
|
||||
}
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
CustomCommands * commands;
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
CustomCommands * commands;
|
||||
};
|
||||
|
@ -28,206 +28,206 @@
|
||||
#include <tools/MCEditTool.h>
|
||||
|
||||
ExternalToolsPage::ExternalToolsPage(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExternalToolsPage)
|
||||
QWidget(parent),
|
||||
ui(new Ui::ExternalToolsPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
ui->jsonEditorTextBox->setClearButtonEnabled(true);
|
||||
#endif
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
|
||||
ui->jsonEditorTextBox->setClearButtonEnabled(true);
|
||||
#endif
|
||||
|
||||
ui->mceditLink->setOpenExternalLinks(true);
|
||||
ui->jvisualvmLink->setOpenExternalLinks(true);
|
||||
ui->jprofilerLink->setOpenExternalLinks(true);
|
||||
loadSettings();
|
||||
ui->mceditLink->setOpenExternalLinks(true);
|
||||
ui->jvisualvmLink->setOpenExternalLinks(true);
|
||||
ui->jprofilerLink->setOpenExternalLinks(true);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
ExternalToolsPage::~ExternalToolsPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ExternalToolsPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
ui->jprofilerPathEdit->setText(s->get("JProfilerPath").toString());
|
||||
ui->jvisualvmPathEdit->setText(s->get("JVisualVMPath").toString());
|
||||
ui->mceditPathEdit->setText(s->get("MCEditPath").toString());
|
||||
auto s = MMC->settings();
|
||||
ui->jprofilerPathEdit->setText(s->get("JProfilerPath").toString());
|
||||
ui->jvisualvmPathEdit->setText(s->get("JVisualVMPath").toString());
|
||||
ui->mceditPathEdit->setText(s->get("MCEditPath").toString());
|
||||
|
||||
// Editors
|
||||
ui->jsonEditorTextBox->setText(s->get("JsonEditor").toString());
|
||||
// Editors
|
||||
ui->jsonEditorTextBox->setText(s->get("JsonEditor").toString());
|
||||
}
|
||||
void ExternalToolsPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
s->set("JProfilerPath", ui->jprofilerPathEdit->text());
|
||||
s->set("JVisualVMPath", ui->jvisualvmPathEdit->text());
|
||||
s->set("MCEditPath", ui->mceditPathEdit->text());
|
||||
s->set("JProfilerPath", ui->jprofilerPathEdit->text());
|
||||
s->set("JVisualVMPath", ui->jvisualvmPathEdit->text());
|
||||
s->set("MCEditPath", ui->mceditPathEdit->text());
|
||||
|
||||
// Editors
|
||||
QString jsonEditor = ui->jsonEditorTextBox->text();
|
||||
if (!jsonEditor.isEmpty() &&
|
||||
(!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable()))
|
||||
{
|
||||
QString found = QStandardPaths::findExecutable(jsonEditor);
|
||||
if (!found.isEmpty())
|
||||
{
|
||||
jsonEditor = found;
|
||||
}
|
||||
}
|
||||
s->set("JsonEditor", jsonEditor);
|
||||
// Editors
|
||||
QString jsonEditor = ui->jsonEditorTextBox->text();
|
||||
if (!jsonEditor.isEmpty() &&
|
||||
(!QFileInfo(jsonEditor).exists() || !QFileInfo(jsonEditor).isExecutable()))
|
||||
{
|
||||
QString found = QStandardPaths::findExecutable(jsonEditor);
|
||||
if (!found.isEmpty())
|
||||
{
|
||||
jsonEditor = found;
|
||||
}
|
||||
}
|
||||
s->set("JsonEditor", jsonEditor);
|
||||
}
|
||||
|
||||
void ExternalToolsPage::on_jprofilerPathBtn_clicked()
|
||||
{
|
||||
QString raw_dir = ui->jprofilerPathEdit->text();
|
||||
QString error;
|
||||
do
|
||||
{
|
||||
raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler Folder"), raw_dir);
|
||||
if (raw_dir.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (!MMC->profilers()["jprofiler"]->check(cooked_dir, &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->jprofilerPathEdit->setText(cooked_dir);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
QString raw_dir = ui->jprofilerPathEdit->text();
|
||||
QString error;
|
||||
do
|
||||
{
|
||||
raw_dir = QFileDialog::getExistingDirectory(this, tr("JProfiler Folder"), raw_dir);
|
||||
if (raw_dir.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (!MMC->profilers()["jprofiler"]->check(cooked_dir, &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->jprofilerPathEdit->setText(cooked_dir);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
void ExternalToolsPage::on_jprofilerCheckBtn_clicked()
|
||||
{
|
||||
QString error;
|
||||
if (!MMC->profilers()["jprofiler"]->check(ui->jprofilerPathEdit->text(), &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("OK"), tr("JProfiler setup seems to be OK"));
|
||||
}
|
||||
QString error;
|
||||
if (!MMC->profilers()["jprofiler"]->check(ui->jprofilerPathEdit->text(), &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JProfiler install:\n%1").arg(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("OK"), tr("JProfiler setup seems to be OK"));
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalToolsPage::on_jvisualvmPathBtn_clicked()
|
||||
{
|
||||
QString raw_dir = ui->jvisualvmPathEdit->text();
|
||||
QString error;
|
||||
do
|
||||
{
|
||||
raw_dir = QFileDialog::getOpenFileName(this, tr("JVisualVM Executable"), raw_dir);
|
||||
if (raw_dir.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (!MMC->profilers()["jvisualvm"]->check(cooked_dir, &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->jvisualvmPathEdit->setText(cooked_dir);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
QString raw_dir = ui->jvisualvmPathEdit->text();
|
||||
QString error;
|
||||
do
|
||||
{
|
||||
raw_dir = QFileDialog::getOpenFileName(this, tr("JVisualVM Executable"), raw_dir);
|
||||
if (raw_dir.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (!MMC->profilers()["jvisualvm"]->check(cooked_dir, &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->jvisualvmPathEdit->setText(cooked_dir);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
void ExternalToolsPage::on_jvisualvmCheckBtn_clicked()
|
||||
{
|
||||
QString error;
|
||||
if (!MMC->profilers()["jvisualvm"]->check(ui->jvisualvmPathEdit->text(), &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("OK"), tr("JVisualVM setup seems to be OK"));
|
||||
}
|
||||
QString error;
|
||||
if (!MMC->profilers()["jvisualvm"]->check(ui->jvisualvmPathEdit->text(), &error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking JVisualVM install:\n%1").arg(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("OK"), tr("JVisualVM setup seems to be OK"));
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalToolsPage::on_mceditPathBtn_clicked()
|
||||
{
|
||||
QString raw_dir = ui->mceditPathEdit->text();
|
||||
QString error;
|
||||
do
|
||||
{
|
||||
QString raw_dir = ui->mceditPathEdit->text();
|
||||
QString error;
|
||||
do
|
||||
{
|
||||
#ifdef Q_OS_OSX
|
||||
raw_dir = QFileDialog::getOpenFileName(this, tr("MCEdit Application"), raw_dir);
|
||||
raw_dir = QFileDialog::getOpenFileName(this, tr("MCEdit Application"), raw_dir);
|
||||
#else
|
||||
raw_dir = QFileDialog::getExistingDirectory(this, tr("MCEdit Folder"), raw_dir);
|
||||
raw_dir = QFileDialog::getExistingDirectory(this, tr("MCEdit Folder"), raw_dir);
|
||||
#endif
|
||||
if (raw_dir.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (!MMC->mcedit()->check(cooked_dir, error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->mceditPathEdit->setText(cooked_dir);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
if (raw_dir.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (!MMC->mcedit()->check(cooked_dir, error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->mceditPathEdit->setText(cooked_dir);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
void ExternalToolsPage::on_mceditCheckBtn_clicked()
|
||||
{
|
||||
QString error;
|
||||
if (!MMC->mcedit()->check(ui->mceditPathEdit->text(), error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("OK"), tr("MCEdit setup seems to be OK"));
|
||||
}
|
||||
QString error;
|
||||
if (!MMC->mcedit()->check(ui->mceditPathEdit->text(), error))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Error while checking MCEdit install:\n%1").arg(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("OK"), tr("MCEdit setup seems to be OK"));
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalToolsPage::on_jsonEditorBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_file = QFileDialog::getOpenFileName(
|
||||
this, tr("JSON Editor"),
|
||||
ui->jsonEditorTextBox->text().isEmpty()
|
||||
QString raw_file = QFileDialog::getOpenFileName(
|
||||
this, tr("JSON Editor"),
|
||||
ui->jsonEditorTextBox->text().isEmpty()
|
||||
#if defined(Q_OS_LINUX)
|
||||
? QString("/usr/bin")
|
||||
? QString("/usr/bin")
|
||||
#else
|
||||
? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first()
|
||||
? QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).first()
|
||||
#endif
|
||||
: ui->jsonEditorTextBox->text());
|
||||
: ui->jsonEditorTextBox->text());
|
||||
|
||||
if (raw_file.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString cooked_file = FS::NormalizePath(raw_file);
|
||||
if (raw_file.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString cooked_file = FS::NormalizePath(raw_file);
|
||||
|
||||
// it has to exist and be an executable
|
||||
if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable())
|
||||
{
|
||||
ui->jsonEditorTextBox->setText(cooked_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Invalid"),
|
||||
tr("The file chosen does not seem to be an executable"));
|
||||
}
|
||||
// it has to exist and be an executable
|
||||
if (QFileInfo(cooked_file).exists() && QFileInfo(cooked_file).isExecutable())
|
||||
{
|
||||
ui->jsonEditorTextBox->setText(cooked_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this, tr("Invalid"),
|
||||
tr("The file chosen does not seem to be an executable"));
|
||||
}
|
||||
}
|
||||
|
||||
bool ExternalToolsPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
@ -26,49 +26,49 @@ class ExternalToolsPage;
|
||||
|
||||
class ExternalToolsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExternalToolsPage(QWidget *parent = 0);
|
||||
~ExternalToolsPage();
|
||||
explicit ExternalToolsPage(QWidget *parent = 0);
|
||||
~ExternalToolsPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("External Tools");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
auto icon = MMC->getThemedIcon("externaltools");
|
||||
if(icon.isNull())
|
||||
{
|
||||
icon = MMC->getThemedIcon("loadermods");
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "external-tools";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Tools";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("External Tools");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
auto icon = MMC->getThemedIcon("externaltools");
|
||||
if(icon.isNull())
|
||||
{
|
||||
icon = MMC->getThemedIcon("loadermods");
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "external-tools";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Tools";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
|
||||
private:
|
||||
Ui::ExternalToolsPage *ui;
|
||||
Ui::ExternalToolsPage *ui;
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_jprofilerPathBtn_clicked();
|
||||
void on_jprofilerCheckBtn_clicked();
|
||||
void on_jvisualvmPathBtn_clicked();
|
||||
void on_jvisualvmCheckBtn_clicked();
|
||||
void on_mceditPathBtn_clicked();
|
||||
void on_mceditCheckBtn_clicked();
|
||||
void on_jsonEditorBrowseBtn_clicked();
|
||||
void on_jprofilerPathBtn_clicked();
|
||||
void on_jprofilerCheckBtn_clicked();
|
||||
void on_jvisualvmPathBtn_clicked();
|
||||
void on_jvisualvmCheckBtn_clicked();
|
||||
void on_mceditPathBtn_clicked();
|
||||
void on_mceditCheckBtn_clicked();
|
||||
void on_jsonEditorBrowseBtn_clicked();
|
||||
};
|
||||
|
@ -34,120 +34,120 @@
|
||||
|
||||
JavaPage::JavaPage(QWidget *parent) : QWidget(parent), ui(new Ui::JavaPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
auto sysMB = Sys::getSystemRam() / Sys::megabyte;
|
||||
ui->maxMemSpinBox->setMaximum(sysMB);
|
||||
loadSettings();
|
||||
auto sysMB = Sys::getSystemRam() / Sys::megabyte;
|
||||
ui->maxMemSpinBox->setMaximum(sysMB);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
JavaPage::~JavaPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool JavaPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void JavaPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
// Memory
|
||||
int min = ui->minMemSpinBox->value();
|
||||
int max = ui->maxMemSpinBox->value();
|
||||
if(min < max)
|
||||
{
|
||||
s->set("MinMemAlloc", min);
|
||||
s->set("MaxMemAlloc", max);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->set("MinMemAlloc", max);
|
||||
s->set("MaxMemAlloc", min);
|
||||
}
|
||||
s->set("PermGen", ui->permGenSpinBox->value());
|
||||
// Memory
|
||||
int min = ui->minMemSpinBox->value();
|
||||
int max = ui->maxMemSpinBox->value();
|
||||
if(min < max)
|
||||
{
|
||||
s->set("MinMemAlloc", min);
|
||||
s->set("MaxMemAlloc", max);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->set("MinMemAlloc", max);
|
||||
s->set("MaxMemAlloc", min);
|
||||
}
|
||||
s->set("PermGen", ui->permGenSpinBox->value());
|
||||
|
||||
// Java Settings
|
||||
s->set("JavaPath", ui->javaPathTextBox->text());
|
||||
s->set("JvmArgs", ui->jvmArgsTextBox->text());
|
||||
JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
|
||||
// Java Settings
|
||||
s->set("JavaPath", ui->javaPathTextBox->text());
|
||||
s->set("JvmArgs", ui->jvmArgsTextBox->text());
|
||||
JavaCommon::checkJVMArgs(s->get("JvmArgs").toString(), this->parentWidget());
|
||||
}
|
||||
void JavaPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
// Memory
|
||||
int min = s->get("MinMemAlloc").toInt();
|
||||
int max = s->get("MaxMemAlloc").toInt();
|
||||
if(min < max)
|
||||
{
|
||||
ui->minMemSpinBox->setValue(min);
|
||||
ui->maxMemSpinBox->setValue(max);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->minMemSpinBox->setValue(max);
|
||||
ui->maxMemSpinBox->setValue(min);
|
||||
}
|
||||
ui->permGenSpinBox->setValue(s->get("PermGen").toInt());
|
||||
auto s = MMC->settings();
|
||||
// Memory
|
||||
int min = s->get("MinMemAlloc").toInt();
|
||||
int max = s->get("MaxMemAlloc").toInt();
|
||||
if(min < max)
|
||||
{
|
||||
ui->minMemSpinBox->setValue(min);
|
||||
ui->maxMemSpinBox->setValue(max);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->minMemSpinBox->setValue(max);
|
||||
ui->maxMemSpinBox->setValue(min);
|
||||
}
|
||||
ui->permGenSpinBox->setValue(s->get("PermGen").toInt());
|
||||
|
||||
// Java Settings
|
||||
ui->javaPathTextBox->setText(s->get("JavaPath").toString());
|
||||
ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
|
||||
// Java Settings
|
||||
ui->javaPathTextBox->setText(s->get("JavaPath").toString());
|
||||
ui->jvmArgsTextBox->setText(s->get("JvmArgs").toString());
|
||||
}
|
||||
|
||||
void JavaPage::on_javaDetectBtn_clicked()
|
||||
{
|
||||
JavaInstallPtr java;
|
||||
JavaInstallPtr java;
|
||||
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
}
|
||||
|
||||
void JavaPage::on_javaBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if(raw_path.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if(raw_path.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QString cooked_path = FS::NormalizePath(raw_path);
|
||||
QFileInfo javaInfo(cooked_path);;
|
||||
if(!javaInfo.exists() || !javaInfo.isExecutable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
ui->javaPathTextBox->setText(cooked_path);
|
||||
QString cooked_path = FS::NormalizePath(raw_path);
|
||||
QFileInfo javaInfo(cooked_path);;
|
||||
if(!javaInfo.exists() || !javaInfo.isExecutable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
ui->javaPathTextBox->setText(cooked_path);
|
||||
}
|
||||
|
||||
void JavaPage::on_javaTestBtn_clicked()
|
||||
{
|
||||
if(checker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaCommon::TestCheck(
|
||||
this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->text(),
|
||||
ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value()));
|
||||
connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished()));
|
||||
checker->run();
|
||||
if(checker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaCommon::TestCheck(
|
||||
this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->text(),
|
||||
ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value()));
|
||||
connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished()));
|
||||
checker->run();
|
||||
}
|
||||
|
||||
void JavaPage::checkerFinished()
|
||||
{
|
||||
checker.reset();
|
||||
checker.reset();
|
||||
}
|
||||
|
@ -31,42 +31,42 @@ class JavaPage;
|
||||
|
||||
class JavaPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit JavaPage(QWidget *parent = 0);
|
||||
~JavaPage();
|
||||
explicit JavaPage(QWidget *parent = 0);
|
||||
~JavaPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Java");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("java");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "java-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Java-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Java");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("java");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "java-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Java-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_javaDetectBtn_clicked();
|
||||
void on_javaTestBtn_clicked();
|
||||
void on_javaBrowseBtn_clicked();
|
||||
void checkerFinished();
|
||||
void on_javaDetectBtn_clicked();
|
||||
void on_javaTestBtn_clicked();
|
||||
void on_javaBrowseBtn_clicked();
|
||||
void checkerFinished();
|
||||
|
||||
private:
|
||||
Ui::JavaPage *ui;
|
||||
unique_qobject_ptr<JavaCommon::TestCheck> checker;
|
||||
Ui::JavaPage *ui;
|
||||
unique_qobject_ptr<JavaCommon::TestCheck> checker;
|
||||
};
|
||||
|
@ -25,52 +25,52 @@
|
||||
|
||||
MinecraftPage::MinecraftPage(QWidget *parent) : QWidget(parent), ui(new Ui::MinecraftPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
loadSettings();
|
||||
updateCheckboxStuff();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
loadSettings();
|
||||
updateCheckboxStuff();
|
||||
}
|
||||
|
||||
MinecraftPage::~MinecraftPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool MinecraftPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MinecraftPage::updateCheckboxStuff()
|
||||
{
|
||||
ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
||||
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
||||
ui->windowWidthSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
||||
ui->windowHeightSpinBox->setEnabled(!ui->maximizedCheckBox->isChecked());
|
||||
}
|
||||
|
||||
void MinecraftPage::on_maximizedCheckBox_clicked(bool checked)
|
||||
{
|
||||
Q_UNUSED(checked);
|
||||
updateCheckboxStuff();
|
||||
Q_UNUSED(checked);
|
||||
updateCheckboxStuff();
|
||||
}
|
||||
|
||||
|
||||
void MinecraftPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
// Window Size
|
||||
s->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
|
||||
s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
|
||||
s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
|
||||
// Window Size
|
||||
s->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
|
||||
s->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
|
||||
s->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
|
||||
}
|
||||
|
||||
void MinecraftPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
// Window Size
|
||||
ui->maximizedCheckBox->setChecked(s->get("LaunchMaximized").toBool());
|
||||
ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt());
|
||||
ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt());
|
||||
// Window Size
|
||||
ui->maximizedCheckBox->setChecked(s->get("LaunchMaximized").toBool());
|
||||
ui->windowWidthSpinBox->setValue(s->get("MinecraftWinWidth").toInt());
|
||||
ui->windowHeightSpinBox->setValue(s->get("MinecraftWinHeight").toInt());
|
||||
}
|
||||
|
@ -31,40 +31,40 @@ class MinecraftPage;
|
||||
|
||||
class MinecraftPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MinecraftPage(QWidget *parent = 0);
|
||||
~MinecraftPage();
|
||||
explicit MinecraftPage(QWidget *parent = 0);
|
||||
~MinecraftPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Minecraft");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("minecraft");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "minecraft-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Minecraft");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("minecraft");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "minecraft-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void updateCheckboxStuff();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void updateCheckboxStuff();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_maximizedCheckBox_clicked(bool checked);
|
||||
void on_maximizedCheckBox_clicked(bool checked);
|
||||
|
||||
private:
|
||||
Ui::MinecraftPage *ui;
|
||||
Ui::MinecraftPage *ui;
|
||||
|
||||
};
|
||||
|
@ -32,441 +32,441 @@
|
||||
// FIXME: possibly move elsewhere
|
||||
enum InstSortMode
|
||||
{
|
||||
// Sort alphabetically by name.
|
||||
Sort_Name,
|
||||
// Sort by which instance was launched most recently.
|
||||
Sort_LastLaunch
|
||||
// Sort alphabetically by name.
|
||||
Sort_Name,
|
||||
// Sort by which instance was launched most recently.
|
||||
Sort_LastLaunch
|
||||
};
|
||||
|
||||
MultiMCPage::MultiMCPage(QWidget *parent) : QWidget(parent), ui(new Ui::MultiMCPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
auto origForeground = ui->fontPreview->palette().color(ui->fontPreview->foregroundRole());
|
||||
auto origBackground = ui->fontPreview->palette().color(ui->fontPreview->backgroundRole());
|
||||
m_colors.reset(new LogColorCache(origForeground, origBackground));
|
||||
ui->setupUi(this);
|
||||
auto origForeground = ui->fontPreview->palette().color(ui->fontPreview->foregroundRole());
|
||||
auto origBackground = ui->fontPreview->palette().color(ui->fontPreview->backgroundRole());
|
||||
m_colors.reset(new LogColorCache(origForeground, origBackground));
|
||||
|
||||
ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name);
|
||||
ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch);
|
||||
ui->sortingModeGroup->setId(ui->sortByNameBtn, Sort_Name);
|
||||
ui->sortingModeGroup->setId(ui->sortLastLaunchedBtn, Sort_LastLaunch);
|
||||
|
||||
defaultFormat = new QTextCharFormat(ui->fontPreview->currentCharFormat());
|
||||
defaultFormat = new QTextCharFormat(ui->fontPreview->currentCharFormat());
|
||||
|
||||
m_languageModel = MMC->translations();
|
||||
loadSettings();
|
||||
m_languageModel = MMC->translations();
|
||||
loadSettings();
|
||||
|
||||
if(BuildConfig.UPDATER_ENABLED)
|
||||
{
|
||||
QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this,
|
||||
&MultiMCPage::refreshUpdateChannelList);
|
||||
if(BuildConfig.UPDATER_ENABLED)
|
||||
{
|
||||
QObject::connect(MMC->updateChecker().get(), &UpdateChecker::channelListLoaded, this,
|
||||
&MultiMCPage::refreshUpdateChannelList);
|
||||
|
||||
if (MMC->updateChecker()->hasChannels())
|
||||
{
|
||||
refreshUpdateChannelList();
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC->updateChecker()->updateChanList(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->updateSettingsBox->setHidden(true);
|
||||
}
|
||||
// Analytics
|
||||
if(BuildConfig.ANALYTICS_ID.isEmpty())
|
||||
{
|
||||
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->analyticsTab));
|
||||
}
|
||||
connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview()));
|
||||
connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview()));
|
||||
connect(ui->languageBox, SIGNAL(currentIndexChanged(int)), SLOT(languageIndexChanged(int)));
|
||||
if (MMC->updateChecker()->hasChannels())
|
||||
{
|
||||
refreshUpdateChannelList();
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC->updateChecker()->updateChanList(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->updateSettingsBox->setHidden(true);
|
||||
}
|
||||
// Analytics
|
||||
if(BuildConfig.ANALYTICS_ID.isEmpty())
|
||||
{
|
||||
ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->analyticsTab));
|
||||
}
|
||||
connect(ui->fontSizeBox, SIGNAL(valueChanged(int)), SLOT(refreshFontPreview()));
|
||||
connect(ui->consoleFont, SIGNAL(currentFontChanged(QFont)), SLOT(refreshFontPreview()));
|
||||
connect(ui->languageBox, SIGNAL(currentIndexChanged(int)), SLOT(languageIndexChanged(int)));
|
||||
}
|
||||
|
||||
MultiMCPage::~MultiMCPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool MultiMCPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MultiMCPage::on_instDirBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text());
|
||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Instance Folder"), ui->instDirTextBox->text());
|
||||
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
|
||||
{
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (FS::checkProblemticPathJava(QDir(cooked_dir)))
|
||||
{
|
||||
QMessageBox warning;
|
||||
warning.setText(tr("You're trying to specify an instance folder which\'s path "
|
||||
"contains at least one \'!\'. "
|
||||
"Java is known to cause problems if that is the case, your "
|
||||
"instances (probably) won't start!"));
|
||||
warning.setInformativeText(
|
||||
tr("Do you really want to use this path? "
|
||||
"Selecting \"No\" will close this and not alter your instance path."));
|
||||
warning.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
int result = warning.exec();
|
||||
if (result == QMessageBox::Yes)
|
||||
{
|
||||
ui->instDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->instDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
}
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
|
||||
{
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
if (FS::checkProblemticPathJava(QDir(cooked_dir)))
|
||||
{
|
||||
QMessageBox warning;
|
||||
warning.setText(tr("You're trying to specify an instance folder which\'s path "
|
||||
"contains at least one \'!\'. "
|
||||
"Java is known to cause problems if that is the case, your "
|
||||
"instances (probably) won't start!"));
|
||||
warning.setInformativeText(
|
||||
tr("Do you really want to use this path? "
|
||||
"Selecting \"No\" will close this and not alter your instance path."));
|
||||
warning.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
int result = warning.exec();
|
||||
if (result == QMessageBox::Yes)
|
||||
{
|
||||
ui->instDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->instDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMCPage::on_iconsDirBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text());
|
||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Icons Folder"), ui->iconsDirTextBox->text());
|
||||
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
|
||||
{
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
ui->iconsDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
|
||||
{
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
ui->iconsDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
}
|
||||
void MultiMCPage::on_modsDirBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text());
|
||||
QString raw_dir = QFileDialog::getExistingDirectory(this, tr("Mods Folder"), ui->modsDirTextBox->text());
|
||||
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
|
||||
{
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
ui->modsDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if (!raw_dir.isEmpty() && QDir(raw_dir).exists())
|
||||
{
|
||||
QString cooked_dir = FS::NormalizePath(raw_dir);
|
||||
ui->modsDirTextBox->setText(cooked_dir);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMCPage::languageIndexChanged(int index)
|
||||
{
|
||||
auto languageCode = ui->languageBox->itemData(ui->languageBox->currentIndex()).toString();
|
||||
if(languageCode.isEmpty())
|
||||
{
|
||||
qWarning() << "Unknown language at index" << index;
|
||||
return;
|
||||
}
|
||||
auto translations = MMC->translations();
|
||||
translations->selectLanguage(languageCode);
|
||||
translations->updateLanguage(languageCode);
|
||||
auto languageCode = ui->languageBox->itemData(ui->languageBox->currentIndex()).toString();
|
||||
if(languageCode.isEmpty())
|
||||
{
|
||||
qWarning() << "Unknown language at index" << index;
|
||||
return;
|
||||
}
|
||||
auto translations = MMC->translations();
|
||||
translations->selectLanguage(languageCode);
|
||||
translations->updateLanguage(languageCode);
|
||||
}
|
||||
|
||||
void MultiMCPage::refreshUpdateChannelList()
|
||||
{
|
||||
// Stop listening for selection changes. It's going to change a lot while we update it and
|
||||
// we don't need to update the
|
||||
// description label constantly.
|
||||
QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(updateChannelSelectionChanged(int)));
|
||||
// Stop listening for selection changes. It's going to change a lot while we update it and
|
||||
// we don't need to update the
|
||||
// description label constantly.
|
||||
QObject::disconnect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(updateChannelSelectionChanged(int)));
|
||||
|
||||
QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
|
||||
ui->updateChannelComboBox->clear();
|
||||
int selection = -1;
|
||||
for (int i = 0; i < channelList.count(); i++)
|
||||
{
|
||||
UpdateChecker::ChannelListEntry entry = channelList.at(i);
|
||||
QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
|
||||
ui->updateChannelComboBox->clear();
|
||||
int selection = -1;
|
||||
for (int i = 0; i < channelList.count(); i++)
|
||||
{
|
||||
UpdateChecker::ChannelListEntry entry = channelList.at(i);
|
||||
|
||||
// When it comes to selection, we'll rely on the indexes of a channel entry being the
|
||||
// same in the
|
||||
// combo box as it is in the update checker's channel list.
|
||||
// This probably isn't very safe, but the channel list doesn't change often enough (or
|
||||
// at all) for
|
||||
// this to be a big deal. Hope it doesn't break...
|
||||
ui->updateChannelComboBox->addItem(entry.name);
|
||||
// When it comes to selection, we'll rely on the indexes of a channel entry being the
|
||||
// same in the
|
||||
// combo box as it is in the update checker's channel list.
|
||||
// This probably isn't very safe, but the channel list doesn't change often enough (or
|
||||
// at all) for
|
||||
// this to be a big deal. Hope it doesn't break...
|
||||
ui->updateChannelComboBox->addItem(entry.name);
|
||||
|
||||
// If the update channel we just added was the selected one, set the current index in
|
||||
// the combo box to it.
|
||||
if (entry.id == m_currentUpdateChannel)
|
||||
{
|
||||
qDebug() << "Selected index" << i << "channel id" << m_currentUpdateChannel;
|
||||
selection = i;
|
||||
}
|
||||
}
|
||||
// If the update channel we just added was the selected one, set the current index in
|
||||
// the combo box to it.
|
||||
if (entry.id == m_currentUpdateChannel)
|
||||
{
|
||||
qDebug() << "Selected index" << i << "channel id" << m_currentUpdateChannel;
|
||||
selection = i;
|
||||
}
|
||||
}
|
||||
|
||||
ui->updateChannelComboBox->setCurrentIndex(selection);
|
||||
ui->updateChannelComboBox->setCurrentIndex(selection);
|
||||
|
||||
// Start listening for selection changes again and update the description label.
|
||||
QObject::connect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(updateChannelSelectionChanged(int)));
|
||||
refreshUpdateChannelDesc();
|
||||
// Start listening for selection changes again and update the description label.
|
||||
QObject::connect(ui->updateChannelComboBox, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(updateChannelSelectionChanged(int)));
|
||||
refreshUpdateChannelDesc();
|
||||
|
||||
// Now that we've updated the channel list, we can enable the combo box.
|
||||
// It starts off disabled so that if the channel list hasn't been loaded, it will be
|
||||
// disabled.
|
||||
ui->updateChannelComboBox->setEnabled(true);
|
||||
// Now that we've updated the channel list, we can enable the combo box.
|
||||
// It starts off disabled so that if the channel list hasn't been loaded, it will be
|
||||
// disabled.
|
||||
ui->updateChannelComboBox->setEnabled(true);
|
||||
}
|
||||
|
||||
void MultiMCPage::updateChannelSelectionChanged(int index)
|
||||
{
|
||||
refreshUpdateChannelDesc();
|
||||
refreshUpdateChannelDesc();
|
||||
}
|
||||
|
||||
void MultiMCPage::refreshUpdateChannelDesc()
|
||||
{
|
||||
// Get the channel list.
|
||||
QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
|
||||
int selectedIndex = ui->updateChannelComboBox->currentIndex();
|
||||
if (selectedIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (selectedIndex < channelList.count())
|
||||
{
|
||||
// Find the channel list entry with the given index.
|
||||
UpdateChecker::ChannelListEntry selected = channelList.at(selectedIndex);
|
||||
// Get the channel list.
|
||||
QList<UpdateChecker::ChannelListEntry> channelList = MMC->updateChecker()->getChannelList();
|
||||
int selectedIndex = ui->updateChannelComboBox->currentIndex();
|
||||
if (selectedIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (selectedIndex < channelList.count())
|
||||
{
|
||||
// Find the channel list entry with the given index.
|
||||
UpdateChecker::ChannelListEntry selected = channelList.at(selectedIndex);
|
||||
|
||||
// Set the description text.
|
||||
ui->updateChannelDescLabel->setText(selected.description);
|
||||
// Set the description text.
|
||||
ui->updateChannelDescLabel->setText(selected.description);
|
||||
|
||||
// Set the currently selected channel ID.
|
||||
m_currentUpdateChannel = selected.id;
|
||||
}
|
||||
// Set the currently selected channel ID.
|
||||
m_currentUpdateChannel = selected.id;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMCPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
// Language
|
||||
s->set("Language", ui->languageBox->itemData(ui->languageBox->currentIndex()).toString());
|
||||
// Language
|
||||
s->set("Language", ui->languageBox->itemData(ui->languageBox->currentIndex()).toString());
|
||||
|
||||
if (ui->resetNotificationsBtn->isChecked())
|
||||
{
|
||||
s->set("ShownNotifications", QString());
|
||||
}
|
||||
if (ui->resetNotificationsBtn->isChecked())
|
||||
{
|
||||
s->set("ShownNotifications", QString());
|
||||
}
|
||||
|
||||
// Updates
|
||||
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
|
||||
s->set("UpdateChannel", m_currentUpdateChannel);
|
||||
auto original = s->get("IconTheme").toString();
|
||||
//FIXME: make generic
|
||||
switch (ui->themeComboBox->currentIndex())
|
||||
{
|
||||
case 1:
|
||||
s->set("IconTheme", "pe_dark");
|
||||
break;
|
||||
case 2:
|
||||
s->set("IconTheme", "pe_light");
|
||||
break;
|
||||
case 3:
|
||||
s->set("IconTheme", "pe_blue");
|
||||
break;
|
||||
case 4:
|
||||
s->set("IconTheme", "pe_colored");
|
||||
break;
|
||||
case 5:
|
||||
s->set("IconTheme", "OSX");
|
||||
break;
|
||||
case 6:
|
||||
s->set("IconTheme", "iOS");
|
||||
break;
|
||||
case 7:
|
||||
s->set("IconTheme", "flat");
|
||||
break;
|
||||
case 8:
|
||||
s->set("IconTheme", "custom");
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
s->set("IconTheme", "multimc");
|
||||
break;
|
||||
}
|
||||
// Updates
|
||||
s->set("AutoUpdate", ui->autoUpdateCheckBox->isChecked());
|
||||
s->set("UpdateChannel", m_currentUpdateChannel);
|
||||
auto original = s->get("IconTheme").toString();
|
||||
//FIXME: make generic
|
||||
switch (ui->themeComboBox->currentIndex())
|
||||
{
|
||||
case 1:
|
||||
s->set("IconTheme", "pe_dark");
|
||||
break;
|
||||
case 2:
|
||||
s->set("IconTheme", "pe_light");
|
||||
break;
|
||||
case 3:
|
||||
s->set("IconTheme", "pe_blue");
|
||||
break;
|
||||
case 4:
|
||||
s->set("IconTheme", "pe_colored");
|
||||
break;
|
||||
case 5:
|
||||
s->set("IconTheme", "OSX");
|
||||
break;
|
||||
case 6:
|
||||
s->set("IconTheme", "iOS");
|
||||
break;
|
||||
case 7:
|
||||
s->set("IconTheme", "flat");
|
||||
break;
|
||||
case 8:
|
||||
s->set("IconTheme", "custom");
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
s->set("IconTheme", "multimc");
|
||||
break;
|
||||
}
|
||||
|
||||
if(original != s->get("IconTheme"))
|
||||
{
|
||||
MMC->setIconTheme(s->get("IconTheme").toString());
|
||||
}
|
||||
if(original != s->get("IconTheme"))
|
||||
{
|
||||
MMC->setIconTheme(s->get("IconTheme").toString());
|
||||
}
|
||||
|
||||
auto originalAppTheme = s->get("ApplicationTheme").toString();
|
||||
auto newAppTheme = ui->themeComboBoxColors->currentData().toString();
|
||||
if(originalAppTheme != newAppTheme)
|
||||
{
|
||||
s->set("ApplicationTheme", newAppTheme);
|
||||
MMC->setApplicationTheme(newAppTheme, false);
|
||||
}
|
||||
auto originalAppTheme = s->get("ApplicationTheme").toString();
|
||||
auto newAppTheme = ui->themeComboBoxColors->currentData().toString();
|
||||
if(originalAppTheme != newAppTheme)
|
||||
{
|
||||
s->set("ApplicationTheme", newAppTheme);
|
||||
MMC->setApplicationTheme(newAppTheme, false);
|
||||
}
|
||||
|
||||
// Console settings
|
||||
s->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
s->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked());
|
||||
QString consoleFontFamily = ui->consoleFont->currentFont().family();
|
||||
s->set("ConsoleFont", consoleFontFamily);
|
||||
s->set("ConsoleFontSize", ui->fontSizeBox->value());
|
||||
s->set("ConsoleMaxLines", ui->lineLimitSpinBox->value());
|
||||
s->set("ConsoleOverflowStop", ui->checkStopLogging->checkState() != Qt::Unchecked);
|
||||
// Console settings
|
||||
s->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
s->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
s->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked());
|
||||
QString consoleFontFamily = ui->consoleFont->currentFont().family();
|
||||
s->set("ConsoleFont", consoleFontFamily);
|
||||
s->set("ConsoleFontSize", ui->fontSizeBox->value());
|
||||
s->set("ConsoleMaxLines", ui->lineLimitSpinBox->value());
|
||||
s->set("ConsoleOverflowStop", ui->checkStopLogging->checkState() != Qt::Unchecked);
|
||||
|
||||
// Folders
|
||||
// TODO: Offer to move instances to new instance folder.
|
||||
s->set("InstanceDir", ui->instDirTextBox->text());
|
||||
s->set("CentralModsDir", ui->modsDirTextBox->text());
|
||||
s->set("IconsDir", ui->iconsDirTextBox->text());
|
||||
// Folders
|
||||
// TODO: Offer to move instances to new instance folder.
|
||||
s->set("InstanceDir", ui->instDirTextBox->text());
|
||||
s->set("CentralModsDir", ui->modsDirTextBox->text());
|
||||
s->set("IconsDir", ui->iconsDirTextBox->text());
|
||||
|
||||
auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
|
||||
switch (sortMode)
|
||||
{
|
||||
case Sort_LastLaunch:
|
||||
s->set("InstSortMode", "LastLaunch");
|
||||
break;
|
||||
case Sort_Name:
|
||||
default:
|
||||
s->set("InstSortMode", "Name");
|
||||
break;
|
||||
}
|
||||
auto sortMode = (InstSortMode)ui->sortingModeGroup->checkedId();
|
||||
switch (sortMode)
|
||||
{
|
||||
case Sort_LastLaunch:
|
||||
s->set("InstSortMode", "LastLaunch");
|
||||
break;
|
||||
case Sort_Name:
|
||||
default:
|
||||
s->set("InstSortMode", "Name");
|
||||
break;
|
||||
}
|
||||
|
||||
// Analytics
|
||||
if(!BuildConfig.ANALYTICS_ID.isEmpty())
|
||||
{
|
||||
s->set("Analytics", ui->analyticsCheck->isChecked());
|
||||
}
|
||||
// Analytics
|
||||
if(!BuildConfig.ANALYTICS_ID.isEmpty())
|
||||
{
|
||||
s->set("Analytics", ui->analyticsCheck->isChecked());
|
||||
}
|
||||
}
|
||||
void MultiMCPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
// Language
|
||||
{
|
||||
ui->languageBox->setModel(m_languageModel.get());
|
||||
ui->languageBox->setCurrentIndex(ui->languageBox->findData(s->get("Language").toString()));
|
||||
}
|
||||
auto s = MMC->settings();
|
||||
// Language
|
||||
{
|
||||
ui->languageBox->setModel(m_languageModel.get());
|
||||
ui->languageBox->setCurrentIndex(ui->languageBox->findData(s->get("Language").toString()));
|
||||
}
|
||||
|
||||
// Updates
|
||||
ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
|
||||
m_currentUpdateChannel = s->get("UpdateChannel").toString();
|
||||
//FIXME: make generic
|
||||
auto theme = s->get("IconTheme").toString();
|
||||
if (theme == "pe_dark")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(1);
|
||||
}
|
||||
else if (theme == "pe_light")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(2);
|
||||
}
|
||||
else if (theme == "pe_blue")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(3);
|
||||
}
|
||||
else if (theme == "pe_colored")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(4);
|
||||
}
|
||||
else if (theme == "OSX")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(5);
|
||||
}
|
||||
else if (theme == "iOS")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(6);
|
||||
}
|
||||
else if (theme == "flat")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(7);
|
||||
}
|
||||
else if (theme == "custom")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(0);
|
||||
}
|
||||
// Updates
|
||||
ui->autoUpdateCheckBox->setChecked(s->get("AutoUpdate").toBool());
|
||||
m_currentUpdateChannel = s->get("UpdateChannel").toString();
|
||||
//FIXME: make generic
|
||||
auto theme = s->get("IconTheme").toString();
|
||||
if (theme == "pe_dark")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(1);
|
||||
}
|
||||
else if (theme == "pe_light")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(2);
|
||||
}
|
||||
else if (theme == "pe_blue")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(3);
|
||||
}
|
||||
else if (theme == "pe_colored")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(4);
|
||||
}
|
||||
else if (theme == "OSX")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(5);
|
||||
}
|
||||
else if (theme == "iOS")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(6);
|
||||
}
|
||||
else if (theme == "flat")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(7);
|
||||
}
|
||||
else if (theme == "custom")
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(8);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->themeComboBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
{
|
||||
auto currentTheme = s->get("ApplicationTheme").toString();
|
||||
auto themes = MMC->getValidApplicationThemes();
|
||||
int idx = 0;
|
||||
for(auto &theme: themes)
|
||||
{
|
||||
ui->themeComboBoxColors->addItem(theme->name(), theme->id());
|
||||
if(currentTheme == theme->id())
|
||||
{
|
||||
ui->themeComboBoxColors->setCurrentIndex(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
{
|
||||
auto currentTheme = s->get("ApplicationTheme").toString();
|
||||
auto themes = MMC->getValidApplicationThemes();
|
||||
int idx = 0;
|
||||
for(auto &theme: themes)
|
||||
{
|
||||
ui->themeComboBoxColors->addItem(theme->name(), theme->id());
|
||||
if(currentTheme == theme->id())
|
||||
{
|
||||
ui->themeComboBoxColors->setCurrentIndex(idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// Console settings
|
||||
ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool());
|
||||
ui->showConsoleErrorCheck->setChecked(s->get("ShowConsoleOnError").toBool());
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
QFont consoleFont(fontFamily);
|
||||
ui->consoleFont->setCurrentFont(consoleFont);
|
||||
// Console settings
|
||||
ui->showConsoleCheck->setChecked(s->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(s->get("AutoCloseConsole").toBool());
|
||||
ui->showConsoleErrorCheck->setChecked(s->get("ShowConsoleOnError").toBool());
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
QFont consoleFont(fontFamily);
|
||||
ui->consoleFont->setCurrentFont(consoleFont);
|
||||
|
||||
bool conversionOk = true;
|
||||
int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
fontSize = 11;
|
||||
}
|
||||
ui->fontSizeBox->setValue(fontSize);
|
||||
refreshFontPreview();
|
||||
ui->lineLimitSpinBox->setValue(s->get("ConsoleMaxLines").toInt());
|
||||
ui->checkStopLogging->setChecked(s->get("ConsoleOverflowStop").toBool());
|
||||
bool conversionOk = true;
|
||||
int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
fontSize = 11;
|
||||
}
|
||||
ui->fontSizeBox->setValue(fontSize);
|
||||
refreshFontPreview();
|
||||
ui->lineLimitSpinBox->setValue(s->get("ConsoleMaxLines").toInt());
|
||||
ui->checkStopLogging->setChecked(s->get("ConsoleOverflowStop").toBool());
|
||||
|
||||
// Folders
|
||||
ui->instDirTextBox->setText(s->get("InstanceDir").toString());
|
||||
ui->modsDirTextBox->setText(s->get("CentralModsDir").toString());
|
||||
ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
|
||||
// Folders
|
||||
ui->instDirTextBox->setText(s->get("InstanceDir").toString());
|
||||
ui->modsDirTextBox->setText(s->get("CentralModsDir").toString());
|
||||
ui->iconsDirTextBox->setText(s->get("IconsDir").toString());
|
||||
|
||||
QString sortMode = s->get("InstSortMode").toString();
|
||||
QString sortMode = s->get("InstSortMode").toString();
|
||||
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
ui->sortLastLaunchedBtn->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->sortByNameBtn->setChecked(true);
|
||||
}
|
||||
if (sortMode == "LastLaunch")
|
||||
{
|
||||
ui->sortLastLaunchedBtn->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->sortByNameBtn->setChecked(true);
|
||||
}
|
||||
|
||||
// Analytics
|
||||
if(!BuildConfig.ANALYTICS_ID.isEmpty())
|
||||
{
|
||||
ui->analyticsCheck->setChecked(s->get("Analytics").toBool());
|
||||
}
|
||||
// Analytics
|
||||
if(!BuildConfig.ANALYTICS_ID.isEmpty())
|
||||
{
|
||||
ui->analyticsCheck->setChecked(s->get("Analytics").toBool());
|
||||
}
|
||||
}
|
||||
|
||||
void MultiMCPage::refreshFontPreview()
|
||||
{
|
||||
int fontSize = ui->fontSizeBox->value();
|
||||
QString fontFamily = ui->consoleFont->currentFont().family();
|
||||
ui->fontPreview->clear();
|
||||
defaultFormat->setFont(QFont(fontFamily, fontSize));
|
||||
{
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
format.setForeground(m_colors->getFront(MessageLevel::Error));
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->fontPreview->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(tr("[Something/ERROR] A spooky error!"), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
{
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
format.setForeground(m_colors->getFront(MessageLevel::Message));
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->fontPreview->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(tr("[Test/INFO] A harmless message..."), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
{
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
format.setForeground(m_colors->getFront(MessageLevel::Warning));
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->fontPreview->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(tr("[Something/WARN] A not so spooky warning."), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
int fontSize = ui->fontSizeBox->value();
|
||||
QString fontFamily = ui->consoleFont->currentFont().family();
|
||||
ui->fontPreview->clear();
|
||||
defaultFormat->setFont(QFont(fontFamily, fontSize));
|
||||
{
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
format.setForeground(m_colors->getFront(MessageLevel::Error));
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->fontPreview->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(tr("[Something/ERROR] A spooky error!"), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
{
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
format.setForeground(m_colors->getFront(MessageLevel::Message));
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->fontPreview->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(tr("[Test/INFO] A harmless message..."), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
{
|
||||
QTextCharFormat format(*defaultFormat);
|
||||
format.setForeground(m_colors->getFront(MessageLevel::Warning));
|
||||
// append a paragraph/line
|
||||
auto workCursor = ui->fontPreview->textCursor();
|
||||
workCursor.movePosition(QTextCursor::End);
|
||||
workCursor.insertText(tr("[Something/WARN] A not so spooky warning."), format);
|
||||
workCursor.insertBlock();
|
||||
}
|
||||
}
|
||||
|
@ -34,71 +34,71 @@ class MultiMCPage;
|
||||
|
||||
class MultiMCPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MultiMCPage(QWidget *parent = 0);
|
||||
~MultiMCPage();
|
||||
explicit MultiMCPage(QWidget *parent = 0);
|
||||
~MultiMCPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return "MultiMC";
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("multimc");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "multimc-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "MultiMC-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return "MultiMC";
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("multimc");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "multimc-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "MultiMC-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
private
|
||||
slots:
|
||||
void on_instDirBrowseBtn_clicked();
|
||||
void on_modsDirBrowseBtn_clicked();
|
||||
void on_iconsDirBrowseBtn_clicked();
|
||||
void on_instDirBrowseBtn_clicked();
|
||||
void on_modsDirBrowseBtn_clicked();
|
||||
void on_iconsDirBrowseBtn_clicked();
|
||||
|
||||
void languageIndexChanged(int index);
|
||||
void languageIndexChanged(int index);
|
||||
|
||||
/*!
|
||||
* Updates the list of update channels in the combo box.
|
||||
*/
|
||||
void refreshUpdateChannelList();
|
||||
/*!
|
||||
* Updates the list of update channels in the combo box.
|
||||
*/
|
||||
void refreshUpdateChannelList();
|
||||
|
||||
/*!
|
||||
* Updates the channel description label.
|
||||
*/
|
||||
void refreshUpdateChannelDesc();
|
||||
/*!
|
||||
* Updates the channel description label.
|
||||
*/
|
||||
void refreshUpdateChannelDesc();
|
||||
|
||||
/*!
|
||||
* Updates the font preview
|
||||
*/
|
||||
void refreshFontPreview();
|
||||
/*!
|
||||
* Updates the font preview
|
||||
*/
|
||||
void refreshFontPreview();
|
||||
|
||||
void updateChannelSelectionChanged(int index);
|
||||
void updateChannelSelectionChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::MultiMCPage *ui;
|
||||
Ui::MultiMCPage *ui;
|
||||
|
||||
/*!
|
||||
* Stores the currently selected update channel.
|
||||
*/
|
||||
QString m_currentUpdateChannel;
|
||||
/*!
|
||||
* Stores the currently selected update channel.
|
||||
*/
|
||||
QString m_currentUpdateChannel;
|
||||
|
||||
// default format for the font preview...
|
||||
QTextCharFormat *defaultFormat;
|
||||
// default format for the font preview...
|
||||
QTextCharFormat *defaultFormat;
|
||||
|
||||
std::unique_ptr<LogColorCache> m_colors;
|
||||
std::unique_ptr<LogColorCache> m_colors;
|
||||
|
||||
std::shared_ptr<TranslationsModel> m_languageModel;
|
||||
std::shared_ptr<TranslationsModel> m_languageModel;
|
||||
};
|
||||
|
@ -33,192 +33,192 @@ using namespace Meta;
|
||||
|
||||
static QString formatRequires(const VersionPtr &version)
|
||||
{
|
||||
QStringList lines;
|
||||
auto & reqs = version->requires();
|
||||
auto iter = reqs.begin();
|
||||
while (iter != reqs.end())
|
||||
{
|
||||
auto &uid = iter->uid;
|
||||
auto &version = iter->equalsVersion;
|
||||
const QString readable = ENV.metadataIndex()->hasUid(uid) ? ENV.metadataIndex()->get(uid)->humanReadable() : uid;
|
||||
if(!version.isEmpty())
|
||||
{
|
||||
lines.append(QString("%1 (%2)").arg(readable, version));
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.append(QString("%1").arg(readable));
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
return lines.join('\n');
|
||||
QStringList lines;
|
||||
auto & reqs = version->requires();
|
||||
auto iter = reqs.begin();
|
||||
while (iter != reqs.end())
|
||||
{
|
||||
auto &uid = iter->uid;
|
||||
auto &version = iter->equalsVersion;
|
||||
const QString readable = ENV.metadataIndex()->hasUid(uid) ? ENV.metadataIndex()->get(uid)->humanReadable() : uid;
|
||||
if(!version.isEmpty())
|
||||
{
|
||||
lines.append(QString("%1 (%2)").arg(readable, version));
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.append(QString("%1").arg(readable));
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
PackagesPage::PackagesPage(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::PackagesPage)
|
||||
QWidget(parent),
|
||||
ui(new Ui::PackagesPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_fileProxy = new QSortFilterProxyModel(this);
|
||||
m_fileProxy->setSortRole(Qt::DisplayRole);
|
||||
m_fileProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_fileProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_fileProxy->setFilterRole(Qt::DisplayRole);
|
||||
m_fileProxy->setFilterKeyColumn(0);
|
||||
m_fileProxy->sort(0);
|
||||
m_fileProxy->setSourceModel(ENV.metadataIndex().get());
|
||||
ui->indexView->setModel(m_fileProxy);
|
||||
m_fileProxy = new QSortFilterProxyModel(this);
|
||||
m_fileProxy->setSortRole(Qt::DisplayRole);
|
||||
m_fileProxy->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_fileProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_fileProxy->setFilterRole(Qt::DisplayRole);
|
||||
m_fileProxy->setFilterKeyColumn(0);
|
||||
m_fileProxy->sort(0);
|
||||
m_fileProxy->setSourceModel(ENV.metadataIndex().get());
|
||||
ui->indexView->setModel(m_fileProxy);
|
||||
|
||||
m_filterProxy = new QSortFilterProxyModel(this);
|
||||
m_filterProxy->setSortRole(VersionList::SortRole);
|
||||
m_filterProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterProxy->setFilterRole(Qt::DisplayRole);
|
||||
m_filterProxy->setFilterKeyColumn(0);
|
||||
m_filterProxy->sort(0, Qt::DescendingOrder);
|
||||
ui->versionsView->setModel(m_filterProxy);
|
||||
m_filterProxy = new QSortFilterProxyModel(this);
|
||||
m_filterProxy->setSortRole(VersionList::SortRole);
|
||||
m_filterProxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterProxy->setFilterRole(Qt::DisplayRole);
|
||||
m_filterProxy->setFilterKeyColumn(0);
|
||||
m_filterProxy->sort(0, Qt::DescendingOrder);
|
||||
ui->versionsView->setModel(m_filterProxy);
|
||||
|
||||
m_versionProxy = new VersionProxyModel(this);
|
||||
m_filterProxy->setSourceModel(m_versionProxy);
|
||||
m_versionProxy = new VersionProxyModel(this);
|
||||
m_filterProxy->setSourceModel(m_versionProxy);
|
||||
|
||||
connect(ui->indexView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateCurrentVersionList);
|
||||
connect(ui->versionsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateVersion);
|
||||
connect(m_filterProxy, &QSortFilterProxyModel::dataChanged, this, &PackagesPage::versionListDataChanged);
|
||||
connect(ui->indexView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateCurrentVersionList);
|
||||
connect(ui->versionsView->selectionModel(), &QItemSelectionModel::currentChanged, this, &PackagesPage::updateVersion);
|
||||
connect(m_filterProxy, &QSortFilterProxyModel::dataChanged, this, &PackagesPage::versionListDataChanged);
|
||||
|
||||
updateCurrentVersionList(QModelIndex());
|
||||
updateVersion();
|
||||
updateCurrentVersionList(QModelIndex());
|
||||
updateVersion();
|
||||
}
|
||||
|
||||
PackagesPage::~PackagesPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QIcon PackagesPage::icon() const
|
||||
{
|
||||
return MMC->getThemedIcon("packages");
|
||||
return MMC->getThemedIcon("packages");
|
||||
}
|
||||
|
||||
void PackagesPage::on_refreshIndexBtn_clicked()
|
||||
{
|
||||
ENV.metadataIndex()->load(Net::Mode::Online);
|
||||
ENV.metadataIndex()->load(Net::Mode::Online);
|
||||
}
|
||||
void PackagesPage::on_refreshFileBtn_clicked()
|
||||
{
|
||||
VersionListPtr list = ui->indexView->currentIndex().data(Index::ListPtrRole).value<VersionListPtr>();
|
||||
if (!list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
list->load(Net::Mode::Online);
|
||||
VersionListPtr list = ui->indexView->currentIndex().data(Index::ListPtrRole).value<VersionListPtr>();
|
||||
if (!list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
list->load(Net::Mode::Online);
|
||||
}
|
||||
void PackagesPage::on_refreshVersionBtn_clicked()
|
||||
{
|
||||
VersionPtr version = ui->versionsView->currentIndex().data(VersionList::VersionPtrRole).value<VersionPtr>();
|
||||
if (!version)
|
||||
{
|
||||
return;
|
||||
}
|
||||
version->load(Net::Mode::Online);
|
||||
VersionPtr version = ui->versionsView->currentIndex().data(VersionList::VersionPtrRole).value<VersionPtr>();
|
||||
if (!version)
|
||||
{
|
||||
return;
|
||||
}
|
||||
version->load(Net::Mode::Online);
|
||||
}
|
||||
|
||||
void PackagesPage::on_fileSearchEdit_textChanged(const QString &search)
|
||||
{
|
||||
if (search.isEmpty())
|
||||
{
|
||||
m_fileProxy->setFilterFixedString(QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList parts = search.split(' ');
|
||||
std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape);
|
||||
m_fileProxy->setFilterRegExp(".*" + parts.join(".*") + ".*");
|
||||
}
|
||||
if (search.isEmpty())
|
||||
{
|
||||
m_fileProxy->setFilterFixedString(QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList parts = search.split(' ');
|
||||
std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape);
|
||||
m_fileProxy->setFilterRegExp(".*" + parts.join(".*") + ".*");
|
||||
}
|
||||
}
|
||||
void PackagesPage::on_versionSearchEdit_textChanged(const QString &search)
|
||||
{
|
||||
if (search.isEmpty())
|
||||
{
|
||||
m_filterProxy->setFilterFixedString(QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList parts = search.split(' ');
|
||||
std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape);
|
||||
m_filterProxy->setFilterRegExp(".*" + parts.join(".*") + ".*");
|
||||
}
|
||||
if (search.isEmpty())
|
||||
{
|
||||
m_filterProxy->setFilterFixedString(QString());
|
||||
}
|
||||
else
|
||||
{
|
||||
QStringList parts = search.split(' ');
|
||||
std::transform(parts.begin(), parts.end(), parts.begin(), &QRegularExpression::escape);
|
||||
m_filterProxy->setFilterRegExp(".*" + parts.join(".*") + ".*");
|
||||
}
|
||||
}
|
||||
|
||||
void PackagesPage::updateCurrentVersionList(const QModelIndex &index)
|
||||
{
|
||||
if (index.isValid())
|
||||
{
|
||||
VersionListPtr list = index.data(Index::ListPtrRole).value<VersionListPtr>();
|
||||
ui->versionsBox->setEnabled(true);
|
||||
ui->refreshFileBtn->setEnabled(true);
|
||||
ui->fileUidLabel->setEnabled(true);
|
||||
ui->fileUid->setText(list->uid());
|
||||
ui->fileNameLabel->setEnabled(true);
|
||||
ui->fileName->setText(list->name());
|
||||
m_versionProxy->setSourceModel(list.get());
|
||||
ui->refreshFileBtn->setText(tr("Refresh %1").arg(list->humanReadable()));
|
||||
list->load(Net::Mode::Offline);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->versionsBox->setEnabled(false);
|
||||
ui->refreshFileBtn->setEnabled(false);
|
||||
ui->fileUidLabel->setEnabled(false);
|
||||
ui->fileUid->clear();
|
||||
ui->fileNameLabel->setEnabled(false);
|
||||
ui->fileName->clear();
|
||||
m_versionProxy->setSourceModel(nullptr);
|
||||
ui->refreshFileBtn->setText(tr("Refresh"));
|
||||
}
|
||||
if (index.isValid())
|
||||
{
|
||||
VersionListPtr list = index.data(Index::ListPtrRole).value<VersionListPtr>();
|
||||
ui->versionsBox->setEnabled(true);
|
||||
ui->refreshFileBtn->setEnabled(true);
|
||||
ui->fileUidLabel->setEnabled(true);
|
||||
ui->fileUid->setText(list->uid());
|
||||
ui->fileNameLabel->setEnabled(true);
|
||||
ui->fileName->setText(list->name());
|
||||
m_versionProxy->setSourceModel(list.get());
|
||||
ui->refreshFileBtn->setText(tr("Refresh %1").arg(list->humanReadable()));
|
||||
list->load(Net::Mode::Offline);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->versionsBox->setEnabled(false);
|
||||
ui->refreshFileBtn->setEnabled(false);
|
||||
ui->fileUidLabel->setEnabled(false);
|
||||
ui->fileUid->clear();
|
||||
ui->fileNameLabel->setEnabled(false);
|
||||
ui->fileName->clear();
|
||||
m_versionProxy->setSourceModel(nullptr);
|
||||
ui->refreshFileBtn->setText(tr("Refresh"));
|
||||
}
|
||||
}
|
||||
|
||||
void PackagesPage::versionListDataChanged(const QModelIndex &tl, const QModelIndex &br)
|
||||
{
|
||||
if (QItemSelection(tl, br).contains(ui->versionsView->currentIndex()))
|
||||
{
|
||||
updateVersion();
|
||||
}
|
||||
if (QItemSelection(tl, br).contains(ui->versionsView->currentIndex()))
|
||||
{
|
||||
updateVersion();
|
||||
}
|
||||
}
|
||||
|
||||
void PackagesPage::updateVersion()
|
||||
{
|
||||
VersionPtr version = std::dynamic_pointer_cast<Version>(
|
||||
ui->versionsView->currentIndex().data(VersionList::VersionPointerRole).value<BaseVersionPtr>());
|
||||
if (version)
|
||||
{
|
||||
ui->refreshVersionBtn->setEnabled(true);
|
||||
ui->versionVersionLabel->setEnabled(true);
|
||||
ui->versionVersion->setText(version->version());
|
||||
ui->versionTimeLabel->setEnabled(true);
|
||||
ui->versionTime->setText(version->time().toString("yyyy-MM-dd HH:mm"));
|
||||
ui->versionTypeLabel->setEnabled(true);
|
||||
ui->versionType->setText(version->type());
|
||||
ui->versionRequiresLabel->setEnabled(true);
|
||||
ui->versionRequires->setText(formatRequires(version));
|
||||
ui->refreshVersionBtn->setText(tr("Refresh %1").arg(version->version()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->refreshVersionBtn->setEnabled(false);
|
||||
ui->versionVersionLabel->setEnabled(false);
|
||||
ui->versionVersion->clear();
|
||||
ui->versionTimeLabel->setEnabled(false);
|
||||
ui->versionTime->clear();
|
||||
ui->versionTypeLabel->setEnabled(false);
|
||||
ui->versionType->clear();
|
||||
ui->versionRequiresLabel->setEnabled(false);
|
||||
ui->versionRequires->clear();
|
||||
ui->refreshVersionBtn->setText(tr("Refresh"));
|
||||
}
|
||||
VersionPtr version = std::dynamic_pointer_cast<Version>(
|
||||
ui->versionsView->currentIndex().data(VersionList::VersionPointerRole).value<BaseVersionPtr>());
|
||||
if (version)
|
||||
{
|
||||
ui->refreshVersionBtn->setEnabled(true);
|
||||
ui->versionVersionLabel->setEnabled(true);
|
||||
ui->versionVersion->setText(version->version());
|
||||
ui->versionTimeLabel->setEnabled(true);
|
||||
ui->versionTime->setText(version->time().toString("yyyy-MM-dd HH:mm"));
|
||||
ui->versionTypeLabel->setEnabled(true);
|
||||
ui->versionType->setText(version->type());
|
||||
ui->versionRequiresLabel->setEnabled(true);
|
||||
ui->versionRequires->setText(formatRequires(version));
|
||||
ui->refreshVersionBtn->setText(tr("Refresh %1").arg(version->version()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->refreshVersionBtn->setEnabled(false);
|
||||
ui->versionVersionLabel->setEnabled(false);
|
||||
ui->versionVersion->clear();
|
||||
ui->versionTimeLabel->setEnabled(false);
|
||||
ui->versionTime->clear();
|
||||
ui->versionTypeLabel->setEnabled(false);
|
||||
ui->versionType->clear();
|
||||
ui->versionRequiresLabel->setEnabled(false);
|
||||
ui->versionRequires->clear();
|
||||
ui->refreshVersionBtn->setText(tr("Refresh"));
|
||||
}
|
||||
}
|
||||
|
||||
void PackagesPage::openedImpl()
|
||||
{
|
||||
ENV.metadataIndex()->load(Net::Mode::Offline);
|
||||
ENV.metadataIndex()->load(Net::Mode::Offline);
|
||||
}
|
||||
|
@ -28,30 +28,30 @@ class VersionProxyModel;
|
||||
|
||||
class PackagesPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PackagesPage(QWidget *parent = 0);
|
||||
~PackagesPage();
|
||||
explicit PackagesPage(QWidget *parent = 0);
|
||||
~PackagesPage();
|
||||
|
||||
QString id() const override { return "packages-global"; }
|
||||
QString displayName() const override { return tr("Packages"); }
|
||||
QIcon icon() const override;
|
||||
void openedImpl() override;
|
||||
QString id() const override { return "packages-global"; }
|
||||
QString displayName() const override { return tr("Packages"); }
|
||||
QIcon icon() const override;
|
||||
void openedImpl() override;
|
||||
|
||||
private slots:
|
||||
void on_refreshIndexBtn_clicked();
|
||||
void on_refreshFileBtn_clicked();
|
||||
void on_refreshVersionBtn_clicked();
|
||||
void on_fileSearchEdit_textChanged(const QString &search);
|
||||
void on_versionSearchEdit_textChanged(const QString &search);
|
||||
void updateCurrentVersionList(const QModelIndex &index);
|
||||
void versionListDataChanged(const QModelIndex &tl, const QModelIndex &br);
|
||||
void on_refreshIndexBtn_clicked();
|
||||
void on_refreshFileBtn_clicked();
|
||||
void on_refreshVersionBtn_clicked();
|
||||
void on_fileSearchEdit_textChanged(const QString &search);
|
||||
void on_versionSearchEdit_textChanged(const QString &search);
|
||||
void updateCurrentVersionList(const QModelIndex &index);
|
||||
void versionListDataChanged(const QModelIndex &tl, const QModelIndex &br);
|
||||
|
||||
private:
|
||||
Ui::PackagesPage *ui;
|
||||
QSortFilterProxyModel *m_fileProxy;
|
||||
QSortFilterProxyModel *m_filterProxy;
|
||||
VersionProxyModel *m_versionProxy;
|
||||
Ui::PackagesPage *ui;
|
||||
QSortFilterProxyModel *m_fileProxy;
|
||||
QSortFilterProxyModel *m_filterProxy;
|
||||
VersionProxyModel *m_versionProxy;
|
||||
|
||||
void updateVersion();
|
||||
void updateVersion();
|
||||
};
|
||||
|
@ -26,56 +26,56 @@
|
||||
#include "MultiMC.h"
|
||||
|
||||
PasteEEPage::PasteEEPage(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::PasteEEPage)
|
||||
QWidget(parent),
|
||||
ui(new Ui::PasteEEPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();\
|
||||
connect(ui->customAPIkeyEdit, &QLineEdit::textEdited, this, &PasteEEPage::textEdited);
|
||||
loadSettings();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();\
|
||||
connect(ui->customAPIkeyEdit, &QLineEdit::textEdited, this, &PasteEEPage::textEdited);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
PasteEEPage::~PasteEEPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PasteEEPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
QString keyToUse = s->get("PasteEEAPIKey").toString();
|
||||
if(keyToUse == "multimc")
|
||||
{
|
||||
ui->multimcButton->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->customButton->setChecked(true);
|
||||
ui->customAPIkeyEdit->setText(keyToUse);
|
||||
}
|
||||
auto s = MMC->settings();
|
||||
QString keyToUse = s->get("PasteEEAPIKey").toString();
|
||||
if(keyToUse == "multimc")
|
||||
{
|
||||
ui->multimcButton->setChecked(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->customButton->setChecked(true);
|
||||
ui->customAPIkeyEdit->setText(keyToUse);
|
||||
}
|
||||
}
|
||||
|
||||
void PasteEEPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
QString pasteKeyToUse;
|
||||
if (ui->customButton->isChecked())
|
||||
pasteKeyToUse = ui->customAPIkeyEdit->text();
|
||||
else
|
||||
{
|
||||
pasteKeyToUse = "multimc";
|
||||
}
|
||||
s->set("PasteEEAPIKey", pasteKeyToUse);
|
||||
QString pasteKeyToUse;
|
||||
if (ui->customButton->isChecked())
|
||||
pasteKeyToUse = ui->customAPIkeyEdit->text();
|
||||
else
|
||||
{
|
||||
pasteKeyToUse = "multimc";
|
||||
}
|
||||
s->set("PasteEEAPIKey", pasteKeyToUse);
|
||||
}
|
||||
|
||||
bool PasteEEPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PasteEEPage::textEdited(const QString& text)
|
||||
{
|
||||
ui->customButton->setChecked(true);
|
||||
ui->customButton->setChecked(true);
|
||||
}
|
||||
|
@ -26,37 +26,37 @@ class PasteEEPage;
|
||||
|
||||
class PasteEEPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PasteEEPage(QWidget *parent = 0);
|
||||
~PasteEEPage();
|
||||
explicit PasteEEPage(QWidget *parent = 0);
|
||||
~PasteEEPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Log Upload");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "log-upload";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Log-Upload";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Log Upload");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "log-upload";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Log-Upload";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
|
||||
private slots:
|
||||
void textEdited(const QString &text);
|
||||
void textEdited(const QString &text);
|
||||
|
||||
private:
|
||||
Ui::PasteEEPage *ui;
|
||||
Ui::PasteEEPage *ui;
|
||||
};
|
||||
|
@ -23,75 +23,75 @@
|
||||
|
||||
ProxyPage::ProxyPage(QWidget *parent) : QWidget(parent), ui(new Ui::ProxyPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
loadSettings();
|
||||
updateCheckboxStuff();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
loadSettings();
|
||||
updateCheckboxStuff();
|
||||
|
||||
connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
|
||||
connect(ui->proxyGroup, SIGNAL(buttonClicked(int)), SLOT(proxyChanged(int)));
|
||||
}
|
||||
|
||||
ProxyPage::~ProxyPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ProxyPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProxyPage::updateCheckboxStuff()
|
||||
{
|
||||
ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
|
||||
!ui->proxyDefaultBtn->isChecked());
|
||||
ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
|
||||
!ui->proxyDefaultBtn->isChecked());
|
||||
ui->proxyAddrBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
|
||||
!ui->proxyDefaultBtn->isChecked());
|
||||
ui->proxyAuthBox->setEnabled(!ui->proxyNoneBtn->isChecked() &&
|
||||
!ui->proxyDefaultBtn->isChecked());
|
||||
}
|
||||
|
||||
void ProxyPage::proxyChanged(int)
|
||||
{
|
||||
updateCheckboxStuff();
|
||||
updateCheckboxStuff();
|
||||
}
|
||||
|
||||
void ProxyPage::applySettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
auto s = MMC->settings();
|
||||
|
||||
// Proxy
|
||||
QString proxyType = "None";
|
||||
if (ui->proxyDefaultBtn->isChecked())
|
||||
proxyType = "Default";
|
||||
else if (ui->proxyNoneBtn->isChecked())
|
||||
proxyType = "None";
|
||||
else if (ui->proxySOCKS5Btn->isChecked())
|
||||
proxyType = "SOCKS5";
|
||||
else if (ui->proxyHTTPBtn->isChecked())
|
||||
proxyType = "HTTP";
|
||||
// Proxy
|
||||
QString proxyType = "None";
|
||||
if (ui->proxyDefaultBtn->isChecked())
|
||||
proxyType = "Default";
|
||||
else if (ui->proxyNoneBtn->isChecked())
|
||||
proxyType = "None";
|
||||
else if (ui->proxySOCKS5Btn->isChecked())
|
||||
proxyType = "SOCKS5";
|
||||
else if (ui->proxyHTTPBtn->isChecked())
|
||||
proxyType = "HTTP";
|
||||
|
||||
s->set("ProxyType", proxyType);
|
||||
s->set("ProxyAddr", ui->proxyAddrEdit->text());
|
||||
s->set("ProxyPort", ui->proxyPortEdit->value());
|
||||
s->set("ProxyUser", ui->proxyUserEdit->text());
|
||||
s->set("ProxyPass", ui->proxyPassEdit->text());
|
||||
s->set("ProxyType", proxyType);
|
||||
s->set("ProxyAddr", ui->proxyAddrEdit->text());
|
||||
s->set("ProxyPort", ui->proxyPortEdit->value());
|
||||
s->set("ProxyUser", ui->proxyUserEdit->text());
|
||||
s->set("ProxyPass", ui->proxyPassEdit->text());
|
||||
}
|
||||
void ProxyPage::loadSettings()
|
||||
{
|
||||
auto s = MMC->settings();
|
||||
// Proxy
|
||||
QString proxyType = s->get("ProxyType").toString();
|
||||
if (proxyType == "Default")
|
||||
ui->proxyDefaultBtn->setChecked(true);
|
||||
else if (proxyType == "None")
|
||||
ui->proxyNoneBtn->setChecked(true);
|
||||
else if (proxyType == "SOCKS5")
|
||||
ui->proxySOCKS5Btn->setChecked(true);
|
||||
else if (proxyType == "HTTP")
|
||||
ui->proxyHTTPBtn->setChecked(true);
|
||||
auto s = MMC->settings();
|
||||
// Proxy
|
||||
QString proxyType = s->get("ProxyType").toString();
|
||||
if (proxyType == "Default")
|
||||
ui->proxyDefaultBtn->setChecked(true);
|
||||
else if (proxyType == "None")
|
||||
ui->proxyNoneBtn->setChecked(true);
|
||||
else if (proxyType == "SOCKS5")
|
||||
ui->proxySOCKS5Btn->setChecked(true);
|
||||
else if (proxyType == "HTTP")
|
||||
ui->proxyHTTPBtn->setChecked(true);
|
||||
|
||||
ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
|
||||
ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
|
||||
ui->proxyUserEdit->setText(s->get("ProxyUser").toString());
|
||||
ui->proxyPassEdit->setText(s->get("ProxyPass").toString());
|
||||
ui->proxyAddrEdit->setText(s->get("ProxyAddr").toString());
|
||||
ui->proxyPortEdit->setValue(s->get("ProxyPort").value<qint16>());
|
||||
ui->proxyUserEdit->setText(s->get("ProxyUser").toString());
|
||||
ui->proxyPassEdit->setText(s->get("ProxyPass").toString());
|
||||
}
|
||||
|
@ -28,39 +28,39 @@ class ProxyPage;
|
||||
|
||||
class ProxyPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProxyPage(QWidget *parent = 0);
|
||||
~ProxyPage();
|
||||
explicit ProxyPage(QWidget *parent = 0);
|
||||
~ProxyPage();
|
||||
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Proxy");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("proxy");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "proxy-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Proxy-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
QString displayName() const override
|
||||
{
|
||||
return tr("Proxy");
|
||||
}
|
||||
QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("proxy");
|
||||
}
|
||||
QString id() const override
|
||||
{
|
||||
return "proxy-settings";
|
||||
}
|
||||
QString helpPage() const override
|
||||
{
|
||||
return "Proxy-settings";
|
||||
}
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void updateCheckboxStuff();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void updateCheckboxStuff();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
private
|
||||
slots:
|
||||
void proxyChanged(int);
|
||||
void proxyChanged(int);
|
||||
|
||||
private:
|
||||
Ui::ProxyPage *ui;
|
||||
Ui::ProxyPage *ui;
|
||||
};
|
||||
|
@ -15,237 +15,237 @@
|
||||
#include <widgets/CustomCommands.h>
|
||||
|
||||
InstanceSettingsPage::InstanceSettingsPage(BaseInstance *inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
|
||||
: QWidget(parent), ui(new Ui::InstanceSettingsPage), m_instance(inst)
|
||||
{
|
||||
m_settings = inst->settings();
|
||||
ui->setupUi(this);
|
||||
auto sysMB = Sys::getSystemRam() / Sys::megabyte;
|
||||
ui->maxMemSpinBox->setMaximum(sysMB);
|
||||
loadSettings();
|
||||
m_settings = inst->settings();
|
||||
ui->setupUi(this);
|
||||
auto sysMB = Sys::getSystemRam() / Sys::megabyte;
|
||||
ui->maxMemSpinBox->setMaximum(sysMB);
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::shouldDisplay() const
|
||||
{
|
||||
return !m_instance->isRunning();
|
||||
return !m_instance->isRunning();
|
||||
}
|
||||
|
||||
InstanceSettingsPage::~InstanceSettingsPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool InstanceSettingsPage::apply()
|
||||
{
|
||||
applySettings();
|
||||
return true;
|
||||
applySettings();
|
||||
return true;
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::applySettings()
|
||||
{
|
||||
SettingsObject::Lock lock(m_settings);
|
||||
SettingsObject::Lock lock(m_settings);
|
||||
|
||||
// Console
|
||||
bool console = ui->consoleSettingsBox->isChecked();
|
||||
m_settings->set("OverrideConsole", console);
|
||||
if (console)
|
||||
{
|
||||
m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
m_settings->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("ShowConsole");
|
||||
m_settings->reset("AutoCloseConsole");
|
||||
m_settings->reset("ShowConsoleOnError");
|
||||
}
|
||||
// Console
|
||||
bool console = ui->consoleSettingsBox->isChecked();
|
||||
m_settings->set("OverrideConsole", console);
|
||||
if (console)
|
||||
{
|
||||
m_settings->set("ShowConsole", ui->showConsoleCheck->isChecked());
|
||||
m_settings->set("AutoCloseConsole", ui->autoCloseConsoleCheck->isChecked());
|
||||
m_settings->set("ShowConsoleOnError", ui->showConsoleErrorCheck->isChecked());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("ShowConsole");
|
||||
m_settings->reset("AutoCloseConsole");
|
||||
m_settings->reset("ShowConsoleOnError");
|
||||
}
|
||||
|
||||
// Window Size
|
||||
bool window = ui->windowSizeGroupBox->isChecked();
|
||||
m_settings->set("OverrideWindow", window);
|
||||
if (window)
|
||||
{
|
||||
m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
|
||||
m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
|
||||
m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("LaunchMaximized");
|
||||
m_settings->reset("MinecraftWinWidth");
|
||||
m_settings->reset("MinecraftWinHeight");
|
||||
}
|
||||
// Window Size
|
||||
bool window = ui->windowSizeGroupBox->isChecked();
|
||||
m_settings->set("OverrideWindow", window);
|
||||
if (window)
|
||||
{
|
||||
m_settings->set("LaunchMaximized", ui->maximizedCheckBox->isChecked());
|
||||
m_settings->set("MinecraftWinWidth", ui->windowWidthSpinBox->value());
|
||||
m_settings->set("MinecraftWinHeight", ui->windowHeightSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("LaunchMaximized");
|
||||
m_settings->reset("MinecraftWinWidth");
|
||||
m_settings->reset("MinecraftWinHeight");
|
||||
}
|
||||
|
||||
// Memory
|
||||
bool memory = ui->memoryGroupBox->isChecked();
|
||||
m_settings->set("OverrideMemory", memory);
|
||||
if (memory)
|
||||
{
|
||||
int min = ui->minMemSpinBox->value();
|
||||
int max = ui->maxMemSpinBox->value();
|
||||
if(min < max)
|
||||
{
|
||||
m_settings->set("MinMemAlloc", min);
|
||||
m_settings->set("MaxMemAlloc", max);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->set("MinMemAlloc", max);
|
||||
m_settings->set("MaxMemAlloc", min);
|
||||
}
|
||||
m_settings->set("PermGen", ui->permGenSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("MinMemAlloc");
|
||||
m_settings->reset("MaxMemAlloc");
|
||||
m_settings->reset("PermGen");
|
||||
}
|
||||
// Memory
|
||||
bool memory = ui->memoryGroupBox->isChecked();
|
||||
m_settings->set("OverrideMemory", memory);
|
||||
if (memory)
|
||||
{
|
||||
int min = ui->minMemSpinBox->value();
|
||||
int max = ui->maxMemSpinBox->value();
|
||||
if(min < max)
|
||||
{
|
||||
m_settings->set("MinMemAlloc", min);
|
||||
m_settings->set("MaxMemAlloc", max);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->set("MinMemAlloc", max);
|
||||
m_settings->set("MaxMemAlloc", min);
|
||||
}
|
||||
m_settings->set("PermGen", ui->permGenSpinBox->value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("MinMemAlloc");
|
||||
m_settings->reset("MaxMemAlloc");
|
||||
m_settings->reset("PermGen");
|
||||
}
|
||||
|
||||
// Java Install Settings
|
||||
bool javaInstall = ui->javaSettingsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaLocation", javaInstall);
|
||||
if (javaInstall)
|
||||
{
|
||||
m_settings->set("JavaPath", ui->javaPathTextBox->text());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JavaPath");
|
||||
}
|
||||
// Java Install Settings
|
||||
bool javaInstall = ui->javaSettingsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaLocation", javaInstall);
|
||||
if (javaInstall)
|
||||
{
|
||||
m_settings->set("JavaPath", ui->javaPathTextBox->text());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JavaPath");
|
||||
}
|
||||
|
||||
// Java arguments
|
||||
bool javaArgs = ui->javaArgumentsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaArgs", javaArgs);
|
||||
if(javaArgs)
|
||||
{
|
||||
m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
|
||||
JavaCommon::checkJVMArgs(m_settings->get("JvmArgs").toString(), this->parentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JvmArgs");
|
||||
}
|
||||
// Java arguments
|
||||
bool javaArgs = ui->javaArgumentsGroupBox->isChecked();
|
||||
m_settings->set("OverrideJavaArgs", javaArgs);
|
||||
if(javaArgs)
|
||||
{
|
||||
m_settings->set("JvmArgs", ui->jvmArgsTextBox->toPlainText().replace("\n", " "));
|
||||
JavaCommon::checkJVMArgs(m_settings->get("JvmArgs").toString(), this->parentWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("JvmArgs");
|
||||
}
|
||||
|
||||
// old generic 'override both' is removed.
|
||||
m_settings->reset("OverrideJava");
|
||||
// old generic 'override both' is removed.
|
||||
m_settings->reset("OverrideJava");
|
||||
|
||||
// Custom Commands
|
||||
bool custcmd = ui->customCommands->checked();
|
||||
m_settings->set("OverrideCommands", custcmd);
|
||||
if (custcmd)
|
||||
{
|
||||
m_settings->set("PreLaunchCommand", ui->customCommands->prelaunchCommand());
|
||||
m_settings->set("WrapperCommand", ui->customCommands->wrapperCommand());
|
||||
m_settings->set("PostExitCommand", ui->customCommands->postexitCommand());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("PreLaunchCommand");
|
||||
m_settings->reset("WrapperCommand");
|
||||
m_settings->reset("PostExitCommand");
|
||||
}
|
||||
// Custom Commands
|
||||
bool custcmd = ui->customCommands->checked();
|
||||
m_settings->set("OverrideCommands", custcmd);
|
||||
if (custcmd)
|
||||
{
|
||||
m_settings->set("PreLaunchCommand", ui->customCommands->prelaunchCommand());
|
||||
m_settings->set("WrapperCommand", ui->customCommands->wrapperCommand());
|
||||
m_settings->set("PostExitCommand", ui->customCommands->postexitCommand());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings->reset("PreLaunchCommand");
|
||||
m_settings->reset("WrapperCommand");
|
||||
m_settings->reset("PostExitCommand");
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::loadSettings()
|
||||
{
|
||||
// Console
|
||||
ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool());
|
||||
ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(m_settings->get("AutoCloseConsole").toBool());
|
||||
ui->showConsoleErrorCheck->setChecked(m_settings->get("ShowConsoleOnError").toBool());
|
||||
// Console
|
||||
ui->consoleSettingsBox->setChecked(m_settings->get("OverrideConsole").toBool());
|
||||
ui->showConsoleCheck->setChecked(m_settings->get("ShowConsole").toBool());
|
||||
ui->autoCloseConsoleCheck->setChecked(m_settings->get("AutoCloseConsole").toBool());
|
||||
ui->showConsoleErrorCheck->setChecked(m_settings->get("ShowConsoleOnError").toBool());
|
||||
|
||||
// Window Size
|
||||
ui->windowSizeGroupBox->setChecked(m_settings->get("OverrideWindow").toBool());
|
||||
ui->maximizedCheckBox->setChecked(m_settings->get("LaunchMaximized").toBool());
|
||||
ui->windowWidthSpinBox->setValue(m_settings->get("MinecraftWinWidth").toInt());
|
||||
ui->windowHeightSpinBox->setValue(m_settings->get("MinecraftWinHeight").toInt());
|
||||
// Window Size
|
||||
ui->windowSizeGroupBox->setChecked(m_settings->get("OverrideWindow").toBool());
|
||||
ui->maximizedCheckBox->setChecked(m_settings->get("LaunchMaximized").toBool());
|
||||
ui->windowWidthSpinBox->setValue(m_settings->get("MinecraftWinWidth").toInt());
|
||||
ui->windowHeightSpinBox->setValue(m_settings->get("MinecraftWinHeight").toInt());
|
||||
|
||||
// Memory
|
||||
ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool());
|
||||
int min = m_settings->get("MinMemAlloc").toInt();
|
||||
int max = m_settings->get("MaxMemAlloc").toInt();
|
||||
if(min < max)
|
||||
{
|
||||
ui->minMemSpinBox->setValue(min);
|
||||
ui->maxMemSpinBox->setValue(max);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->minMemSpinBox->setValue(max);
|
||||
ui->maxMemSpinBox->setValue(min);
|
||||
}
|
||||
ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt());
|
||||
// Memory
|
||||
ui->memoryGroupBox->setChecked(m_settings->get("OverrideMemory").toBool());
|
||||
int min = m_settings->get("MinMemAlloc").toInt();
|
||||
int max = m_settings->get("MaxMemAlloc").toInt();
|
||||
if(min < max)
|
||||
{
|
||||
ui->minMemSpinBox->setValue(min);
|
||||
ui->maxMemSpinBox->setValue(max);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->minMemSpinBox->setValue(max);
|
||||
ui->maxMemSpinBox->setValue(min);
|
||||
}
|
||||
ui->permGenSpinBox->setValue(m_settings->get("PermGen").toInt());
|
||||
|
||||
// Java Settings
|
||||
bool overrideJava = m_settings->get("OverrideJava").toBool();
|
||||
bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava;
|
||||
bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava;
|
||||
// Java Settings
|
||||
bool overrideJava = m_settings->get("OverrideJava").toBool();
|
||||
bool overrideLocation = m_settings->get("OverrideJavaLocation").toBool() || overrideJava;
|
||||
bool overrideArgs = m_settings->get("OverrideJavaArgs").toBool() || overrideJava;
|
||||
|
||||
ui->javaSettingsGroupBox->setChecked(overrideLocation);
|
||||
ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString());
|
||||
ui->javaSettingsGroupBox->setChecked(overrideLocation);
|
||||
ui->javaPathTextBox->setText(m_settings->get("JavaPath").toString());
|
||||
|
||||
ui->javaArgumentsGroupBox->setChecked(overrideArgs);
|
||||
ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString());
|
||||
ui->javaArgumentsGroupBox->setChecked(overrideArgs);
|
||||
ui->jvmArgsTextBox->setPlainText(m_settings->get("JvmArgs").toString());
|
||||
|
||||
// Custom commands
|
||||
ui->customCommands->initialize(
|
||||
true,
|
||||
m_settings->get("OverrideCommands").toBool(),
|
||||
m_settings->get("PreLaunchCommand").toString(),
|
||||
m_settings->get("WrapperCommand").toString(),
|
||||
m_settings->get("PostExitCommand").toString()
|
||||
);
|
||||
// Custom commands
|
||||
ui->customCommands->initialize(
|
||||
true,
|
||||
m_settings->get("OverrideCommands").toBool(),
|
||||
m_settings->get("PreLaunchCommand").toString(),
|
||||
m_settings->get("WrapperCommand").toString(),
|
||||
m_settings->get("PostExitCommand").toString()
|
||||
);
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaDetectBtn_clicked()
|
||||
{
|
||||
JavaInstallPtr java;
|
||||
JavaInstallPtr java;
|
||||
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
VersionSelectDialog vselect(MMC->javalist().get(), tr("Select a Java version"), this, true);
|
||||
vselect.setResizeOn(2);
|
||||
vselect.exec();
|
||||
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
if (vselect.result() == QDialog::Accepted && vselect.selectedVersion())
|
||||
{
|
||||
java = std::dynamic_pointer_cast<JavaInstall>(vselect.selectedVersion());
|
||||
ui->javaPathTextBox->setText(java->path);
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaBrowseBtn_clicked()
|
||||
{
|
||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
QString raw_path = QFileDialog::getOpenFileName(this, tr("Find Java executable"));
|
||||
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if(raw_path.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString cooked_path = FS::NormalizePath(raw_path);
|
||||
// do not allow current dir - it's dirty. Do not allow dirs that don't exist
|
||||
if(raw_path.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString cooked_path = FS::NormalizePath(raw_path);
|
||||
|
||||
QFileInfo javaInfo(cooked_path);;
|
||||
if(!javaInfo.exists() || !javaInfo.isExecutable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
ui->javaPathTextBox->setText(cooked_path);
|
||||
QFileInfo javaInfo(cooked_path);;
|
||||
if(!javaInfo.exists() || !javaInfo.isExecutable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
ui->javaPathTextBox->setText(cooked_path);
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::on_javaTestBtn_clicked()
|
||||
{
|
||||
if(checker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaCommon::TestCheck(
|
||||
this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "),
|
||||
ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value()));
|
||||
connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished()));
|
||||
checker->run();
|
||||
if(checker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
checker.reset(new JavaCommon::TestCheck(
|
||||
this, ui->javaPathTextBox->text(), ui->jvmArgsTextBox->toPlainText().replace("\n", " "),
|
||||
ui->minMemSpinBox->value(), ui->maxMemSpinBox->value(), ui->permGenSpinBox->value()));
|
||||
connect(checker.get(), SIGNAL(finished()), SLOT(checkerFinished()));
|
||||
checker->run();
|
||||
}
|
||||
|
||||
void InstanceSettingsPage::checkerFinished()
|
||||
{
|
||||
checker.reset();
|
||||
checker.reset();
|
||||
}
|
||||
|
@ -32,43 +32,43 @@ class InstanceSettingsPage;
|
||||
|
||||
class InstanceSettingsPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0);
|
||||
virtual ~InstanceSettingsPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Settings");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("instance-settings");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "settings";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Instance-settings";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
explicit InstanceSettingsPage(BaseInstance *inst, QWidget *parent = 0);
|
||||
virtual ~InstanceSettingsPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Settings");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("instance-settings");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "settings";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Instance-settings";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
|
||||
private slots:
|
||||
void on_javaDetectBtn_clicked();
|
||||
void on_javaTestBtn_clicked();
|
||||
void on_javaBrowseBtn_clicked();
|
||||
void on_javaDetectBtn_clicked();
|
||||
void on_javaTestBtn_clicked();
|
||||
void on_javaBrowseBtn_clicked();
|
||||
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
void applySettings();
|
||||
void loadSettings();
|
||||
|
||||
void checkerFinished();
|
||||
void checkerFinished();
|
||||
|
||||
private:
|
||||
Ui::InstanceSettingsPage *ui;
|
||||
BaseInstance *m_instance;
|
||||
SettingsObjectPtr m_settings;
|
||||
unique_qobject_ptr<JavaCommon::TestCheck> checker;
|
||||
Ui::InstanceSettingsPage *ui;
|
||||
BaseInstance *m_instance;
|
||||
SettingsObjectPtr m_settings;
|
||||
unique_qobject_ptr<JavaCommon::TestCheck> checker;
|
||||
};
|
||||
|
@ -9,42 +9,42 @@
|
||||
#include "dialogs/ProgressDialog.h"
|
||||
|
||||
LegacyUpgradePage::LegacyUpgradePage(InstancePtr inst, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst)
|
||||
: QWidget(parent), ui(new Ui::LegacyUpgradePage), m_inst(inst)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
LegacyUpgradePage::~LegacyUpgradePage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LegacyUpgradePage::runModalTask(Task *task)
|
||||
{
|
||||
connect(task, &Task::failed, [this](QString reason)
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
|
||||
});
|
||||
ProgressDialog loadDialog(this);
|
||||
loadDialog.setSkipButton(true, tr("Abort"));
|
||||
if(loadDialog.execWithTask(task) == QDialog::Accepted)
|
||||
{
|
||||
m_container->requestClose();
|
||||
}
|
||||
connect(task, &Task::failed, [this](QString reason)
|
||||
{
|
||||
CustomMessageBox::selectable(this, tr("Error"), reason, QMessageBox::Warning)->show();
|
||||
});
|
||||
ProgressDialog loadDialog(this);
|
||||
loadDialog.setSkipButton(true, tr("Abort"));
|
||||
if(loadDialog.execWithTask(task) == QDialog::Accepted)
|
||||
{
|
||||
m_container->requestClose();
|
||||
}
|
||||
}
|
||||
|
||||
void LegacyUpgradePage::on_upgradeButton_clicked()
|
||||
{
|
||||
QString newName = tr("%1 (Migrated)").arg(m_inst->name());
|
||||
auto upgradeTask = new LegacyUpgradeTask(m_inst);
|
||||
upgradeTask->setName(newName);
|
||||
upgradeTask->setGroup(m_inst->group());
|
||||
upgradeTask->setIcon(m_inst->iconKey());
|
||||
std::unique_ptr<Task> task(MMC->folderProvider()->wrapInstanceTask(upgradeTask));
|
||||
runModalTask(task.get());
|
||||
QString newName = tr("%1 (Migrated)").arg(m_inst->name());
|
||||
auto upgradeTask = new LegacyUpgradeTask(m_inst);
|
||||
upgradeTask->setName(newName);
|
||||
upgradeTask->setGroup(m_inst->group());
|
||||
upgradeTask->setIcon(m_inst->iconKey());
|
||||
std::unique_ptr<Task> task(MMC->folderProvider()->wrapInstanceTask(upgradeTask));
|
||||
runModalTask(task.get());
|
||||
}
|
||||
|
||||
bool LegacyUpgradePage::shouldDisplay() const
|
||||
{
|
||||
return !m_inst->isRunning();
|
||||
return !m_inst->isRunning();
|
||||
}
|
||||
|
@ -29,36 +29,36 @@ class LegacyUpgradePage;
|
||||
|
||||
class LegacyUpgradePage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0);
|
||||
virtual ~LegacyUpgradePage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Upgrade");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("checkupdate");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "upgrade";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Legacy-upgrade";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
explicit LegacyUpgradePage(InstancePtr inst, QWidget *parent = 0);
|
||||
virtual ~LegacyUpgradePage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Upgrade");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("checkupdate");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "upgrade";
|
||||
}
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Legacy-upgrade";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
|
||||
private slots:
|
||||
void on_upgradeButton_clicked();
|
||||
void on_upgradeButton_clicked();
|
||||
|
||||
private:
|
||||
void runModalTask(Task *task);
|
||||
void runModalTask(Task *task);
|
||||
|
||||
private:
|
||||
Ui::LegacyUpgradePage *ui;
|
||||
InstancePtr m_inst;
|
||||
Ui::LegacyUpgradePage *ui;
|
||||
InstancePtr m_inst;
|
||||
};
|
||||
|
@ -15,298 +15,298 @@
|
||||
class LogFormatProxyModel : public QIdentityProxyModel
|
||||
{
|
||||
public:
|
||||
LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent)
|
||||
{
|
||||
}
|
||||
QVariant data(const QModelIndex &index, int role) const override
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
case Qt::FontRole:
|
||||
return m_font;
|
||||
case Qt::TextColorRole:
|
||||
{
|
||||
MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt();
|
||||
return m_colors->getFront(level);
|
||||
}
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt();
|
||||
return m_colors->getBack(level);
|
||||
}
|
||||
default:
|
||||
return QIdentityProxyModel::data(index, role);
|
||||
}
|
||||
}
|
||||
LogFormatProxyModel(QObject* parent = nullptr) : QIdentityProxyModel(parent)
|
||||
{
|
||||
}
|
||||
QVariant data(const QModelIndex &index, int role) const override
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
case Qt::FontRole:
|
||||
return m_font;
|
||||
case Qt::TextColorRole:
|
||||
{
|
||||
MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt();
|
||||
return m_colors->getFront(level);
|
||||
}
|
||||
case Qt::BackgroundRole:
|
||||
{
|
||||
MessageLevel::Enum level = (MessageLevel::Enum) QIdentityProxyModel::data(index, LogModel::LevelRole).toInt();
|
||||
return m_colors->getBack(level);
|
||||
}
|
||||
default:
|
||||
return QIdentityProxyModel::data(index, role);
|
||||
}
|
||||
}
|
||||
|
||||
void setFont(QFont font)
|
||||
{
|
||||
m_font = font;
|
||||
}
|
||||
void setFont(QFont font)
|
||||
{
|
||||
m_font = font;
|
||||
}
|
||||
|
||||
void setColors(LogColorCache* colors)
|
||||
{
|
||||
m_colors.reset(colors);
|
||||
}
|
||||
void setColors(LogColorCache* colors)
|
||||
{
|
||||
m_colors.reset(colors);
|
||||
}
|
||||
|
||||
QModelIndex find(const QModelIndex &start, const QString &value, bool reverse) const
|
||||
{
|
||||
QModelIndex parentIndex = parent(start);
|
||||
auto compare = [&](int r) -> QModelIndex
|
||||
{
|
||||
QModelIndex idx = index(r, start.column(), parentIndex);
|
||||
if (!idx.isValid() || idx == start)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
QVariant v = data(idx, Qt::DisplayRole);
|
||||
QString t = v.toString();
|
||||
if (t.contains(value, Qt::CaseInsensitive))
|
||||
return idx;
|
||||
return QModelIndex();
|
||||
};
|
||||
if(reverse)
|
||||
{
|
||||
int from = start.row();
|
||||
int to = 0;
|
||||
QModelIndex find(const QModelIndex &start, const QString &value, bool reverse) const
|
||||
{
|
||||
QModelIndex parentIndex = parent(start);
|
||||
auto compare = [&](int r) -> QModelIndex
|
||||
{
|
||||
QModelIndex idx = index(r, start.column(), parentIndex);
|
||||
if (!idx.isValid() || idx == start)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
QVariant v = data(idx, Qt::DisplayRole);
|
||||
QString t = v.toString();
|
||||
if (t.contains(value, Qt::CaseInsensitive))
|
||||
return idx;
|
||||
return QModelIndex();
|
||||
};
|
||||
if(reverse)
|
||||
{
|
||||
int from = start.row();
|
||||
int to = 0;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
for (int r = from; (r >= to); --r)
|
||||
{
|
||||
auto idx = compare(r);
|
||||
if(idx.isValid())
|
||||
return idx;
|
||||
}
|
||||
// prepare for the next iteration
|
||||
from = rowCount() - 1;
|
||||
to = start.row();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int from = start.row();
|
||||
int to = rowCount(parentIndex);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
for (int r = from; (r >= to); --r)
|
||||
{
|
||||
auto idx = compare(r);
|
||||
if(idx.isValid())
|
||||
return idx;
|
||||
}
|
||||
// prepare for the next iteration
|
||||
from = rowCount() - 1;
|
||||
to = start.row();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int from = start.row();
|
||||
int to = rowCount(parentIndex);
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
for (int r = from; (r < to); ++r)
|
||||
{
|
||||
auto idx = compare(r);
|
||||
if(idx.isValid())
|
||||
return idx;
|
||||
}
|
||||
// prepare for the next iteration
|
||||
from = 0;
|
||||
to = start.row();
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
for (int r = from; (r < to); ++r)
|
||||
{
|
||||
auto idx = compare(r);
|
||||
if(idx.isValid())
|
||||
return idx;
|
||||
}
|
||||
// prepare for the next iteration
|
||||
from = 0;
|
||||
to = start.row();
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
private:
|
||||
QFont m_font;
|
||||
std::unique_ptr<LogColorCache> m_colors;
|
||||
QFont m_font;
|
||||
std::unique_ptr<LogColorCache> m_colors;
|
||||
};
|
||||
|
||||
LogPage::LogPage(InstancePtr instance, QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::LogPage), m_instance(instance)
|
||||
: QWidget(parent), ui(new Ui::LogPage), m_instance(instance)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
|
||||
m_proxy = new LogFormatProxyModel(this);
|
||||
// set up text colors in the log proxy and adapt them to the current theme foreground and background
|
||||
{
|
||||
auto origForeground = ui->text->palette().color(ui->text->foregroundRole());
|
||||
auto origBackground = ui->text->palette().color(ui->text->backgroundRole());
|
||||
m_proxy->setColors(new LogColorCache(origForeground, origBackground));
|
||||
}
|
||||
m_proxy = new LogFormatProxyModel(this);
|
||||
// set up text colors in the log proxy and adapt them to the current theme foreground and background
|
||||
{
|
||||
auto origForeground = ui->text->palette().color(ui->text->foregroundRole());
|
||||
auto origBackground = ui->text->palette().color(ui->text->backgroundRole());
|
||||
m_proxy->setColors(new LogColorCache(origForeground, origBackground));
|
||||
}
|
||||
|
||||
// set up fonts in the log proxy
|
||||
{
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
bool conversionOk = false;
|
||||
int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
fontSize = 11;
|
||||
}
|
||||
m_proxy->setFont(QFont(fontFamily, fontSize));
|
||||
}
|
||||
// set up fonts in the log proxy
|
||||
{
|
||||
QString fontFamily = MMC->settings()->get("ConsoleFont").toString();
|
||||
bool conversionOk = false;
|
||||
int fontSize = MMC->settings()->get("ConsoleFontSize").toInt(&conversionOk);
|
||||
if(!conversionOk)
|
||||
{
|
||||
fontSize = 11;
|
||||
}
|
||||
m_proxy->setFont(QFont(fontFamily, fontSize));
|
||||
}
|
||||
|
||||
ui->text->setModel(m_proxy);
|
||||
ui->text->setModel(m_proxy);
|
||||
|
||||
// set up instance and launch process recognition
|
||||
{
|
||||
auto launchTask = m_instance->getLaunchTask();
|
||||
if(launchTask)
|
||||
{
|
||||
setInstanceLaunchTaskChanged(launchTask, true);
|
||||
}
|
||||
connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::onInstanceLaunchTaskChanged);
|
||||
}
|
||||
// set up instance and launch process recognition
|
||||
{
|
||||
auto launchTask = m_instance->getLaunchTask();
|
||||
if(launchTask)
|
||||
{
|
||||
setInstanceLaunchTaskChanged(launchTask, true);
|
||||
}
|
||||
connect(m_instance.get(), &BaseInstance::launchTaskChanged, this, &LogPage::onInstanceLaunchTaskChanged);
|
||||
}
|
||||
|
||||
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
|
||||
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
|
||||
auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
|
||||
connect(findNextShortcut, SIGNAL(activated()), SLOT(findNextActivated()));
|
||||
connect(ui->searchBar, SIGNAL(returnPressed()), SLOT(on_findButton_clicked()));
|
||||
auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this);
|
||||
connect(findPreviousShortcut, SIGNAL(activated()), SLOT(findPreviousActivated()));
|
||||
auto findShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
|
||||
connect(findShortcut, SIGNAL(activated()), SLOT(findActivated()));
|
||||
auto findNextShortcut = new QShortcut(QKeySequence(QKeySequence::FindNext), this);
|
||||
connect(findNextShortcut, SIGNAL(activated()), SLOT(findNextActivated()));
|
||||
connect(ui->searchBar, SIGNAL(returnPressed()), SLOT(on_findButton_clicked()));
|
||||
auto findPreviousShortcut = new QShortcut(QKeySequence(QKeySequence::FindPrevious), this);
|
||||
connect(findPreviousShortcut, SIGNAL(activated()), SLOT(findPreviousActivated()));
|
||||
}
|
||||
|
||||
LogPage::~LogPage()
|
||||
{
|
||||
delete ui;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void LogPage::modelStateToUI()
|
||||
{
|
||||
if(m_model->wrapLines())
|
||||
{
|
||||
ui->text->setWordWrap(true);
|
||||
ui->wrapCheckbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->text->setWordWrap(false);
|
||||
ui->wrapCheckbox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
if(m_model->suspended())
|
||||
{
|
||||
ui->trackLogCheckbox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->trackLogCheckbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
if(m_model->wrapLines())
|
||||
{
|
||||
ui->text->setWordWrap(true);
|
||||
ui->wrapCheckbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->text->setWordWrap(false);
|
||||
ui->wrapCheckbox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
if(m_model->suspended())
|
||||
{
|
||||
ui->trackLogCheckbox->setCheckState(Qt::Unchecked);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->trackLogCheckbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::UIToModelState()
|
||||
{
|
||||
if(!m_model)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_model->setLineWrap(ui->wrapCheckbox->checkState() == Qt::Checked);
|
||||
m_model->suspend(ui->trackLogCheckbox->checkState() != Qt::Checked);
|
||||
if(!m_model)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_model->setLineWrap(ui->wrapCheckbox->checkState() == Qt::Checked);
|
||||
m_model->suspend(ui->trackLogCheckbox->checkState() != Qt::Checked);
|
||||
}
|
||||
|
||||
void LogPage::setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial)
|
||||
{
|
||||
m_process = proc;
|
||||
if(m_process)
|
||||
{
|
||||
m_model = proc->getLogModel();
|
||||
m_proxy->setSourceModel(m_model.get());
|
||||
if(initial)
|
||||
{
|
||||
modelStateToUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
UIToModelState();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_proxy->setSourceModel(nullptr);
|
||||
m_model.reset();
|
||||
}
|
||||
m_process = proc;
|
||||
if(m_process)
|
||||
{
|
||||
m_model = proc->getLogModel();
|
||||
m_proxy->setSourceModel(m_model.get());
|
||||
if(initial)
|
||||
{
|
||||
modelStateToUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
UIToModelState();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_proxy->setSourceModel(nullptr);
|
||||
m_model.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc)
|
||||
{
|
||||
setInstanceLaunchTaskChanged(proc, false);
|
||||
setInstanceLaunchTaskChanged(proc, false);
|
||||
}
|
||||
|
||||
bool LogPage::apply()
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LogPage::shouldDisplay() const
|
||||
{
|
||||
return m_instance->isRunning() || m_proxy->rowCount() > 0;
|
||||
return m_instance->isRunning() || m_proxy->rowCount() > 0;
|
||||
}
|
||||
|
||||
void LogPage::on_btnPaste_clicked()
|
||||
{
|
||||
if(!m_model)
|
||||
return;
|
||||
if(!m_model)
|
||||
return;
|
||||
|
||||
//FIXME: turn this into a proper task and move the upload logic out of GuiUtil!
|
||||
m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date)));
|
||||
auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this);
|
||||
if(!url.isEmpty())
|
||||
{
|
||||
m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log uploaded to: %1").arg(url));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->append(MessageLevel::Error, tr("MultiMC: Log upload failed!"));
|
||||
}
|
||||
//FIXME: turn this into a proper task and move the upload logic out of GuiUtil!
|
||||
m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log upload triggered at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date)));
|
||||
auto url = GuiUtil::uploadPaste(m_model->toPlainText(), this);
|
||||
if(!url.isEmpty())
|
||||
{
|
||||
m_model->append(MessageLevel::MultiMC, tr("MultiMC: Log uploaded to: %1").arg(url));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_model->append(MessageLevel::Error, tr("MultiMC: Log upload failed!"));
|
||||
}
|
||||
}
|
||||
|
||||
void LogPage::on_btnCopy_clicked()
|
||||
{
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->append(MessageLevel::MultiMC, QString("Clipboard copy at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date)));
|
||||
GuiUtil::setClipboardText(m_model->toPlainText());
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->append(MessageLevel::MultiMC, QString("Clipboard copy at: %1").arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date)));
|
||||
GuiUtil::setClipboardText(m_model->toPlainText());
|
||||
}
|
||||
|
||||
void LogPage::on_btnClear_clicked()
|
||||
{
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->clear();
|
||||
m_container->refreshContainer();
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->clear();
|
||||
m_container->refreshContainer();
|
||||
}
|
||||
|
||||
void LogPage::on_btnBottom_clicked()
|
||||
{
|
||||
ui->text->scrollToBottom();
|
||||
ui->text->scrollToBottom();
|
||||
}
|
||||
|
||||
void LogPage::on_trackLogCheckbox_clicked(bool checked)
|
||||
{
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->suspend(!checked);
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->suspend(!checked);
|
||||
}
|
||||
|
||||
void LogPage::on_wrapCheckbox_clicked(bool checked)
|
||||
{
|
||||
ui->text->setWordWrap(checked);
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->setLineWrap(checked);
|
||||
ui->text->setWordWrap(checked);
|
||||
if(!m_model)
|
||||
return;
|
||||
m_model->setLineWrap(checked);
|
||||
}
|
||||
|
||||
void LogPage::on_findButton_clicked()
|
||||
{
|
||||
auto modifiers = QApplication::keyboardModifiers();
|
||||
bool reverse = modifiers & Qt::ShiftModifier;
|
||||
ui->text->findNext(ui->searchBar->text(), reverse);
|
||||
auto modifiers = QApplication::keyboardModifiers();
|
||||
bool reverse = modifiers & Qt::ShiftModifier;
|
||||
ui->text->findNext(ui->searchBar->text(), reverse);
|
||||
}
|
||||
|
||||
void LogPage::findNextActivated()
|
||||
{
|
||||
ui->text->findNext(ui->searchBar->text(), false);
|
||||
ui->text->findNext(ui->searchBar->text(), false);
|
||||
}
|
||||
|
||||
void LogPage::findPreviousActivated()
|
||||
{
|
||||
ui->text->findNext(ui->searchBar->text(), true);
|
||||
ui->text->findNext(ui->searchBar->text(), true);
|
||||
}
|
||||
|
||||
void LogPage::findActivated()
|
||||
{
|
||||
// focus the search bar if it doesn't have focus
|
||||
if (!ui->searchBar->hasFocus())
|
||||
{
|
||||
ui->searchBar->setFocus();
|
||||
ui->searchBar->selectAll();
|
||||
}
|
||||
// focus the search bar if it doesn't have focus
|
||||
if (!ui->searchBar->hasFocus())
|
||||
{
|
||||
ui->searchBar->setFocus();
|
||||
ui->searchBar->selectAll();
|
||||
}
|
||||
}
|
||||
|
@ -31,56 +31,56 @@ class LogFormatProxyModel;
|
||||
|
||||
class LogPage : public QWidget, public BasePage
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogPage(InstancePtr instance, QWidget *parent = 0);
|
||||
virtual ~LogPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Minecraft Log");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "console";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-Logs";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
explicit LogPage(InstancePtr instance, QWidget *parent = 0);
|
||||
virtual ~LogPage();
|
||||
virtual QString displayName() const override
|
||||
{
|
||||
return tr("Minecraft Log");
|
||||
}
|
||||
virtual QIcon icon() const override
|
||||
{
|
||||
return MMC->getThemedIcon("log");
|
||||
}
|
||||
virtual QString id() const override
|
||||
{
|
||||
return "console";
|
||||
}
|
||||
virtual bool apply() override;
|
||||
virtual QString helpPage() const override
|
||||
{
|
||||
return "Minecraft-Logs";
|
||||
}
|
||||
virtual bool shouldDisplay() const override;
|
||||
|
||||
private slots:
|
||||
void on_btnPaste_clicked();
|
||||
void on_btnCopy_clicked();
|
||||
void on_btnClear_clicked();
|
||||
void on_btnBottom_clicked();
|
||||
void on_btnPaste_clicked();
|
||||
void on_btnCopy_clicked();
|
||||
void on_btnClear_clicked();
|
||||
void on_btnBottom_clicked();
|
||||
|
||||
void on_trackLogCheckbox_clicked(bool checked);
|
||||
void on_wrapCheckbox_clicked(bool checked);
|
||||
void on_trackLogCheckbox_clicked(bool checked);
|
||||
void on_wrapCheckbox_clicked(bool checked);
|
||||
|
||||
void on_findButton_clicked();
|
||||
void findActivated();
|
||||
void findNextActivated();
|
||||
void findPreviousActivated();
|
||||
void on_findButton_clicked();
|
||||
void findActivated();
|
||||
void findNextActivated();
|
||||
void findPreviousActivated();
|
||||
|
||||
void onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc);
|
||||
void onInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc);
|
||||
|
||||
private:
|
||||
void modelStateToUI();
|
||||
void UIToModelState();
|
||||
void setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial);
|
||||
void modelStateToUI();
|
||||
void UIToModelState();
|
||||
void setInstanceLaunchTaskChanged(std::shared_ptr<LaunchTask> proc, bool initial);
|
||||
|
||||
private:
|
||||
Ui::LogPage *ui;
|
||||
InstancePtr m_instance;
|
||||
std::shared_ptr<LaunchTask> m_process;
|
||||
Ui::LogPage *ui;
|
||||
InstancePtr m_instance;
|
||||
std::shared_ptr<LaunchTask> m_process;
|
||||
|
||||
LogFormatProxyModel * m_proxy;
|
||||
shared_qobject_ptr <LogModel> m_model;
|
||||
LogFormatProxyModel * m_proxy;
|
||||
shared_qobject_ptr <LogModel> m_model;
|
||||
};
|
||||
|
@ -32,179 +32,179 @@
|
||||
#include <DesktopServices.h>
|
||||
|
||||
ModFolderPage::ModFolderPage(BaseInstance *inst, std::shared_ptr<SimpleModList> mods, QString id,
|
||||
QString iconName, QString displayName, QString helpPage,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::ModFolderPage)
|
||||
QString iconName, QString displayName, QString helpPage,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::ModFolderPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
m_inst = inst;
|
||||
m_mods = mods;
|
||||
m_id = id;
|
||||
m_displayName = displayName;
|
||||
m_iconName = iconName;
|
||||
m_helpName = helpPage;
|
||||
m_fileSelectionFilter = "%1 (*.zip *.jar)";
|
||||
m_filterModel = new QSortFilterProxyModel(this);
|
||||
m_filterModel->setDynamicSortFilter(true);
|
||||
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterModel->setSourceModel(m_mods.get());
|
||||
m_filterModel->setFilterKeyColumn(-1);
|
||||
ui->modTreeView->setModel(m_filterModel);
|
||||
ui->modTreeView->installEventFilter(this);
|
||||
ui->modTreeView->sortByColumn(1, Qt::AscendingOrder);
|
||||
auto smodel = ui->modTreeView->selectionModel();
|
||||
connect(smodel, &QItemSelectionModel::currentChanged, this, &ModFolderPage::modCurrent);
|
||||
connect(ui->filterEdit, &QLineEdit::textChanged, this, &ModFolderPage::on_filterTextChanged );
|
||||
ui->setupUi(this);
|
||||
ui->tabWidget->tabBar()->hide();
|
||||
m_inst = inst;
|
||||
m_mods = mods;
|
||||
m_id = id;
|
||||
m_displayName = displayName;
|
||||
m_iconName = iconName;
|
||||
m_helpName = helpPage;
|
||||
m_fileSelectionFilter = "%1 (*.zip *.jar)";
|
||||
m_filterModel = new QSortFilterProxyModel(this);
|
||||
m_filterModel->setDynamicSortFilter(true);
|
||||
m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_filterModel->setSourceModel(m_mods.get());
|
||||
m_filterModel->setFilterKeyColumn(-1);
|
||||
ui->modTreeView->setModel(m_filterModel);
|
||||
ui->modTreeView->installEventFilter(this);
|
||||
ui->modTreeView->sortByColumn(1, Qt::AscendingOrder);
|
||||
auto smodel = ui->modTreeView->selectionModel();
|
||||
connect(smodel, &QItemSelectionModel::currentChanged, this, &ModFolderPage::modCurrent);
|
||||
connect(ui->filterEdit, &QLineEdit::textChanged, this, &ModFolderPage::on_filterTextChanged );
|
||||
}
|
||||
|
||||
void ModFolderPage::openedImpl()
|
||||
{
|
||||
m_mods->startWatching();
|
||||
m_mods->startWatching();
|
||||
}
|
||||
|
||||
void ModFolderPage::closedImpl()
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
m_mods->stopWatching();
|
||||
}
|
||||
|
||||
void ModFolderPage::on_filterTextChanged(const QString& newContents)
|
||||
{
|
||||
m_viewFilter = newContents;
|
||||
m_filterModel->setFilterFixedString(m_viewFilter);
|
||||
m_viewFilter = newContents;
|
||||
m_filterModel->setFilterFixedString(m_viewFilter);
|
||||
}
|
||||
|
||||
|
||||
CoreModFolderPage::CoreModFolderPage(BaseInstance *inst, std::shared_ptr<SimpleModList> mods,
|
||||
QString id, QString iconName, QString displayName,
|
||||
QString helpPage, QWidget *parent)
|
||||
: ModFolderPage(inst, mods, id, iconName, displayName, helpPage, parent)
|
||||
QString id, QString iconName, QString displayName,
|
||||
QString helpPage, QWidget *parent)
|
||||
: ModFolderPage(inst, mods, id, iconName, displayName, helpPage, parent)
|
||||
{
|
||||
}
|
||||
|
||||
ModFolderPage::~ModFolderPage()
|
||||
{
|
||||
m_mods->stopWatching();
|
||||
delete ui;
|
||||
m_mods->stopWatching();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ModFolderPage::shouldDisplay() const
|
||||
{
|
||||
if (m_inst)
|
||||
return !m_inst->isRunning();
|
||||
return true;
|
||||
if (m_inst)
|
||||
return !m_inst->isRunning();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoreModFolderPage::shouldDisplay() const
|
||||
{
|
||||
if (ModFolderPage::shouldDisplay())
|
||||
{
|
||||
auto inst = dynamic_cast<MinecraftInstance *>(m_inst);
|
||||
if (!inst)
|
||||
return true;
|
||||
auto version = inst->getComponentList();
|
||||
if (!version)
|
||||
return true;
|
||||
if(!version->getComponent("net.minecraftforge"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!version->getComponent("net.minecraft"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(version->getComponent("net.minecraft")->getReleaseDateTime() < g_VersionFilterData.legacyCutoffDate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (ModFolderPage::shouldDisplay())
|
||||
{
|
||||
auto inst = dynamic_cast<MinecraftInstance *>(m_inst);
|
||||
if (!inst)
|
||||
return true;
|
||||
auto version = inst->getComponentList();
|
||||
if (!version)
|
||||
return true;
|
||||
if(!version->getComponent("net.minecraftforge"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!version->getComponent("net.minecraft"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(version->getComponent("net.minecraft")->getReleaseDateTime() < g_VersionFilterData.legacyCutoffDate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModFolderPage::modListFilter(QKeyEvent *keyEvent)
|
||||
{
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmModBtn_clicked();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
on_addModBtn_clicked();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(ui->modTreeView, keyEvent);
|
||||
switch (keyEvent->key())
|
||||
{
|
||||
case Qt::Key_Delete:
|
||||
on_rmModBtn_clicked();
|
||||
return true;
|
||||
case Qt::Key_Plus:
|
||||
on_addModBtn_clicked();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QWidget::eventFilter(ui->modTreeView, keyEvent);
|
||||
}
|
||||
|
||||
bool ModFolderPage::eventFilter(QObject *obj, QEvent *ev)
|
||||
{
|
||||
if (ev->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
if (obj == ui->modTreeView)
|
||||
return modListFilter(keyEvent);
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
if (ev->type() != QEvent::KeyPress)
|
||||
{
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
|
||||
if (obj == ui->modTreeView)
|
||||
return modListFilter(keyEvent);
|
||||
return QWidget::eventFilter(obj, ev);
|
||||
}
|
||||
|
||||
void ModFolderPage::on_addModBtn_clicked()
|
||||
{
|
||||
auto list = GuiUtil::BrowseForFiles(
|
||||
m_helpName,
|
||||
tr("Select %1",
|
||||
"Select whatever type of files the page contains. Example: 'Loader Mods'")
|
||||
.arg(m_displayName),
|
||||
m_fileSelectionFilter.arg(m_displayName), MMC->settings()->get("CentralModsDir").toString(),
|
||||
this->parentWidget());
|
||||
if (!list.empty())
|
||||
{
|
||||
for (auto filename : list)
|
||||
{
|
||||
m_mods->installMod(filename);
|
||||
}
|
||||
}
|
||||
auto list = GuiUtil::BrowseForFiles(
|
||||
m_helpName,
|
||||
tr("Select %1",
|
||||
"Select whatever type of files the page contains. Example: 'Loader Mods'")
|
||||
.arg(m_displayName),
|
||||
m_fileSelectionFilter.arg(m_displayName), MMC->settings()->get("CentralModsDir").toString(),
|
||||
this->parentWidget());
|
||||
if (!list.empty())
|
||||
{
|
||||
for (auto filename : list)
|
||||
{
|
||||
m_mods->installMod(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModFolderPage::on_enableModBtn_clicked()
|
||||
{
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection());
|
||||
m_mods->enableMods(selection.indexes(), true);
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection());
|
||||
m_mods->enableMods(selection.indexes(), true);
|
||||
}
|
||||
|
||||
void ModFolderPage::on_disableModBtn_clicked()
|
||||
{
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection());
|
||||
m_mods->enableMods(selection.indexes(), false);
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection());
|
||||
m_mods->enableMods(selection.indexes(), false);
|
||||
}
|
||||
|
||||
void ModFolderPage::on_rmModBtn_clicked()
|
||||
{
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection());
|
||||
m_mods->deleteMods(selection.indexes());
|
||||
auto selection = m_filterModel->mapSelectionToSource(ui->modTreeView->selectionModel()->selection());
|
||||
m_mods->deleteMods(selection.indexes());
|
||||
}
|
||||
|
||||
void ModFolderPage::on_configFolderBtn_clicked()
|
||||
{
|
||||
DesktopServices::openDirectory(m_inst->instanceConfigFolder(), true);
|
||||
DesktopServices::openDirectory(m_inst->instanceConfigFolder(), true);
|
||||
}
|
||||
|
||||
void ModFolderPage::on_viewModBtn_clicked()
|
||||
{
|
||||
DesktopServices::openDirectory(m_mods->dir().absolutePath(), true);
|
||||
DesktopServices::openDirectory(m_mods->dir().absolutePath(), true);
|
||||
}
|
||||
|
||||
void ModFolderPage::modCurrent(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
if (!current.isValid())
|
||||
{
|
||||
ui->frame->clear();
|
||||
return;
|
||||
}
|
||||
auto sourceCurrent = m_filterModel->mapToSource(current);
|
||||
int row = sourceCurrent.row();
|
||||
Mod &m = m_mods->operator[](row);
|
||||
ui->frame->updateWithMod(m);
|
||||
if (!current.isValid())
|
||||
{
|
||||
ui->frame->clear();
|
||||
return;
|
||||
}
|
||||
auto sourceCurrent = m_filterModel->mapToSource(current);
|
||||
int row = sourceCurrent.row();
|
||||
Mod &m = m_mods->operator[](row);
|
||||
ui->frame->updateWithMod(m);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user