185 lines
4.8 KiB
C++
185 lines
4.8 KiB
C++
|
#include "MPServersModel.h"
|
||
|
|
||
|
#include <QDebug>
|
||
|
#include <QSettings>
|
||
|
|
||
|
#include <Network/RemoteXMLRequest.hxx>
|
||
|
#include <Network/HTTPClient.hxx>
|
||
|
|
||
|
#include <Main/fg_props.hxx>
|
||
|
#include <Main/globals.hxx>
|
||
|
|
||
|
#include "LaunchConfig.hxx"
|
||
|
|
||
|
const int IsCustomIndexRole = Qt::UserRole + 1;
|
||
|
|
||
|
MPServersModel::MPServersModel(QObject* parent) :
|
||
|
QAbstractListModel(parent)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
MPServersModel::~MPServersModel()
|
||
|
{
|
||
|
// if we don't cancel this now, it may complete after we are gone,
|
||
|
// causing a crash when the SGCallback fires (SGCallbacks don't clean up
|
||
|
// when their subject is deleted)
|
||
|
globals->get_subsystem<FGHTTPClient>()->client()->cancelRequest(m_mpServerRequest);
|
||
|
}
|
||
|
|
||
|
int MPServersModel::rowCount(const QModelIndex&) const
|
||
|
{
|
||
|
return m_servers.size() + 1;
|
||
|
}
|
||
|
|
||
|
QVariant MPServersModel::data(const QModelIndex &index, int role) const
|
||
|
{
|
||
|
int row = index.row();
|
||
|
if ((row < 0) || (row > m_servers.size())) {
|
||
|
return QVariant();
|
||
|
}
|
||
|
|
||
|
if (row == m_servers.size()) {
|
||
|
if (role == Qt::DisplayRole) {
|
||
|
return tr("Custom server");
|
||
|
} else if (role == IsCustomIndexRole) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return QVariant();
|
||
|
}
|
||
|
|
||
|
const ServerInfo& sv(m_servers.at(row));
|
||
|
if (role == Qt::DisplayRole) {
|
||
|
return tr("%1 - %2").arg(sv.name).arg(sv.location);
|
||
|
} else if (role == IsCustomIndexRole) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return QVariant();
|
||
|
}
|
||
|
|
||
|
QHash<int, QByteArray> MPServersModel::roleNames() const
|
||
|
{
|
||
|
QHash<int, QByteArray> result;
|
||
|
result[IsCustomIndexRole] = "isCustomIndex";
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
void MPServersModel::refresh()
|
||
|
{
|
||
|
if (m_mpServerRequest.get()) {
|
||
|
return; // in-progress
|
||
|
}
|
||
|
|
||
|
string url(fgGetString("/sim/multiplay/serverlist-url",
|
||
|
"http://liveries.flightgear.org/mpstatus/mpservers.xml"));
|
||
|
|
||
|
if (url.empty()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||
|
m_mpServerRequest.reset(new RemoteXMLRequest(url, targetnode));
|
||
|
m_mpServerRequest->done(this, &MPServersModel::onRefreshMPServersDone);
|
||
|
m_mpServerRequest->fail(this, &MPServersModel::onRefreshMPServersFailed);
|
||
|
globals->get_subsystem<FGHTTPClient>()->makeRequest(m_mpServerRequest);
|
||
|
}
|
||
|
|
||
|
void MPServersModel::onRefreshMPServersDone(simgear::HTTP::Request*)
|
||
|
{
|
||
|
beginResetModel();
|
||
|
// parse the properties
|
||
|
SGPropertyNode *targetnode = fgGetNode("/sim/multiplay/server-list", true);
|
||
|
m_servers.clear();
|
||
|
|
||
|
for (int i=0; i<targetnode->nChildren(); ++i) {
|
||
|
SGPropertyNode* c = targetnode->getChild(i);
|
||
|
if (c->getName() != std::string("server")) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (c->getBoolValue("online") != true) {
|
||
|
// only list online servers
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
QString name = QString::fromStdString(c->getStringValue("name"));
|
||
|
QString loc = QString::fromStdString(c->getStringValue("location"));
|
||
|
QString host = QString::fromStdString(c->getStringValue("hostname"));
|
||
|
int port = c->getIntValue("port");
|
||
|
m_servers.push_back(ServerInfo(name, loc, host, port));
|
||
|
}
|
||
|
endResetModel();
|
||
|
|
||
|
restoreMPServerSelection();
|
||
|
m_mpServerRequest.clear();
|
||
|
}
|
||
|
|
||
|
void MPServersModel::onRefreshMPServersFailed(simgear::HTTP::Request*)
|
||
|
{
|
||
|
qWarning() << "refreshing MP servers failed:" << QString::fromStdString(m_mpServerRequest->responseReason());
|
||
|
m_mpServerRequest.clear();
|
||
|
beginResetModel();
|
||
|
m_servers.clear();
|
||
|
endResetModel();
|
||
|
restoreMPServerSelection();
|
||
|
}
|
||
|
|
||
|
void MPServersModel::restoreMPServerSelection()
|
||
|
{
|
||
|
if (m_doRestoreMPServer) {
|
||
|
QSettings settings;
|
||
|
settings.beginGroup("mpSettings");
|
||
|
QString host = settings.value("mp-server").toString();
|
||
|
if (host == "__custom__") {
|
||
|
emit restoreIndex(m_servers.size());
|
||
|
} else {
|
||
|
// restore a built-in server
|
||
|
auto it = std::find_if(m_servers.begin(), m_servers.end(), [host](const ServerInfo& info)
|
||
|
{ return (info.host == host); });
|
||
|
|
||
|
if (it != m_servers.end()) {
|
||
|
emit restoreIndex(std::distance(m_servers.begin(), it));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_doRestoreMPServer = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void MPServersModel::requestRestore()
|
||
|
{
|
||
|
m_doRestoreMPServer = true;
|
||
|
}
|
||
|
|
||
|
QString MPServersModel::serverForIndex(int index) const
|
||
|
{
|
||
|
if ((index < 0) || (index > m_servers.size())) {
|
||
|
return QString();
|
||
|
}
|
||
|
|
||
|
if (index == m_servers.size()) {
|
||
|
return "__custom__";
|
||
|
}
|
||
|
|
||
|
return m_servers.at(index).host;
|
||
|
}
|
||
|
|
||
|
int MPServersModel::portForIndex(int index) const
|
||
|
{
|
||
|
if ((index < 0) || (index >= m_servers.size())) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return m_servers.at(index).port;
|
||
|
}
|
||
|
|
||
|
MPServersModel::ServerInfo::ServerInfo(QString n, QString l, QString h, int p)
|
||
|
{
|
||
|
name = n;
|
||
|
location = l;
|
||
|
host = h;
|
||
|
port = p;
|
||
|
}
|