[Browser] Rework browser for improved stability & clarity

(cherry picked from commits 5c79e7106f, 57353cdfff, 15723adb9a, 01a5196a92, ed75563a94, 3839a2dcfd, 1fd16ba69c, 66283943c5, ba8613a179, 5b8f4f3e92, 35b771b19e, 043eb224e2, 05fac2f67d)
pull/471/head
Koncord 6 years ago committed by David Cernat
parent 6498bcb22b
commit d03722b3f4

@ -54,6 +54,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(tblServerBrowser, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(play()));
connect(cBoxNotFull, SIGNAL(toggled(bool)), this, SLOT(notFullSwitch(bool)));
connect(cBoxWithPlayers, SIGNAL(toggled(bool)), this, SLOT(havePlayersSwitch(bool)));
connect(cBBoxWOPass, SIGNAL(toggled(bool)), this, SLOT(noPasswordSwitch(bool)));
connect(comboLatency, SIGNAL(currentIndexChanged(int)), this, SLOT(maxLatencyChanged(int)));
connect(leGamemode, SIGNAL(textChanged(const QString &)), this, SLOT(gamemodeChanged(const QString &)));
loadFavorites();
@ -65,7 +66,7 @@ MainWindow::~MainWindow()
delete mGameInvoker;
}
void MainWindow::addServerAndUpdate(QString addr)
void MainWindow::addServerAndUpdate(const QString &addr)
{
favorites->insertRow(0);
QModelIndex mi = favorites->index(0, ServerData::ADDR);
@ -121,19 +122,16 @@ void MainWindow::play()
if (id < 0)
return;
ServerInfoDialog infoDialog(this);
ServerModel *sm = ((ServerModel*)proxyModel->sourceModel());
int sourceId = proxyModel->mapToSource(proxyModel->index(id, ServerData::ADDR)).row();
infoDialog.Server(sm->myData[sourceId].addr);
ServerInfoDialog infoDialog(sm->myData[sourceId].addr, this);
if (!infoDialog.refresh())
{
queryHelper->refresh();
if (!infoDialog.exec())
return;
}
if (!infoDialog.exec())
if (!infoDialog.isUpdated())
return;
QStringList arguments;
@ -142,7 +140,8 @@ void MainWindow::play()
if (sm->myData[sourceId].GetPassword() == 1)
{
bool ok;
QString passw = QInputDialog::getText(this, "Connecting to: " + sm->myData[sourceId].addr, "Password: ", QLineEdit::Password, "", &ok);
QString passw = QInputDialog::getText(this, tr("Connecting to: ") + sm->myData[sourceId].addr, tr("Password: "),
QLineEdit::Password, "", &ok);
if (!ok)
return;
arguments.append(QLatin1String("--password=") + passw.toLatin1());
@ -228,6 +227,11 @@ void MainWindow::havePlayersSwitch(bool state)
proxyModel->filterEmptyServers(state);
}
void MainWindow::noPasswordSwitch(bool state)
{
proxyModel->filterPassworded(state);
}
void MainWindow::maxLatencyChanged(int index)
{
int maxLatency = index * 50;

@ -17,11 +17,11 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
virtual ~MainWindow();
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
protected:
void closeEvent(QCloseEvent * event) Q_DECL_OVERRIDE;
void addServerAndUpdate(QString addr);
void addServerAndUpdate(const QString &addr);
protected slots:
void tabSwitched(int index);
void addServer();
@ -31,6 +31,7 @@ protected slots:
void serverSelected();
void notFullSwitch(bool state);
void havePlayersSwitch(bool state);
void noPasswordSwitch(bool state);
void maxLatencyChanged(int index);
void gamemodeChanged(const QString &text);
private:

@ -6,6 +6,7 @@
#include "ServerModel.hpp"
#include <qdebug.h>
#include <apps/browser/netutils/Utils.hpp>
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
@ -13,26 +14,49 @@ bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &
QModelIndex pingIndex = sourceModel()->index(sourceRow, ServerData::PING, sourceParent);
QModelIndex plIndex = sourceModel()->index(sourceRow, ServerData::PLAYERS, sourceParent);
QModelIndex maxPlIndex = sourceModel()->index(sourceRow, ServerData::MAX_PLAYERS, sourceParent);
QModelIndex passwordIndex = sourceModel()->index(sourceRow, ServerData::PASSW, sourceParent);
int ping = sourceModel()->data(pingIndex).toInt();
bool pingOk;
int ping = sourceModel()->data(pingIndex).toInt(&pingOk);
int players = sourceModel()->data(plIndex).toInt();
int maxPlayers = sourceModel()->data(maxPlIndex).toInt();
if (maxPing > 0 && (ping == -1 || ping > maxPing))
if (maxPing > 0 && (ping == -1 || ping > maxPing || !pingOk))
return false;
if (filterEmpty && players == 0)
return false;
if (filterFull && players >= maxPlayers)
return false;
if(filterPasswEnabled && sourceModel()->data(passwordIndex).toString() == "Yes")
return false;
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
bool MySortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if(sortColumn() == ServerData::PING)
{
bool valid;
int pingright = sourceModel()->data(source_right).toInt(&valid);
pingright = valid ? pingright : PING_UNREACHABLE;
int pingleft = sourceModel()->data(source_left).toInt(&valid);
pingleft = valid ? pingleft : PING_UNREACHABLE;
return pingleft < pingright;
}
else
return QSortFilterProxyModel::lessThan(source_left, source_right);
}
MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
{
filterEmpty = false;
filterFull = false;
filterPasswEnabled = false;
maxPing = 0;
setSortCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
}
void MySortFilterProxyModel::filterEmptyServers(bool state)
@ -52,3 +76,9 @@ void MySortFilterProxyModel::pingLessThan(int maxPing)
this->maxPing = maxPing;
invalidateFilter();
}
void MySortFilterProxyModel::filterPassworded(bool state)
{
filterPasswEnabled = state;
invalidateFilter();
}

