summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt21
-rw-r--r--gui/MainWindow.h2
-rw-r--r--gui/widgets/IconLabel.cpp30
-rw-r--r--gui/widgets/IconLabel.h26
-rw-r--r--gui/widgets/LineSeparator.cpp37
-rw-r--r--gui/widgets/LineSeparator.h18
-rw-r--r--gui/widgets/ServerStatus.cpp150
-rw-r--r--gui/widgets/ServerStatus.h26
-rw-r--r--logic/status/StatusChecker.cpp23
-rw-r--r--logic/status/StatusChecker.h11
10 files changed, 236 insertions, 108 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d7c9e6fd..17589f9a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -308,16 +308,23 @@ SET(MULTIMC_SOURCES
gui/dialogs/NotificationDialog.cpp
# GUI - widgets
- gui/widgets/Common.h
gui/widgets/Common.cpp
- gui/widgets/ModListView.h
- gui/widgets/ModListView.cpp
- gui/widgets/VersionListView.h
- gui/widgets/VersionListView.cpp
- gui/widgets/LabeledToolButton.h
+ gui/widgets/Common.h
+ gui/widgets/IconLabel.cpp
+ gui/widgets/IconLabel.h
gui/widgets/LabeledToolButton.cpp
- gui/widgets/MCModInfoFrame.h
+ gui/widgets/LabeledToolButton.h
+ gui/widgets/LineSeparator.cpp
+ gui/widgets/LineSeparator.h
gui/widgets/MCModInfoFrame.cpp
+ gui/widgets/MCModInfoFrame.h
+ gui/widgets/ModListView.cpp
+ gui/widgets/ModListView.h
+ gui/widgets/ServerStatus.cpp
+ gui/widgets/ServerStatus.h
+ gui/widgets/VersionListView.cpp
+ gui/widgets/VersionListView.h
+
# GUI - instance group view
gui/groupview/Group.cpp
diff --git a/gui/MainWindow.h b/gui/MainWindow.h
index ad160da7..2c421b88 100644
--- a/gui/MainWindow.h
+++ b/gui/MainWindow.h
@@ -200,7 +200,7 @@ private:
Task *m_versionLoadTask;
QLabel *m_statusLeft;
- QLabel *m_statusRight;
+ class ServerStatus *m_statusRight;
QMenu *accountMenu;
QToolButton *accountMenuButton;
diff --git a/gui/widgets/IconLabel.cpp b/gui/widgets/IconLabel.cpp
new file mode 100644
index 00000000..1bfe8dc9
--- /dev/null
+++ b/gui/widgets/IconLabel.cpp
@@ -0,0 +1,30 @@
+#include "IconLabel.h"
+
+#include <QStyle>
+#include <QStyleOption>
+#include <QLayout>
+#include <QPainter>
+#include <QRect>
+
+IconLabel::IconLabel(QWidget *parent, QIcon icon, QSize size)
+ : QWidget(parent), m_icon(icon), m_size(size)
+{
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+}
+
+QSize IconLabel::sizeHint() const
+{
+ return m_size;
+}
+
+void IconLabel::setIcon(QIcon icon)
+{
+ m_icon = icon;
+ update();
+}
+
+void IconLabel::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ m_icon.paint(&p, contentsRect());
+}
diff --git a/gui/widgets/IconLabel.h b/gui/widgets/IconLabel.h
new file mode 100644
index 00000000..a2f1eef3
--- /dev/null
+++ b/gui/widgets/IconLabel.h
@@ -0,0 +1,26 @@
+#pragma once
+#include <QWidget>
+#include <QIcon>
+
+class QStyleOption;
+
+/**
+ * This is a trivial widget that paints a QIcon of the specified size.
+ */
+class IconLabel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /// Create a line separator. orientation is the orientation of the line.
+ explicit IconLabel(QWidget *parent, QIcon icon, QSize size);
+
+ virtual QSize sizeHint() const;
+ virtual void paintEvent(QPaintEvent *);
+
+ void setIcon(QIcon icon);
+
+private:
+ QSize m_size;
+ QIcon m_icon;
+};
diff --git a/gui/widgets/LineSeparator.cpp b/gui/widgets/LineSeparator.cpp
new file mode 100644
index 00000000..f4ee173d
--- /dev/null
+++ b/gui/widgets/LineSeparator.cpp
@@ -0,0 +1,37 @@
+#include "LineSeparator.h"
+
+#include <QStyle>
+#include <QStyleOption>
+#include <QLayout>
+#include <QPainter>
+
+void LineSeparator::initStyleOption(QStyleOption *option) const
+{
+ option->initFrom(this);
+ // in a horizontal layout, the line is vertical (and vice versa)
+ if (m_orientation == Qt::Vertical)
+ option->state |= QStyle::State_Horizontal;
+}
+
+LineSeparator::LineSeparator(QWidget *parent, Qt::Orientation orientation)
+ : QWidget(parent), m_orientation(orientation)
+{
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+}
+
+QSize LineSeparator::sizeHint() const
+{
+ QStyleOption opt;
+ initStyleOption(&opt);
+ const int extent =
+ style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, &opt, parentWidget());
+ return QSize(extent, extent);
+}
+
+void LineSeparator::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ QStyleOption opt;
+ initStyleOption(&opt);
+ style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, &p, parentWidget());
+}
diff --git a/gui/widgets/LineSeparator.h b/gui/widgets/LineSeparator.h
new file mode 100644
index 00000000..376f2056
--- /dev/null
+++ b/gui/widgets/LineSeparator.h
@@ -0,0 +1,18 @@
+#pragma once
+#include <QWidget>
+
+class QStyleOption;
+
+class LineSeparator : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /// Create a line separator. orientation is the orientation of the line.
+ explicit LineSeparator(QWidget *parent, Qt::Orientation orientation = Qt::Vertical);
+ QSize sizeHint() const;
+ void paintEvent(QPaintEvent *);
+ void initStyleOption(QStyleOption *option) const;
+private:
+ Qt::Orientation m_orientation = Qt::Vertical;
+};
diff --git a/gui/widgets/ServerStatus.cpp b/gui/widgets/ServerStatus.cpp
index 1b1bb6f7..e540a301 100644
--- a/gui/widgets/ServerStatus.cpp
+++ b/gui/widgets/ServerStatus.cpp
@@ -1,4 +1,6 @@
#include "ServerStatus.h"
+#include "LineSeparator.h"
+#include "IconLabel.h"
#include "logic/status/StatusChecker.h"
#include "MultiMC.h"
@@ -8,118 +10,106 @@
#include <QLabel>
#include <QMap>
#include <QToolButton>
+#include <QAction>
-ServerStatus::ServerStatus(QWidget *parent, Qt::WindowFlags f)
- :QWidget(parent, f)
+ServerStatus::ServerStatus(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f)
{
- clear();
- goodIcon = QPixmap(":/icons/multimc/48x48/status-good.png");
- goodIcon.setDevicePixelRatio(2.0);
- badIcon = QPixmap(":/icons/multimc/48x48/status-bad.png");
- badIcon.setDevicePixelRatio(2.0);
- addStatus(tr("No status available"), false);
+ layout = new QHBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ goodIcon = QIcon::fromTheme("status-good");
+ badIcon = QIcon::fromTheme("status-bad");
+
+ addStatus("minecraft.net", tr("Web"));
+ addLine();
+ addStatus("account.mojang.com", tr("Account"));
+ addLine();
+ addStatus("skins.minecraft.net", tr("Skins"));
+ addLine();
+ addStatus("authserver.mojang.com", tr("Auth"));
+ addLine();
+ addStatus("sessionserver.mojang.com", tr("Session"));
+
m_statusRefresh = new QToolButton(this);
m_statusRefresh->setCheckable(true);
m_statusRefresh->setToolButtonStyle(Qt::ToolButtonIconOnly);
m_statusRefresh->setIcon(QIcon::fromTheme("refresh"));
+ layout->addWidget(m_statusRefresh);
+
+ setLayout(layout);
+
// Start status checker
{
- connect(MMC->statusChecker().get(), &StatusChecker::statusLoaded, this,
- &ServerStatus::updateStatusUI);
- connect(MMC->statusChecker().get(), &StatusChecker::statusLoadingFailed, this,
- &ServerStatus::updateStatusFailedUI);
-
+ auto reloader = MMC->statusChecker().get();
+ connect(reloader, &StatusChecker::statusChanged, this, &ServerStatus::StatusChanged);
+ connect(reloader, &StatusChecker::statusLoading, this, &ServerStatus::StatusReloading);
connect(m_statusRefresh, &QAbstractButton::clicked, this, &ServerStatus::reloadStatus);
- connect(&statusTimer, &QTimer::timeout, this, &ServerStatus::reloadStatus);
- statusTimer.setSingleShot(true);
-
+ MMC->statusChecker()->startTimer(60000);
reloadStatus();
}
-
}
-ServerStatus::addLine()
+ServerStatus::~ServerStatus()
{
- auto line = new QFrame(this);
- line->setFrameShape(QFrame::VLine);
- line->setFrameShadow(QFrame::Sunken);
- layout->addWidget(line);
}
-ServerStatus::addStatus(QString name, bool online)
+void ServerStatus::reloadStatus()
{
- auto label = new QLabel(this);
- label->setText(name);
- if(online)
- label->setPixmap(goodIcon);
- else
- label->setPixmap(badIcon);
- layout->addWidget(label);
+ MMC->statusChecker()->reloadStatus();
}
-ServerStatus::clear()
+void ServerStatus::addLine()
{
- if(layout)
- delete layout;
- layout = new QHBoxLayout(this);
+ layout->addWidget(new LineSeparator(this));
}
-void ServerStatus::StatusChanged(QMap<QString, QString> statusEntries)
+void ServerStatus::addStatus(QString key, QString name)
{
- clear();
- int howmany = statusEntries.size();
- int index = 0;
- auto iter = statusEntries.begin();
- while (iter != statusEntries.end())
{
- addStatus();
- index++;
+ auto label = new IconLabel(this, badIcon, QSize(16, 16));
+ label->setToolTip(key);
+ serverLabels[key] = label;
+ layout->addWidget(label);
+ }
+ {
+ auto label = new QLabel(this);
+ label->setText(name);
+ label->setToolTip(key);
+ layout->addWidget(label);
}
}
-static QString convertStatus(const QString &status)
-{
- QString ret = "?";
-
- if (status == "green")
- ret = "↑";
- else if (status == "yellow")
- ret = "-";
- else if (status == "red")
- ret = "↓";
-
- return "<span style=\"font-size:11pt; font-weight:600;\">" + ret + "</span>";
-}
-
-void ServerStatus::reloadStatus()
+void ServerStatus::setStatus(QString key, bool value)
{
- m_statusRefresh->setChecked(true);
- MMC->statusChecker()->reloadStatus();
- // updateStatusUI();
+ if (!serverLabels.contains(key))
+ return;
+ IconLabel *label = serverLabels[key];
+ label->setIcon(value ? goodIcon : badIcon);
}
-static QString makeStatusString(const QMap<QString, QString> statuses)
+void ServerStatus::StatusChanged(const QMap<QString, QString> statusEntries)
{
- QString status = "";
- status += "Web: " + convertStatus(statuses["minecraft.net"]);
- status += " Account: " + convertStatus(statuses["account.mojang.com"]);
- status += " Skins: " + convertStatus(statuses["skins.minecraft.net"]);
- status += " Auth: " + convertStatus(statuses["authserver.mojang.com"]);
- status += " Session: " + convertStatus(statuses["sessionserver.mojang.com"]);
-
- return status;
-}
-
-void ServerStatus::updateStatusUI()
-{
- m_statusRefresh->setChecked(false);
- MMC->statusChecker()->getStatusEntries();
- statusTimer.start(60 * 1000);
+ auto convertStatus = [&](QString status)->bool
+ {
+ if (status == "green")
+ return true;
+ else if (status == "yellow")
+ return false;
+ else if (status == "red")
+ return false;
+ return false;
+ }
+ ;
+ auto iter = statusEntries.begin();
+ while (iter != statusEntries.end())
+ {
+ QString key = iter.key();
+ bool value = convertStatus(iter.value());
+ setStatus(key, value);
+ iter++;
+ }
}
-void ServerStatus::updateStatusFailedUI()
+void ServerStatus::StatusReloading(bool is_reloading)
{
- m_statusRefresh->setChecked(false);
- StatusChanged();
- statusTimer.start(60 * 1000);
+ m_statusRefresh->setChecked(is_reloading);
}
diff --git a/gui/widgets/ServerStatus.h b/gui/widgets/ServerStatus.h
index a116d3d4..2244031b 100644
--- a/gui/widgets/ServerStatus.h
+++ b/gui/widgets/ServerStatus.h
@@ -1,7 +1,11 @@
#pragma once
+#include <QString>
#include <QWidget>
+#include <QMap>
+#include <QIcon>
#include <memory>
+class IconLabel;
class QToolButton;
class QHBoxLayout;
@@ -10,23 +14,21 @@ class ServerStatus: public QWidget
Q_OBJECT
public:
explicit ServerStatus(QWidget *parent = nullptr, Qt::WindowFlags f = 0);
- virtual ~ServerStatus() {};
+ virtual ~ServerStatus();
+ ;
public slots:
- void updateStatusUI();
-
- void updateStatusFailedUI();
-
void reloadStatus();
- void StatusChanged();
+ void StatusChanged(const QMap<QString, QString> statuses);
+ void StatusReloading(bool is_reloading);
private: /* methods */
- clear();
- addLine();
- addStatus(QString name, bool online);
+ void addLine();
+ void addStatus(QString key, QString name);
+ void setStatus(QString key, bool value);
private: /* data */
QHBoxLayout * layout = nullptr;
QToolButton *m_statusRefresh = nullptr;
- QPixmap goodIcon;
- QPixmap badIcon;
- QTimer statusTimer;
+ QMap<QString, IconLabel *> serverLabels;
+ QIcon goodIcon;
+ QIcon badIcon;
};
diff --git a/logic/status/StatusChecker.cpp b/logic/status/StatusChecker.cpp
index 66f800ae..17053837 100644
--- a/logic/status/StatusChecker.cpp
+++ b/logic/status/StatusChecker.cpp
@@ -27,6 +27,12 @@ StatusChecker::StatusChecker()
}
+void StatusChecker::timerEvent(QTimerEvent *e)
+{
+ QObject::timerEvent(e);
+ reloadStatus();
+}
+
void StatusChecker::reloadStatus()
{
if (isLoadingStatus())
@@ -42,13 +48,14 @@ void StatusChecker::reloadStatus()
QObject::connect(job, &NetJob::succeeded, this, &StatusChecker::statusDownloadFinished);
QObject::connect(job, &NetJob::failed, this, &StatusChecker::statusDownloadFailed);
m_statusNetJob.reset(job);
+ emit statusLoading(true);
job->start();
}
void StatusChecker::statusDownloadFinished()
{
QLOG_DEBUG() << "Finished loading status JSON.";
-
+ m_statusEntries.clear();
QByteArray data;
{
ByteArrayDownloadPtr dl = std::dynamic_pointer_cast<ByteArrayDownload>(m_statusNetJob->first());
@@ -121,17 +128,27 @@ QString StatusChecker::getLastLoadErrorMsg() const
void StatusChecker::succeed()
{
+ if(m_prevEntries != m_statusEntries)
+ {
+ emit statusChanged(m_statusEntries);
+ m_prevEntries = m_statusEntries;
+ }
m_lastLoadError = "";
QLOG_DEBUG() << "Status loading succeeded.";
m_statusNetJob.reset();
- emit statusLoaded();
+ emit statusLoading(false);
}
void StatusChecker::fail(const QString& errorMsg)
{
+ if(m_prevEntries != m_statusEntries)
+ {
+ emit statusChanged(m_statusEntries);
+ m_prevEntries = m_statusEntries;
+ }
m_lastLoadError = errorMsg;
QLOG_DEBUG() << "Failed to load status:" << errorMsg;
m_statusNetJob.reset();
- emit statusLoadingFailed(errorMsg);
+ emit statusLoading(false);
}
diff --git a/logic/status/StatusChecker.h b/logic/status/StatusChecker.h
index 1cb01836..df0dd06d 100644
--- a/logic/status/StatusChecker.h
+++ b/logic/status/StatusChecker.h
@@ -29,26 +29,27 @@ public:
QString getLastLoadErrorMsg() const;
- bool isStatusLoaded() const;
-
bool isLoadingStatus() const;
QMap<QString, QString> getStatusEntries() const;
void Q_SLOT reloadStatus();
+protected:
+ virtual void timerEvent(QTimerEvent *);
+
signals:
- void statusLoaded();
- void statusLoadingFailed(QString errorMsg);
+ void statusLoading(bool loading);
+ void statusChanged(QMap<QString, QString> newStatus);
protected slots:
void statusDownloadFinished();
void statusDownloadFailed();
protected:
+ QMap<QString, QString> m_prevEntries;
QMap<QString, QString> m_statusEntries;
NetJobPtr m_statusNetJob;
- bool m_loadedStatus;
QString m_lastLoadError;
void Q_SLOT succeed();