Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hub/ThunderHub.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Project {
Depends { name: "cpp" }
Depends { name: "bundle" }
Depends { name: "7zip" }
Depends { name: "Qt"; submodules: ["core", "quickwidgets", "network"]; }
Depends { name: "Qt"; submodules: ["core", "quickwidgets", "network", "xml"]; }
property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle
bundle.infoPlist: ({
"NSHumanReadableCopyright": "(C) 2007-" + ThunderHub.COPYRIGHT_YEAR + " by " + ThunderHub.COPYRIGHT_AUTHOR
Expand Down
111 changes: 104 additions & 7 deletions hub/feed/feedmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
#include <QNetworkReply>
#include <QNetworkAccessManager>

#include <QtXml/QDomDocument>

FeedManager::FeedManager(QObject *parent) :
QObject(parent),
QAbstractListModel(parent),
m_manager(new QNetworkAccessManager()) {

QNetworkRequest req(QUrl("http://thunderengine.org/feed.xml"));
Expand All @@ -19,14 +21,109 @@ FeedManager::~FeedManager() {
delete m_manager;
}

QString FeedManager::blogFeed() const {
return m_blogData;
}

void FeedManager::onUpdateCheckFinished() {
QNetworkReply *reply = dynamic_cast<QNetworkReply *>(sender());
if(reply) {
m_blogData = reply->readAll();
emit blogFeedChanged();
m_items.clear();

QDomDocument doc;
doc.setContent(reply->readAll());
QDomElement root = doc.documentElement();

QDomNodeList entries = root.elementsByTagName("entry");
for(int i = 0; i < entries.count(); ++i) {
QDomNode entryNode = entries.at(i);

RssItem item;

QDomNodeList titleNodes = entryNode.toElement().elementsByTagName("title");
if(!titleNodes.isEmpty()) {
item.title = extractTextFromNode(titleNodes.at(0));
}

QDomNodeList linkNodes = entryNode.toElement().elementsByTagName("link");
if(!linkNodes.isEmpty()) {
QDomElement linkElem = linkNodes.at(0).toElement();
if (linkElem.hasAttribute("href")) {
item.link = linkElem.attribute("href");
}
}

QDomNodeList summaryNodes = entryNode.toElement().elementsByTagName("summary");
if(!summaryNodes.isEmpty()) {
item.description = extractTextFromNode(summaryNodes.at(0));
}

QDomNodeList categoryNodes = entryNode.toElement().elementsByTagName("category");
if(!categoryNodes.isEmpty()) {
QDomElement categoryElem = categoryNodes.at(0).toElement();
if (categoryElem.hasAttribute("term")) {
item.category = categoryElem.attribute("term");
}
}

QDomNodeList thumbnailNodes = entryNode.toElement().elementsByTagName("media:thumbnail");
if(!thumbnailNodes.isEmpty()) {
QDomElement thumbnailElem = thumbnailNodes.at(0).toElement();
if (thumbnailElem.hasAttribute("url")) {
item.media = thumbnailElem.attribute("url");
}
}

if(!item.title.isEmpty()) {
m_items.push_back(item);
}
}

emit layoutAboutToBeChanged();
emit layoutChanged();
}
}

QString FeedManager::extractTextFromNode(const QDomNode &node) {
QString result;
QDomNode child = node.firstChild();

while (!child.isNull()) {
if (child.isText()) {
result += child.toText().data();
} else if (child.isCDATASection()) {
result += child.toCDATASection().data();
}
child = child.nextSibling();
}

return result.trimmed();
}

int FeedManager::rowCount(const QModelIndex &parent) const {
if(parent.isValid()) {
return 0;
}
return m_items.size();
}

QVariant FeedManager::data(const QModelIndex &index, int role) const {
if(!index.isValid()) {
return QVariant();
}
RssItem item( m_items.at(index.row()) );
switch(role) {
case Title: { return item.title; }
case Brief: { return item.description; }
case Link: { return item.link; }
case Media: { return item.media; };
default: break;
}
return QVariant();
}

QHash<int, QByteArray> FeedManager::roleNames() const {
QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
roles[Title] = "title";
roles[Brief] = "brief";
roles[Link] = "link";
roles[Media] = "icon";

return roles;
}
37 changes: 27 additions & 10 deletions hub/feed/feedmanager.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,49 @@
#ifndef FEEDMANAGER_H
#define FEEDMANAGER_H

#include <QObject>
#include <QAbstractListModel>

class QNetworkAccessManager;
class QNetworkReply;
class QDomNode;

struct RssItem {
QString title;
QString description;
QString link;
QString category;
QString media;
};

class FeedManager : public QObject {
class FeedManager : public QAbstractListModel {
Q_OBJECT

Q_PROPERTY(QString blogFeed READ blogFeed NOTIFY blogFeedChanged)
enum Roles {
Title,
Brief,
Link,
Media
};

public:
explicit FeedManager(QObject *parent = nullptr);
~FeedManager();

QString blogFeed() const;

signals:
void blogFeedChanged();

private slots:
void onUpdateCheckFinished();

private:
QString extractTextFromNode(const QDomNode &node);

int rowCount(const QModelIndex &parent) const override;

QVariant data(const QModelIndex &index, int role) const override;

QHash<int, QByteArray> roleNames() const override;

private:
QNetworkAccessManager *m_manager;

QString m_blogData;
QList<RssItem> m_items;

};

Expand Down
2 changes: 1 addition & 1 deletion hub/install/downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void Downloader::onDownloadFinished() {

void Downloader::onExtractFinished() {
if(!m_extractComponents.isEmpty()) {
m_extractor.extract(m_extractComponents.takeFirst(), Settings::instance()->sdkDir());
m_extractor.extract(m_extractComponents.takeFirst(), Settings::instance()->sdkDir(), m_sdk->version);
} else {
m_sdk->progress = -1;
m_sdk->status.clear();
Expand Down
18 changes: 13 additions & 5 deletions hub/install/extractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ Extractor::~Extractor() {
m_thread.wait();
}

void Extractor::extract(const QString archiveName, const QString outputPath) {
void Extractor::extract(const QString &archiveName, const QString &outputPath, const QString &version) {
m_archiveName = archiveName;
m_outputPath = outputPath;
m_version = version;

m_thread.start();
}
Expand Down Expand Up @@ -89,10 +90,17 @@ void Extractor::doWork() {
SzArEx_GetFileNameUtf16(&db, i, temp);

QString sub(QString::fromUtf16(temp));
sub.remove("sdk/");
sub.remove("install-root/");
sub.remove("release/");
QString path(m_outputPath + "/" + sub);
QStringList list = sub.split('/', Qt::SkipEmptyParts);
list.removeOne("sdk");
list.removeOne("install-root");
list.removeOne("release");
if(list.isEmpty()) {
continue;
}

list.front() = m_version;

QString path(m_outputPath + "/" + list.join('/'));

if(isDir) {
QDir dir;
Expand Down
3 changes: 2 additions & 1 deletion hub/install/extractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Extractor : public QObject {
explicit Extractor(QObject *parent = 0);
~Extractor();

void extract(const QString archiveName, const QString outputPath);
void extract(const QString &archiveName, const QString &outputPath, const QString &version);

signals:
void extractProgress(qint64 filesExtracted, qint64 filesTotal);
Expand All @@ -24,6 +24,7 @@ private slots:

QString m_archiveName;
QString m_outputPath;
QString m_version;

};

Expand Down
20 changes: 9 additions & 11 deletions hub/install/installmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ void Sdk::checkInstalled() {
if(path.isEmpty()) {
path = Settings::instance()->sdkDir() + "/" + version;
#ifdef Q_OS_WINDOWS
path += "/windows/x86_64/bin/WorldEditor.exe";
path += QString("/windows/x86_64/bin/") + EDITOR_NAME + ".exe";
#endif
#ifdef Q_OS_LINUX
path += "/linux/x86_64/bin/WorldEditor";
path += QString("/linux/x86_64/bin/") + EDITOR_NAME;
#endif
#ifdef Q_OS_MACOS
path += "/macos/arm64/WorldEditor.app/Contents/MacOS/WorldEditor";
path += QString("/macos/arm64/") + EDITOR_NAME + ".app/Contents/MacOS/" + EDITOR_NAME;
#endif
}

Expand Down Expand Up @@ -128,7 +128,7 @@ int InstallModel::rowCount(const QModelIndex &parent) const {

int count = 0;
for(auto &it : m_sdk) {
if(it.installed) {
if(it.installed || it.progress != -1) {
count++;
}
}
Expand All @@ -140,7 +140,7 @@ QVariant InstallModel::data(const QModelIndex &index, int role) const {
if(index.isValid()) {
int idx = -1;
for(auto &it : m_sdk) {
if(it.installed) {
if(it.installed || it.progress != -1) {
idx++;
if(idx == index.row()) {
QFileInfo info(it.path);
Expand Down Expand Up @@ -319,7 +319,7 @@ void InstallModel::locateSdk() {
QString path = QFileDialog::getOpenFileName(nullptr, tr("Locate the ") + EDITOR_NAME, Settings::instance()->sdkDir(), name);
if(!path.isEmpty()) {
#ifdef Q_OS_MACOS
path += "/Contents/MacOS/WorldEditor";
path += QString("/Contents/MacOS/") + EDITOR_NAME;
#endif
QFileInfo info(path);

Expand Down Expand Up @@ -433,15 +433,14 @@ void InstallModel::commitInstallRecord() {

QStringList values;
foreach(auto &it, m_sdk) {
if(it.installed) {
if(it.installed || it.progress != -1) {
values << it.path + ";" + it.version;
}
}
values.removeDuplicates();
settings.setValue(gInstalls, values);

emit layoutAboutToBeChanged();
emit layoutChanged();
onJobUpdated();
}

void InstallModel::onJobFinished() {
Expand All @@ -451,8 +450,7 @@ void InstallModel::onJobFinished() {
job->deleteLater();
}

emit layoutAboutToBeChanged();
emit layoutChanged();
onJobUpdated();
}

void InstallModel::onJobUpdated() {
Expand Down
1 change: 1 addition & 0 deletions hub/res/hub.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
<file>qml/components/StyledPathEdit.qml</file>
<file>icons/close.png</file>
<file>icons/folder.png</file>
<file>qml/components/SideButton.qml</file>
</qresource>
</RCC>
Loading
Loading