@ -13,13 +13,15 @@ class MySortFilterProxyModel : public QSortFilterProxyModel
Q_OBJECT
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_FINAL;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_FINAL;
public:
MySortFilterProxyModel(QObject *parent);
explicit MySortFilterProxyModel(QObject *parent);
void filterFullServer(bool state);
void filterEmptyServers(bool state);
void filterPassworded(bool state);
void pingLessThan(int maxPing);
private:
bool filterEmpty, filterFull;
bool filterEmpty, filterFull, filterPasswEnabled;
int maxPing;
};

@ -7,13 +7,19 @@
#include <QDebug>
#include "PingUpdater.hpp"
void PingHelper::Add(int row, AddrPair addrPair)
void PingHelper::Add(int row, const AddrPair &addrPair)
{
pingUpdater->addServer(row, addrPair);
if (!pingThread->isRunning())
pingThread->start();
}
void PingHelper::Reset()
{
//if (pingThread->isRunning())
Stop();
}
void PingHelper::Stop()
{
emit pingUpdater->stop();
@ -35,9 +41,8 @@ PingHelper &PingHelper::Get()
return helper;
}
PingHelper::PingHelper()
PingHelper::PingHelper() : QObject()
{
QObject();
pingThread = new QThread;
pingUpdater = new PingUpdater;
pingUpdater->moveToThread(pingThread);
@ -48,11 +53,4 @@ PingHelper::PingHelper()
connect(this, SIGNAL(stop()), pingUpdater, SLOT(stop()));
//connect(pingUpdater, SIGNAL(finished()), pingUpdater, SLOT(deleteLater()));
connect(pingUpdater, SIGNAL(updateModel(int, unsigned)), this, SLOT(update(int, unsigned)));
}
PingHelper::~PingHelper()
{
}

@ -17,17 +17,17 @@ class PingHelper : public QObject
Q_OBJECT
public:
void Add(int row, AddrPair addrPair);
void Reset();
void Add(int row, const AddrPair &addrPair);
void Stop();
void SetModel(QAbstractTableModel *model);
//void UpdateImmedialy(PingUpdater::AddrPair addrPair);
static PingHelper &Get();
private:
PingHelper();
~PingHelper();
PingHelper(const PingHelper&) = delete;
PingHelper& operator=(const PingHelper&) = delete;
private:
PingHelper();
signals:
void stop();
public slots:

@ -14,7 +14,7 @@ void PingUpdater::stop()
run = false;
}
void PingUpdater::addServer(int row, AddrPair addr)
void PingUpdater::addServer(int row, const AddrPair &addr)
{
servers.push_back({row, addr});
run = true;
@ -42,7 +42,7 @@ void PingUpdater::process()
unsigned ping = PingRakNetServer(server.second.first.toLatin1(), server.second.second);
qDebug() << "Pong from" << server.second.first + "|" + QString::number(server.second.second)
<< ":" << ping << "ms";
<< ":" << ping << "ms" << "Sizeof servers: " << servers.size();
emit updateModel(server.first, ping);
}

