summaryrefslogtreecommitdiff
path: root/src/gui/serverdialog.cpp
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2009-10-13 09:00:01 -0600
committerJared Adams <jaxad0127@gmail.com>2009-10-13 09:00:01 -0600
commit0aed5e4eb3af56ba0bf9ceb0343c262a7427b6ba (patch)
treee63bc37eb35cd10bc012d4d54fe7d76a81a5edc1 /src/gui/serverdialog.cpp
parent5987d6ff5e737d72193089418a3bf31f9f5a5c8f (diff)
downloadmana-0aed5e4eb3af56ba0bf9ceb0343c262a7427b6ba.tar.gz
mana-0aed5e4eb3af56ba0bf9ceb0343c262a7427b6ba.tar.bz2
mana-0aed5e4eb3af56ba0bf9ceb0343c262a7427b6ba.tar.xz
mana-0aed5e4eb3af56ba0bf9ceb0343c262a7427b6ba.zip
Add an asynchronous download class
And use it to download news, updates, and the server list.
Diffstat (limited to 'src/gui/serverdialog.cpp')
-rw-r--r--src/gui/serverdialog.cpp325
1 files changed, 197 insertions, 128 deletions
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index aaa0515b..f47f33ea 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -36,85 +36,66 @@
#include "net/net.h"
-#include "utils/xml.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
+#include "utils/xml.h"
#include <cstdlib>
#include <iostream>
#include <string>
-const short MAX_SERVERLIST = 5;
-
-int ServersListModel::getNumberOfElements()
-{
- return servers.size();
-}
-
-std::string ServersListModel::getElementAt(int elementIndex)
-{
- std::string myServer = servers.at(elementIndex).name;
- myServer += " (";
- myServer += std::string(servers.at(elementIndex).hostname);
- myServer += ":";
- myServer += toString(servers.at(elementIndex).port);
- myServer += ")";
- return myServer;
-}
+#define MAX_SERVERLIST 5
-void ServersListModel::addFirstElement(const ServerInfo &server)
+ServersListModel::ServersListModel(ServerInfos *servers, ServerDialog *parent):
+ mServers(servers),
+ mParent(parent)
{
- // Equivalent to push_front
- std::vector<ServerInfo>::iterator MyIterator = servers.begin();
- servers.insert(MyIterator, 1, server);
}
-void ServersListModel::addElement(const ServerInfo &server)
+int ServersListModel::getNumberOfElements()
{
- servers.push_back(server);
+ MutexLocker lock = mParent->lock();
+ return mServers->size();
}
-void ServersListModel::mergeElement(const ServerInfo &server)
+std::string ServersListModel::getElementAt(int elementIndex)
{
- // search through the list
- for (int i = 0; i < getNumberOfElements(); i++)
+ MutexLocker lock = mParent->lock();
+ ServerInfo server = mServers->at(elementIndex);
+ std::string myServer;
+ if (server.name.empty())
{
- // the server is already in the list, merge its properties
- if (servers[i] == server)
- {
- servers[i].name = server.name;
- return;
- }
+ myServer += server.hostname;
+ myServer += ":";
+ myServer += toString(server.port);
}
- // the server is not found, add it at the end of the list
- addElement(server);
-}
-
-bool ServersListModel::contains(const ServerInfo &server)
-{
- // search through the list
- for (int i = 0; i < getNumberOfElements(); i++)
+ else
{
- if (servers[i] == server)
- return true;
+ myServer += server.name;
+ myServer += " (";
+ myServer += server.hostname;
+ myServer += ":";
+ myServer += toString(server.port);
+ myServer += ")";
}
- return false;
+ return myServer;
}
-ServerDialog::ServerDialog(ServerInfo *serverInfo):
- Window(_("Choose Your Server")), mServerInfo(serverInfo)
+ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir):
+ Window(_("Choose Your Server")),
+ mDir(dir),
+ mDownloadStatus(DOWNLOADING_PREPARING),
+ mDownloadProgress(-1.0f),
+ mServers(ServerInfos()),
+ mServerInfo(serverInfo)
{
- mServerDescription = new Label(std::string());
- gcn::Label *serverLabel = new Label(_("Server:"));
- gcn::Label *portLabel = new Label(_("Port:"));
+ Label *serverLabel = new Label(_("Server:"));
+ Label *portLabel = new Label(_("Port:"));
mServerNameField = new TextField(mServerInfo->hostname);
mPortField = new TextField(toString(mServerInfo->port));
- mMostUsedServersListModel = new ServersListModel;
ServerInfo currentServer;
- ServerInfo tempServer;
-
// Add the most used servers from config if they are not in the online list
std::string currentConfig = "";
for (int i = 0; i <= MAX_SERVERLIST; i++)
@@ -129,18 +110,18 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo):
if (!currentServer.hostname.empty() && currentServer.port != 0)
{
- if (!mMostUsedServersListModel->contains(currentServer))
- mMostUsedServersListModel->addElement(currentServer);
+ mServers.push_back(currentServer);
}
}
- // load a list with online servers...
- loadServerlist();
+ mServersListModel = new ServersListModel(&mServers, this);
- mMostUsedServersList = new ListBox(mMostUsedServersListModel);
- ScrollArea *usedScroll = new ScrollArea(mMostUsedServersList);
+ mServersList = new ListBox(mServersListModel);
+ ScrollArea *usedScroll = new ScrollArea(mServersList);
usedScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mDescription = new Label(std::string());
+
mQuitButton = new Button(_("Quit"), "quit", this);
mConnectButton = new Button(_("Connect"), "connect", this);
mManualEntryButton = new Button(_("Add Entry"), "addEntry", this);
@@ -151,16 +132,16 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo):
mServerNameField->addActionListener(this);
mPortField->addActionListener(this);
mManualEntryButton->addActionListener(this);
- mMostUsedServersList->addSelectionListener(this);
- mMostUsedServersList->setSelected(0);
+ mServersList->addSelectionListener(this);
+ mServersList->setSelected(0);
usedScroll->setVerticalScrollAmount(0);
- place(0, 0, mServerDescription, 2);
- place(0, 1, serverLabel);
- place(0, 2, portLabel);
- place(1, 1, mServerNameField, 3).setPadding(3);
- place(1, 2, mPortField, 3).setPadding(3);
- place(0, 3, usedScroll, 4, 5).setPadding(3);
+ place(0, 0, serverLabel);
+ place(1, 0, mServerNameField, 3).setPadding(3);
+ place(0, 1, portLabel);
+ place(1, 1, mPortField, 3).setPadding(3);
+ place(0, 2, usedScroll, 4, 5).setPadding(3);
+ place(0, 7, mDescription, 4);
place(0, 8, mManualEntryButton);
place(2, 8, mQuitButton);
place(3, 8, mConnectButton);
@@ -185,11 +166,12 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo):
}
}
+ downloadServerList();
}
ServerDialog::~ServerDialog()
{
- delete mMostUsedServersListModel;
+ delete mServersListModel;
}
void ServerDialog::action(const gcn::ActionEvent &event)
@@ -227,9 +209,9 @@ void ServerDialog::action(const gcn::ActionEvent &event)
// now add the rest of the list...
std::string currentConfig = "";
int configCount = 1;
- for (int i = 0; i < mMostUsedServersListModel->getNumberOfElements(); i++)
+ for (int i = 0; i < mServersListModel->getNumberOfElements(); i++)
{
- tempServer = mMostUsedServersListModel->getServer(i);
+ tempServer = mServersListModel->getServer(i);
// ensure, that our server will not be added twice
if (tempServer != currentServer)
@@ -262,24 +244,77 @@ void ServerDialog::action(const gcn::ActionEvent &event)
void ServerDialog::valueChanged(const gcn::SelectionEvent &event)
{
- const int index = mMostUsedServersList->getSelected();
+ const int index = mServersList->getSelected();
if (index == -1)
return;
// Update the server and post fields according to the new selection
- const ServerInfo myServer = mMostUsedServersListModel->getServer(index);
- mServerDescription->setCaption(myServer.name);
+ const ServerInfo myServer = mServersListModel->getServer(index);
+ mDescription->setCaption(myServer.name);
mServerNameField->setText(myServer.hostname);
mPortField->setText(toString(myServer.port));
setFieldsReadOnly(true);
}
-void ServerDialog::loadServerlist()
+void ServerDialog::logic()
{
- ServerInfo currentServer;
- currentServer.clear();
+ {
+ MutexLocker lock(&mMutex);
+ if (mDownloadStatus == DOWNLOADING_COMPLETE)
+ {
+ mDownloadStatus = DOWNLOADING_OVER;
+
+ mDescription->setCaption(std::string());
+ }
+ else if (mDownloadStatus == DOWNLOADING_IN_PROGRESS)
+ {
+ mDescription->setCaption(strprintf(_("Downloading server list..."
+ "%2.2f%%"),
+ mDownloadProgress * 100));
+ }
+ else if (mDownloadStatus == DOWNLOADING_IDLE)
+ {
+ mDescription->setCaption(_("Waiting for server..."));
+ }
+ else if (mDownloadStatus == DOWNLOADING_PREPARING)
+ {
+ mDescription->setCaption(_("Preparing download"));
+ }
+ }
+
+ Window::logic();
+}
+
+void ServerDialog::setFieldsReadOnly(const bool readOnly)
+{
+ if (readOnly)
+ {
+ mServerNameField->setEnabled(false);
+ mPortField->setEnabled(false);
+ mManualEntryButton->setVisible(true);
+ mDescription->setVisible(true);
+ }
+ else
+ {
+ mManualEntryButton->setVisible(false);
+
+ mDescription->setVisible(false);
+ mDescription->setCaption(std::string());
+ mServersList->setSelected(-1);
+
+ mServerNameField->setText(std::string());
+ mServerNameField->setEnabled(true);
+ mPortField->setText(toString(DEFAULT_PORT));
+ mPortField->setEnabled(true);
+
+ mServerNameField->requestFocus();
+ }
+}
+
+void ServerDialog::downloadServerList()
+{
// try to load the configuration value for the onlineServerList
std::string listFile = config.getValue("onlineServerList", "void");
// if there is no entry, try to load the file from the default updatehost
@@ -287,82 +322,116 @@ void ServerDialog::loadServerlist()
listFile = config.getValue("updatehost", "http://updates.themanaworld.org")
+ "/serverlist.xml";
- xmlDocPtr doc = xmlReadFile(listFile.c_str(), NULL, 0);
- if (doc == NULL)
- {
- logger->log("Failed to load online serverlist from %s", listFile.c_str());
- return;
- }
+ mDownload = new Net::Download(this, listFile, &downloadUpdate);
+ mDownload->setFile(mDir + "/serverlist.xml");
+ mDownload->start();
+}
+
+void ServerDialog::loadServers()
+{
+ ServerInfo currentServer;
- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
- int version = XML::getProperty(rootNode, "version", 3);
+ xmlDocPtr doc = xmlReadFile((mDir + "/serverlist.xml").c_str(), NULL, 0);
- if (version != 1)
+ if (doc != NULL)
{
- logger->log("Online server list has wrong version");
- return;
- }
+ xmlNodePtr rootNode = xmlDocGetRootElement(doc);
+ int version = XML::getProperty(rootNode, "version", 3);
- for_each_xml_child_node(server, rootNode)
- {
- if (xmlStrEqual(server->name, BAD_CAST "server"))
+ if (version != 1)
{
- //check wether the version matches
- #ifdef TMWSERV_SUPPORT
- if (XML::getProperty(server, "type", "unknown") != "TMWSERV")
- continue;
- #endif
+ logger->log("Online server list has wrong version");
+ return;
+ }
- #ifdef EATHENA_SUPPORT
- if (XML::getProperty(server, "type", "unknown") != "EATHENA")
- continue;
- #endif
+ for_each_xml_child_node(server, rootNode)
+ {
+ if (xmlStrEqual(server->name, BAD_CAST "server"))
+ {
+ //check wether the version matches
+ #ifdef TMWSERV_SUPPORT
+ if (XML::getProperty(server, "type", "unknown") != "TMWSERV")
+ continue;
+ #endif
- currentServer.clear();
- currentServer.name = XML::getProperty(server, "name", std::string());
+ #ifdef EATHENA_SUPPORT
+ if (XML::getProperty(server, "type", "unknown") != "EATHENA")
+ continue;
+ #endif
- for_each_xml_child_node(subnode, server)
- {
- if (xmlStrEqual(subnode->name, BAD_CAST "connection"))
+ currentServer.clear();
+ currentServer.name = XML::getProperty(server, "name", std::string());
+
+ for_each_xml_child_node(subnode, server)
{
- currentServer.hostname = XML::getProperty(subnode, "hostname", std::string());
- currentServer.port = XML::getProperty(subnode, "port", DEFAULT_PORT);
+ if (xmlStrEqual(subnode->name, BAD_CAST "connection"))
+ {
+ currentServer.hostname = XML::getProperty(subnode, "hostname", std::string());
+ currentServer.port = XML::getProperty(subnode, "port", DEFAULT_PORT);
+ }
}
- }
- // merge the server into the local list
- mMostUsedServersListModel->mergeElement(currentServer);
+
+ MutexLocker lock(&mMutex);
+ // add the server to the local list (if it's not already present)
+ ServerInfos::iterator it;
+ bool found = false;
+ for (it = mServers.begin(); it != mServers.end(); it++)
+ {
+ if ((*it) == currentServer)
+ {
+ (*it).name = currentServer.name;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ mServers.push_back(currentServer);
+ }
}
+
+ xmlFreeDoc(doc);
}
- xmlFreeDoc(doc);
+ MutexLocker lock(&mMutex);
+ mDownloadStatus = DOWNLOADING_COMPLETE;
}
-void ServerDialog::setFieldsReadOnly(const bool readOnly)
+int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status,
+ size_t total, size_t remaining)
{
- if (readOnly)
+ ServerDialog *sd = reinterpret_cast<ServerDialog*>(ptr);
+ bool finished = false;
+
+ if (status == DOWNLOAD_STATUS_COMPLETE)
{
- mServerNameField->setEnabled(false);
- mPortField->setEnabled(false);
- mManualEntryButton->setVisible(true);
- mServerDescription->setVisible(true);
+ finished = true;
}
- else
+ else if (status < 0)
{
- mManualEntryButton->setVisible(false);
+ logger->log("Error retreiving server list: %s\n",
+ sd->mDownload->getError());
- mServerDescription->setVisible(false);
- mServerDescription->setCaption(std::string());
- mMostUsedServersList->setSelected(-1);
+ finished = true;
+ }
+ else
+ {
+ float progress = (float) remaining / total;
- mServerNameField->setText(std::string());
- mServerNameField->setEnabled(true);
+ if (progress != progress) progress = 0.0f; // check for NaN
+ if (progress < 0.0f) progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway.
+ if (progress > 1.0f) progress = 1.0f;
- mPortField->setText(toString(DEFAULT_PORT));
- mPortField->setEnabled(true);
-
- mServerNameField->requestFocus();
+ MutexLocker lock(&sd->mMutex);
+ sd->mDownloadStatus = DOWNLOADING_IN_PROGRESS;
+ sd->mDownloadProgress = progress;
}
-}
+ if (finished)
+ {
+ sd->loadServers();
+ }
+ return 0;
+}