GH-1670 Fix LWJGL list loading
Now it uses the standard Download class that supports redirects and SSL.
This commit is contained in:
parent
ef73a2bd32
commit
4ca6878743
@ -22,11 +22,10 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#define RSS_URL "http://sourceforge.net/projects/java-game-lib/rss"
|
#define RSS_URL "https://sourceforge.net/projects/java-game-lib/rss"
|
||||||
|
|
||||||
LWJGLVersionList::LWJGLVersionList(QObject *parent) : BaseVersionList(parent)
|
LWJGLVersionList::LWJGLVersionList(QObject *parent) : BaseVersionList(parent)
|
||||||
{
|
{
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant LWJGLVersionList::data(const QModelIndex &index, int role) const
|
QVariant LWJGLVersionList::data(const QModelIndex &index, int role) const
|
||||||
@ -72,21 +71,21 @@ int LWJGLVersionList::columnCount(const QModelIndex &parent) const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LWJGLVersionList::isLoading() const
|
|
||||||
{
|
|
||||||
return m_loading;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LWJGLVersionList::loadList()
|
void LWJGLVersionList::loadList()
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(!m_loading, "loadList", "list is already loading (m_loading is true)");
|
if(m_loading)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_loading = true;
|
||||||
|
|
||||||
setLoading(true);
|
qDebug() << "Downloading LWJGL RSS...";
|
||||||
QNetworkRequest req(QUrl(RSS_URL));
|
m_rssDLJob.reset(new NetJob("LWJGL RSS"));
|
||||||
req.setRawHeader("Accept", "application/rss+xml, text/xml, */*");
|
m_rssDL = Net::Download::makeByteArray(QUrl(RSS_URL), &m_rssData);
|
||||||
req.setRawHeader("User-Agent", "MultiMC/5.0 (Uncached)");
|
m_rssDLJob->addNetAction(m_rssDL);
|
||||||
reply = ENV.qnam().get(req);
|
connect(m_rssDLJob.get(), &NetJob::failed, this, &LWJGLVersionList::rssFailed);
|
||||||
connect(reply, SIGNAL(finished()), SLOT(netRequestComplete()));
|
connect(m_rssDLJob.get(), &NetJob::succeeded, this, &LWJGLVersionList::rssSucceeded);
|
||||||
|
m_rssDLJob->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
|
inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
|
||||||
@ -98,91 +97,70 @@ inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
|
|||||||
return QDomElement();
|
return QDomElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LWJGLVersionList::netRequestComplete()
|
void LWJGLVersionList::rssFailed(const QString& reason)
|
||||||
{
|
{
|
||||||
if (reply->error() == QNetworkReply::NoError)
|
m_loading = false;
|
||||||
|
qWarning() << "Failed to load LWJGL list. Network error: " + reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LWJGLVersionList::rssSucceeded()
|
||||||
|
{
|
||||||
|
QRegExp lwjglRegex("lwjgl-(([0-9]\\.?)+)\\.zip");
|
||||||
|
Q_ASSERT_X(lwjglRegex.isValid(), "load LWJGL list", "LWJGL regex is invalid");
|
||||||
|
|
||||||
|
QDomDocument doc;
|
||||||
|
|
||||||
|
QString xmlErrorMsg;
|
||||||
|
int errorLine;
|
||||||
|
|
||||||
|
if (!doc.setContent(m_rssData, false, &xmlErrorMsg, &errorLine))
|
||||||
{
|
{
|
||||||
QRegExp lwjglRegex("lwjgl-(([0-9]\\.?)+)\\.zip");
|
qWarning() << "Failed to load LWJGL list. XML error: " + xmlErrorMsg + " at line " + QString::number(errorLine);
|
||||||
Q_ASSERT_X(lwjglRegex.isValid(), "load LWJGL list", "LWJGL regex is invalid");
|
m_loading = false;
|
||||||
|
m_rssData.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_rssData.clear();
|
||||||
|
|
||||||
QDomDocument doc;
|
QDomNodeList items = doc.elementsByTagName("item");
|
||||||
|
|
||||||
QString xmlErrorMsg;
|
QList<PtrLWJGLVersion> tempList;
|
||||||
int errorLine;
|
|
||||||
auto rawData = reply->readAll();
|
for (int i = 0; i < items.length(); i++)
|
||||||
if (!doc.setContent(rawData, false, &xmlErrorMsg, &errorLine))
|
{
|
||||||
|
Q_ASSERT_X(items.at(i).isElement(), "load LWJGL list", "XML element isn't an element... wat?");
|
||||||
|
|
||||||
|
QDomElement linkElement = getDomElementByTagName(items.at(i).toElement(), "link");
|
||||||
|
if (linkElement.isNull())
|
||||||
{
|
{
|
||||||
failed("Failed to load LWJGL list. XML error: " + xmlErrorMsg + " at line " + QString::number(errorLine));
|
qDebug() << "Link element" << i << "in RSS feed doesn't exist! Skipping.";
|
||||||
setLoading(false);
|
continue;
|
||||||
qDebug() << QString::fromUtf8(rawData);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDomNodeList items = doc.elementsByTagName("item");
|
QString link = linkElement.text();
|
||||||
|
|
||||||
QList<PtrLWJGLVersion> tempList;
|
// Make sure it's a download link.
|
||||||
|
if (link.endsWith("/download") && link.contains(lwjglRegex))
|
||||||
for (int i = 0; i < items.length(); i++)
|
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(items.at(i).isElement(), "load LWJGL list",
|
QString name = link.mid(lwjglRegex.indexIn(link) + 6);
|
||||||
"XML element isn't an element... wat?");
|
// Subtract 4 here to remove the .zip file extension.
|
||||||
|
name = name.left(lwjglRegex.matchedLength() - 10);
|
||||||
|
|
||||||
QDomElement linkElement = getDomElementByTagName(items.at(i).toElement(), "link");
|
QUrl url(link);
|
||||||
if (linkElement.isNull())
|
if (!url.isValid())
|
||||||
{
|
{
|
||||||
qDebug() << "Link element" << i << "in RSS feed doesn't exist! Skipping.";
|
qWarning() << "LWJGL version URL isn't valid:" << link << "Skipping.";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
qDebug() << "Discovered LWGL version" << name << "at" << link;
|
||||||
QString link = linkElement.text();
|
tempList.append(std::make_shared<LWJGLVersion>(name, link));
|
||||||
|
|
||||||
// Make sure it's a download link.
|
|
||||||
if (link.endsWith("/download") && link.contains(lwjglRegex))
|
|
||||||
{
|
|
||||||
QString name = link.mid(lwjglRegex.indexIn(link) + 6);
|
|
||||||
// Subtract 4 here to remove the .zip file extension.
|
|
||||||
name = name.left(lwjglRegex.matchedLength() - 10);
|
|
||||||
|
|
||||||
QUrl url(link);
|
|
||||||
if (!url.isValid())
|
|
||||||
{
|
|
||||||
qWarning() << "LWJGL version URL isn't valid:" << link << "Skipping.";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
qDebug() << "Discovered LWGL version" << name << "at" << link;
|
|
||||||
tempList.append(std::make_shared<LWJGLVersion>(name, link));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beginResetModel();
|
|
||||||
m_vlist.swap(tempList);
|
|
||||||
endResetModel();
|
|
||||||
|
|
||||||
qDebug() << "Loaded LWJGL list.";
|
|
||||||
finished();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
failed("Failed to load LWJGL list. Network error: " + reply->errorString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false);
|
beginResetModel();
|
||||||
reply->deleteLater();
|
m_vlist.swap(tempList);
|
||||||
}
|
endResetModel();
|
||||||
|
|
||||||
void LWJGLVersionList::failed(QString msg)
|
qDebug() << "Loaded LWJGL list.";
|
||||||
{
|
m_loading = false;
|
||||||
qCritical() << msg;
|
|
||||||
emit loadListFailed(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LWJGLVersionList::finished()
|
|
||||||
{
|
|
||||||
emit loadListFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LWJGLVersionList::setLoading(bool loading)
|
|
||||||
{
|
|
||||||
m_loading = loading;
|
|
||||||
emit loadingStateUpdated(m_loading);
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "BaseVersionList.h"
|
#include "BaseVersionList.h"
|
||||||
|
|
||||||
#include "multimc_logic_export.h"
|
#include "multimc_logic_export.h"
|
||||||
|
#include <net/NetJob.h>
|
||||||
|
|
||||||
class LWJGLVersion;
|
class LWJGLVersion;
|
||||||
typedef std::shared_ptr<LWJGLVersion> PtrLWJGLVersion;
|
typedef std::shared_ptr<LWJGLVersion> PtrLWJGLVersion;
|
||||||
@ -99,58 +100,17 @@ public:
|
|||||||
}
|
}
|
||||||
virtual int columnCount(const QModelIndex &parent) const override;
|
virtual int columnCount(const QModelIndex &parent) const override;
|
||||||
|
|
||||||
virtual bool isLoading() const;
|
public slots:
|
||||||
virtual bool errored() const
|
|
||||||
{
|
|
||||||
return m_errored;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual QString lastErrorMsg() const
|
|
||||||
{
|
|
||||||
return m_lastErrorMsg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
slots:
|
|
||||||
/*!
|
|
||||||
* Loads the version list.
|
|
||||||
* This is done asynchronously. On success, the loadListFinished() signal will
|
|
||||||
* be emitted. The list model will be reset as well, resulting in the modelReset()
|
|
||||||
* signal being emitted. Note that the model will be reset before loadListFinished() is
|
|
||||||
* emitted.
|
|
||||||
* If loading the list failed, the loadListFailed(QString msg),
|
|
||||||
* signal will be emitted.
|
|
||||||
*/
|
|
||||||
virtual void loadList();
|
virtual void loadList();
|
||||||
|
|
||||||
signals:
|
private slots:
|
||||||
/*!
|
void rssFailed(const QString & reason);
|
||||||
* Emitted when the list either starts or finishes loading.
|
void rssSucceeded();
|
||||||
* \param loading Whether or not the list is loading.
|
|
||||||
*/
|
|
||||||
void loadingStateUpdated(bool loading);
|
|
||||||
|
|
||||||
void loadListFinished();
|
|
||||||
|
|
||||||
void loadListFailed(QString msg);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<PtrLWJGLVersion> m_vlist;
|
QList<PtrLWJGLVersion> m_vlist;
|
||||||
|
Net::Download::Ptr m_rssDL;
|
||||||
QNetworkReply *m_netReply;
|
NetJobPtr m_rssDLJob;
|
||||||
QNetworkReply *reply;
|
QByteArray m_rssData;
|
||||||
|
bool m_loading = false;
|
||||||
bool m_loading;
|
|
||||||
bool m_errored;
|
|
||||||
QString m_lastErrorMsg;
|
|
||||||
|
|
||||||
void failed(QString msg);
|
|
||||||
|
|
||||||
void finished();
|
|
||||||
|
|
||||||
void setLoading(bool loading);
|
|
||||||
|
|
||||||
private
|
|
||||||
slots:
|
|
||||||
virtual void netRequestComplete();
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user