@ -14,7 +14,7 @@ class PingUpdater : public QObject
{
Q_OBJECT
public:
void addServer(int row, AddrPair addrPair);
void addServer(int row, const AddrPair &addrPair);
public slots:
void stop();
void process();

@ -19,8 +19,8 @@ QueryHelper::QueryHelper(QAbstractItemModel *model)
connect(queryThread, SIGNAL(started()), queryUpdate, SLOT(process()));
connect(queryUpdate, SIGNAL(finished()), queryThread, SLOT(quit()));
connect(queryUpdate, &QueryUpdate::finished, [this](){emit finished();});
connect(queryUpdate, SIGNAL(updateModel(QString, unsigned short, QueryData)),
this, SLOT(update(QString, unsigned short, QueryData)));
connect(queryUpdate, SIGNAL(updateModel(const QString&, unsigned short, const QueryData&)),
this, SLOT(update(const QString&, unsigned short, const QueryData&)));
queryUpdate->moveToThread(queryThread);
}
@ -29,6 +29,7 @@ void QueryHelper::refresh()
if (!queryThread->isRunning())
{
_model->removeRows(0, _model->rowCount());
PingHelper::Get().Stop();
queryThread->start();
emit started();
}
@ -39,7 +40,7 @@ void QueryHelper::terminate()
queryThread->terminate();
}
void QueryHelper::update(QString addr, unsigned short port, QueryData data)
void QueryHelper::update(const QString &addr, unsigned short port, const QueryData& data)
{
ServerModel *model = ((ServerModel*)_model);
model->insertRow(model->rowCount());
@ -80,7 +81,7 @@ void QueryUpdate::process()
return;
}
for (auto server : data)
for (const auto &server : data)
emit updateModel(server.first.ToString(false), server.first.GetPort(), server.second);
emit finished();
}

@ -23,7 +23,7 @@ public slots:
void refresh();
void terminate();
private slots:
void update(QString addr, unsigned short port, QueryData data);
void update(const QString &addr, unsigned short port, const QueryData& data);
signals:
void finished();
void started();
@ -38,7 +38,7 @@ class QueryUpdate : public QObject
Q_OBJECT
signals:
void finished();
void updateModel(QString addr, unsigned short port, QueryData data);
void updateModel(const QString &addr, unsigned short port, const QueryData& data);
public slots:
void process();
};

@ -6,32 +6,65 @@
#include "qdebug.h"
#include "ServerInfoDialog.hpp"
#include <apps/browser/netutils/Utils.hpp>
#include <algorithm>
#include <utility>
#include <QThread>
using namespace std;
using namespace RakNet;
ServerInfoDialog::ServerInfoDialog(QWidget *parent): QDialog(parent)
ThrWorker::ThrWorker(ServerInfoDialog *dialog, QString addr, unsigned short port): addr(std::move(addr)), port(port), stopped(false)
{
this->dialog = dialog;
}
void ThrWorker::process()
{
stopped = false;
auto newSD = QueryClient::Get().Update(SystemAddress(addr.toUtf8(), port));
if (dialog != nullptr)
dialog->setData(newSD);
stopped = true;
emit finished();
}
ServerInfoDialog::ServerInfoDialog(const QString &addr, QWidget *parent): QDialog(parent)
{
setupUi(this);
connect(btnRefresh, SIGNAL(clicked()), this, SLOT(refresh()));
refreshThread = new QThread;
QStringList list = addr.split(':');
worker = new ThrWorker(this, list[0].toLatin1(), list[1].toUShort());
worker->moveToThread(refreshThread);
connect(refreshThread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), refreshThread, SLOT(quit()));
connect(refreshThread, SIGNAL(finished()), this, SLOT(refresh()));
connect(btnRefresh, &QPushButton::clicked, [this]{
if (!refreshThread->isRunning())
refreshThread->start();
});
}
ServerInfoDialog::~ServerInfoDialog()
{
worker->dialog = nullptr;
if (!refreshThread->isRunning())
refreshThread->terminate();
}
bool ServerInfoDialog::isUpdated()
{
return sd.first != UNASSIGNED_SYSTEM_ADDRESS;
}
void ServerInfoDialog::Server(QString addr)
void ServerInfoDialog::setData(std::pair<RakNet::SystemAddress, QueryData> &newSD)
{
this->addr = addr;
sd = newSD;
}
bool ServerInfoDialog::refresh()
void ServerInfoDialog::refresh()
{
QStringList list = addr.split(':');
auto sd = QueryClient::Get().Update(SystemAddress(list[0].toLatin1(), list[1].toUShort()));
if (sd.first != UNASSIGNED_SYSTEM_ADDRESS)
{
leAddr->setText(sd.first.ToString(true, ':'));
@ -41,17 +74,16 @@ bool ServerInfoDialog::refresh()
btnConnect->setDisabled(ping == PING_UNREACHABLE);
listPlayers->clear();
for (auto player : sd.second.players)
for (const auto &player : sd.second.players)
listPlayers->addItem(QString::fromStdString(player));
listPlugins->clear();
for (auto plugin : sd.second.plugins)
for (const auto &plugin : sd.second.plugins)
listPlugins->addItem(QString::fromStdString(plugin.name));
listRules->clear();
const static vector<std::string> defaultRules {"gamemode", "maxPlayers", "name", "passw", "players", "version"};
for (auto rule : sd.second.rules)
for (auto &rule : sd.second.rules)
{
if (::find(defaultRules.begin(), defaultRules.end(), rule.first) != defaultRules.end())
continue;
@ -64,7 +96,12 @@ bool ServerInfoDialog::refresh()
}
lblPlayers->setText(QString::number(sd.second.players.size()) + " / " + QString::number(sd.second.GetMaxPlayers()));
return true;
}
return false;
}
int ServerInfoDialog::exec()
{
if (!refreshThread->isRunning())
refreshThread->start();
return QDialog::exec();
}

