1
0
Fork 0
flightgear/src/GUI/MPServersModel.cpp

185 lines
4.8 KiB
C++
Raw Normal View History

2017-02-21 11:01:06 +00:00
#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;
}