@ -6,18 +6,45 @@
#define NEWLAUNCHER_SERVERINFODIALOG_HPP
#include "ui_ServerInfo.h"
#include <apps/browser/netutils/Utils.hpp>
#include <RakNetTypes.h>
#include <components/openmw-mp/Master/MasterData.hpp>
class ThrWorker;
class ServerInfoDialog : public QDialog, public Ui::Dialog
{
Q_OBJECT
public:
explicit ServerInfoDialog(QWidget *parent = 0);
virtual ~ServerInfoDialog();
void Server(QString addr);
explicit ServerInfoDialog(const QString &addr, QWidget *parent = nullptr);
~ServerInfoDialog() override;
bool isUpdated();
void setData(std::pair<RakNet::SystemAddress, QueryData> &newSD);
public slots:
void refresh();
int exec() Q_DECL_OVERRIDE;
private:
QThread *refreshThread;
ThrWorker* worker;
std::pair<RakNet::SystemAddress, QueryData> sd;
};
class ThrWorker: public QObject
{
friend class ServerInfoDialog;
Q_OBJECT
public:
ThrWorker(ServerInfoDialog *dialog, QString addr, unsigned short port);
public slots:
bool refresh();
void process();
signals:
void finished();
private:
QString addr;
unsigned short port;
bool stopped;
ServerInfoDialog *dialog;
};

@ -1,16 +1,11 @@
#include <qmessagebox.h>
#include "ServerModel.hpp"
#include <qdebug.h>
#include <apps/browser/netutils/Utils.hpp>
ServerModel::ServerModel(QObject *parent) : QAbstractTableModel(parent)
{
}
ServerModel::~ServerModel()
{
}
/*QHash<int, QByteArray> ServerModel::roleNames() const
{
return roles;
@ -49,7 +44,7 @@ QVariant ServerModel::data(const QModelIndex &index, int role) const
var = QString(sd.rules.at("name").str.c_str());
break;
case ServerData::PING:
var = sd.ping;
var = sd.ping == PING_UNREACHABLE ? QVariant("Unreachable") : sd.ping;
break;
case ServerData::MODNAME:
if (sd.rules.at("gamemode").str == "")
@ -136,7 +131,7 @@ bool ServerModel::setData(const QModelIndex &index, const QVariant &value, int r
sd.SetPassword(value.toBool());
break;
case ServerData::VERSION:
sd.SetVersion(value.toString().toLatin1());
sd.SetVersion(value.toString().toUtf8());
ok = !sd.addr.isEmpty();
break;
case ServerData::PLAYERS:
@ -146,14 +141,14 @@ bool ServerModel::setData(const QModelIndex &index, const QVariant &value, int r
sd.SetMaxPlayers(value.toInt(&ok));
break;
case ServerData::HOSTNAME:
sd.SetName(value.toString().toLatin1());
sd.SetName(value.toString().toUtf8());
ok = !sd.addr.isEmpty();
break;
case ServerData::PING:
sd.ping = value.toInt(&ok);
break;
case ServerData::MODNAME:
sd.SetGameMode(value.toString().toLatin1());
sd.SetGameMode(value.toString().toUtf8());
break;
default:
return false;
@ -170,9 +165,7 @@ bool ServerModel::insertRows(int position, int count, const QModelIndex &index)
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position + count - 1);
for (int row = 0; row < count; ++row) {
myData.insert(position, {});
}
myData.insert(position, count, {});
endInsertRows();
return true;

@ -29,8 +29,7 @@ class ServerModel: public QAbstractTableModel
{
Q_OBJECT
public:
explicit ServerModel(QObject *parent = 0);
~ServerModel();
explicit ServerModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_FINAL;
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_FINAL;
int columnCount(const QModelIndex &parent) const Q_DECL_FINAL;

@ -30,7 +30,7 @@ QueryClient::~QueryClient()
RakPeerInterface::DestroyInstance(peer);
}
void QueryClient::SetServer(std::string addr, unsigned short port)
void QueryClient::SetServer(const string &addr, unsigned short port)
{
masterAddr = SystemAddress(addr.c_str(), port);
}
@ -83,7 +83,7 @@ map<SystemAddress, QueryData> QueryClient::Query()
return query;
}
pair<SystemAddress, QueryData> QueryClient::Update(RakNet::SystemAddress addr)
pair<SystemAddress, QueryData> QueryClient::Update(const RakNet::SystemAddress &addr)
{
qDebug() << "Locking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
pair<SystemAddress, QueryData> server;
@ -179,7 +179,7 @@ ConnectionState QueryClient::Connect()
{
ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), TES3MP_MASTERSERVER_PASSW,
strlen(TES3MP_MASTERSERVER_PASSW), 0, 0, 5, 500);
strlen(TES3MP_MASTERSERVER_PASSW), nullptr, 0, 5, 500);
while (true)
{

@ -14,16 +14,16 @@
class QueryClient
{
private:
public:
QueryClient(QueryClient const &) = delete;
QueryClient(QueryClient &&) = delete;
QueryClient &operator=(QueryClient const &) = delete;
QueryClient &operator=(QueryClient &&) = delete;
public:
static QueryClient &Get();
void SetServer(std::string addr, unsigned short port);
void SetServer(const std::string &addr, unsigned short port);
std::map<RakNet::SystemAddress, QueryData> Query();
std::pair<RakNet::SystemAddress, QueryData> Update(RakNet::SystemAddress addr);
std::pair<RakNet::SystemAddress, QueryData> Update(const RakNet::SystemAddress &addr);
int Status();
private:
RakNet::ConnectionState Connect();

@ -44,11 +44,15 @@ unsigned int PingRakNetServer(const char *addr, unsigned short port)
break;
case ID_CONNECTED_PING:
case ID_UNCONNECTED_PONG:
{
RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
bsIn.Read(time);
time = now - time;
done = true;
break;
}
default:
break;
}
peer->DeallocatePacket(packet);
}
@ -69,9 +73,9 @@ ServerExtendedData getExtendedData(const char *addr, unsigned short port)
sstr << TES3MP_VERSION;
sstr << TES3MP_PROTO_VERSION;
std::string msg = "";
std::string msg;
if (peer->Connect(addr, port, sstr.str().c_str(), (int)(sstr.str().size()), 0, 0, 3, 500, 0) != RakNet::CONNECTION_ATTEMPT_STARTED)
if (peer->Connect(addr, port, sstr.str().c_str(), (int)(sstr.str().size()), nullptr, 0, 3, 500, 0) != RakNet::CONNECTION_ATTEMPT_STARTED)
msg = "Connection attempt failed.\n";
@ -142,14 +146,14 @@ ServerExtendedData getExtendedData(const char *addr, unsigned short port)
{
RakNet::RakString str;
bs.Read(str);
data.players.push_back(str.C_String());
data.players.emplace_back(str.C_String());
}
bs.Read(length);
for (size_t i = 0; i < length; i++)
{
RakNet::RakString str;
bs.Read(str);
data.plugins.push_back(str.C_String());
data.plugins.emplace_back(str.C_String());
}
done = true;
}

@ -166,6 +166,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cBBoxWOPass">
<property name="text">
<string>No password</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

@ -207,6 +207,9 @@
</item>
<item>
<widget class="QPushButton" name="btnConnect">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Connect</string>
</property>

Loading…
Cancel
Save