Work on URDE version detection and downloading

This commit is contained in:
Jack Andersen 2017-12-26 14:48:34 -10:00
parent d3223f0db4
commit a686debdcf
14 changed files with 275 additions and 142 deletions

View File

@ -27,7 +27,7 @@ list(APPEND PLAT_SRCS mainicon_qt.c)
add_executable(hecl-gui WIN32 MACOSX_BUNDLE
MainWindow.ui MainWindow.hpp MainWindow.cpp
FileDirDialog.hpp FileDirDialog.cpp
FileDirDialog.hpp
SysReqTableView.hpp SysReqTableView.cpp
VectorISATableView.hpp VectorISATableView.cpp
VectorISATableModel.hpp VectorISATableModelIntel.hpp

View File

@ -1,4 +1,9 @@
#include "Common.hpp"
#include <QStringList>
#ifndef _WIN32
#include <unistd.h>
#endif
#if __APPLE__
const QString CurPlatformString = QStringLiteral("macos");
@ -25,22 +30,13 @@ QString PlatformToString(Platform plat)
}
}
#if ZEUS_ARCH_X86_64
const QString CurArchitectureString = QStringLiteral("x86_64");
#elif ZEUS_ARCH_X86
const QString CurArchitectureString = QStringLiteral("x86");
#elif ZEUS_ARCH_ARM
const QString CurArchitectureString = QStringLiteral("arm");
#elif ZEUS_ARCH_AARCH64
const QString CurArchitectureString = QStringLiteral("aarch64");
#else
#error HECL does not know which architecture to fetch for
#endif
Architecture CurArchitecture = Architecture::Invalid;
QString CurArchitectureString;
Platform StringToPlatform(const QString& str)
{
for (int i = 1; i < int(Platform::MAXPlatform); ++i)
if (str.contains(PlatformToString(Platform(i)), Qt::CaseInsensitive))
if (!str.compare(PlatformToString(Platform(i)), Qt::CaseInsensitive))
return Platform(i);
return Platform::Invalid;
}
@ -65,7 +61,7 @@ QString ArchitectureToString(Architecture arch)
Architecture StringToArchitecture(const QString& str)
{
for (int i = 1; i < int(Architecture::MAXArchitecture); ++i)
if (str.contains(ArchitectureToString(Architecture(i)), Qt::CaseInsensitive))
if (!str.compare(ArchitectureToString(Architecture(i)), Qt::CaseInsensitive))
return Architecture(i);
return Architecture::Invalid;
}
@ -96,7 +92,62 @@ QString VectorISAToString(VectorISA visa)
VectorISA StringToVectorISA(const QString& str)
{
for (int i = 1; i < int(VectorISA::MAXVectorISA); ++i)
if (str.contains(VectorISAToString(VectorISA(i)), Qt::CaseInsensitive))
if (!str.compare(VectorISAToString(VectorISA(i)), Qt::CaseInsensitive))
return VectorISA(i);
return VectorISA::Invalid;
}
URDEVersion::URDEVersion(const QString& filename)
{
int idx;
QString useFilename = filename;
if ((idx = filename.indexOf('.')) >= 0)
{
m_extension = QString(filename).remove(0, idx);
useFilename.truncate(idx);
}
QStringList list = useFilename.split('-');
if (list.size() >= 2)
m_version = list[1].toInt();
if (list.size() >= 3)
m_platform = StringToPlatform(list[2]);
if (list.size() >= 4)
m_architecture = StringToArchitecture(list[3]);
if (list.size() >= 5)
m_vectorISA = StringToVectorISA(list[4]);
}
QString URDEVersion::fileString(bool withExtension) const
{
if (m_version < 0)
return {};
if (withExtension && !m_extension.isEmpty())
return QString("urde-%1-%2-%3-%4%5").arg(QString::number(m_version),
PlatformToString(m_platform),
ArchitectureToString(m_architecture),
VectorISAToString(m_vectorISA),
m_extension);
else
return QString("urde-%1-%2-%3-%4").arg(QString::number(m_version),
PlatformToString(m_platform),
ArchitectureToString(m_architecture),
VectorISAToString(m_vectorISA));
}
void InitializePlatform()
{
#if ZEUS_ARCH_X86_64
const_cast<Architecture&>(CurArchitecture) = Architecture::X86_64;
#elif ZEUS_ARCH_X86
#if !defined(__APPLE__) && !defined(_WIN32)
const_cast<Architecture&>(CurArchitecture) =
(sysconf(_SC_WORD_BIT) == 64 ? Architecture::X86_64 : Architecture::X86);
#elif _WIN32
bool isWOW = false;
IsWow64Process(GetCurrentProcess(), &isWOW);
const_cast<Architecture&>(CurArchitecture) =
(isWOW ? Architecture::X86_64 : Architecture::X86);
#endif
#endif
const_cast<QString&>(CurArchitectureString) = ArchitectureToString(CurArchitecture);
}

View File

@ -2,6 +2,7 @@
#define GUI_COMMON_HPP
#include <QString>
#include <QMetaType>
#include "zeus/Math.hpp"
enum class Platform
@ -37,17 +38,8 @@ enum class Architecture
QString ArchitectureToString(Architecture arch);
Architecture StringToArchitecture(const QString& str);
#if ZEUS_ARCH_X86_64
constexpr Architecture CurArchitecture = Architecture::X86_64;
#elif ZEUS_ARCH_X86
constexpr Architecture CurArchitecture = Architecture::X86;
#elif ZEUS_ARCH_ARM
constexpr Architecture CurArchitecture = Architecture::ARM;
#elif ZEUS_ARCH_AARCH64
constexpr Architecture CurArchitecture = Architecture::AARCH64;
#endif
extern const QString CurArchitectureString;
extern Architecture CurArchitecture;
extern QString CurArchitectureString;
enum class VectorISA
{
@ -67,11 +59,22 @@ VectorISA StringToVectorISA(const QString& str);
class URDEVersion
{
int m_version = -1;
VectorISA m_vectorISA;
Platform m_platform = CurPlatform;
Architecture m_architecture = CurArchitecture;
VectorISA m_vectorISA = VectorISA::Invalid;
QString m_extension;
public:
URDEVersion() = default;
explicit URDEVersion(const QString& filename);
bool isValid() const { return m_version >= 0; }
QString fileString(bool withExtension) const;
int getVersion() const { return m_version; }
Platform getPlatform() const { return m_platform; }
Architecture getArchitecture() const { return m_architecture; }
VectorISA getVectorISA() const { return m_vectorISA; }
};
Q_DECLARE_METATYPE(URDEVersion);
void InitializePlatform();
#endif // GUI_COMMON_HPP

View File

@ -84,14 +84,12 @@ void DownloadManager::indexFinished()
QStringList files;
while (true)
while (!m_indexInProgress->atEnd())
{
if (m_indexInProgress->atEnd())
break;
QByteArray line = m_indexInProgress->readLine();
QString line = QString::fromUtf8(m_indexInProgress->readLine()).trimmed();
if (line.isEmpty())
continue;
files.push_back(QString::fromUtf8(line).trimmed());
files.push_back(line);
}
if (m_indexCompletionHandler)

View File

@ -1,68 +0,0 @@
#include "FileDirDialog.hpp"
#include <QModelIndex>
#include <QPushButton>
#include <QTreeView>
#include <QListView>
#include <QEvent>
#include <QDir>
FileDirDialog::FileDirDialog(QWidget *parent)
: QFileDialog(parent)
{
m_selectedFiles.clear();
this->setOption(QFileDialog::DontUseNativeDialog, true);
this->setFileMode(QFileDialog::Directory);
QList<QPushButton*> btns = this->findChildren<QPushButton*>();
for (int i = 0; i < btns.size(); ++i)
{
QString text = btns[i]->text();
if (text.toLower().contains("open") || text.toLower().contains("choose"))
{
m_btnOpen = btns[i];
break;
}
}
if (!m_btnOpen)
return;
m_btnOpen->installEventFilter(this);
m_btnOpen->disconnect(SIGNAL(clicked()));
connect(m_btnOpen, SIGNAL(clicked()), this, SLOT(chooseClicked()));
m_listView = findChild<QListView*>("listView");
if (m_listView) {
m_listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
m_treeView = findChild<QTreeView*>();
if (m_treeView)
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
bool FileDirDialog::eventFilter( QObject* watched, QEvent* event )
{
QPushButton *btn = qobject_cast<QPushButton*>(watched);
if (btn && !btn->isEnabled() && event->type()==QEvent::EnabledChange)
btn->setEnabled(true);
return QWidget::eventFilter(watched, event);
}
void FileDirDialog::chooseClicked()
{
QModelIndexList indexList = m_listView->selectionModel()->selectedIndexes();
foreach (QModelIndex index, indexList)
if (index.column( )== 0)
m_selectedFiles.append(this->directory().absolutePath() + "/" + index.data().toString());
QDialog::accept();
}
QStringList FileDirDialog::selectedFiles()
{
return m_selectedFiles;
}

View File

@ -2,29 +2,12 @@
#define FILEDIRDIALOG_HPP
#include <QFileDialog>
#include <QTreeWidget>
#include <QPushButton>
#include <QStringList>
class QPushButton;
class QTreeView;
class QListView;
class FileDirDialog : public QFileDialog
{
Q_OBJECT
private:
QListView* m_listView = nullptr;
QTreeView* m_treeView = nullptr;
QPushButton* m_btnOpen = nullptr;
QStringList m_selectedFiles;
public slots:
void chooseClicked();
public:
FileDirDialog(QWidget* parent = nullptr);
QStringList selectedFiles();
bool eventFilter(QObject* watched, QEvent* event);
FileDirDialog(QWidget* parent = nullptr) : QFileDialog(parent) { setFileMode(QFileDialog::Directory); }
};
#endif // FILEDIRDIALOG_HPP

View File

@ -12,6 +12,7 @@ MainWindow::MainWindow(QWidget *parent) :
m_ui(new Ui::MainWindow)
, m_heclProc(this)
, m_dlManager(this)
, m_settings("AxioDL", "HECL", this)
{
m_ui->setupUi(this);
m_ui->heclTabs->setCurrentIndex(0);
@ -24,6 +25,16 @@ MainWindow::MainWindow(QWidget *parent) :
m_ui->currentBinaryLabel->setFont(mFont);
m_ui->recommendedBinaryLabel->setFont(mFont);
m_updateURDEButton = new QPushButton(QStringLiteral("Update URDE"), m_ui->centralwidget);
m_ui->gridLayout->addWidget(m_updateURDEButton, 2, 3, 1, 1);
m_updateURDEButton->hide();
QPalette pal = m_updateURDEButton->palette();
pal.setColor(QPalette::Button, QColor(53,53,72));
m_updateURDEButton->setPalette(pal);
connect(m_updateURDEButton, SIGNAL(clicked()), this, SLOT(onUpdateURDEPressed()));
setPath(m_settings.value(QStringLiteral("working_dir")).toString());
m_dlManager.connectWidgets(m_ui->downloadProgressBar, m_ui->downloadErrorLabel,
std::bind(&MainWindow::onIndexDownloaded, this, std::placeholders::_1),
std::bind(&MainWindow::onBinaryDownloaded, this, std::placeholders::_1));
@ -557,20 +568,131 @@ void MainWindow::onExtract()
void MainWindow::onReturnPressed()
{
if (sender() == m_ui->pathEdit && !m_ui->pathEdit->text().isEmpty())
m_path = m_ui->pathEdit->text();
setPath(m_ui->pathEdit->text());
}
void MainWindow::onIndexDownloaded(const QStringList& index)
{
int bestVersion = 0;
m_ui->binaryComboBox->clear();
for (const QString& str : index)
m_ui->binaryComboBox->addItem(str);
{
URDEVersion version(str);
if (m_ui->sysReqTable->willRun(version))
bestVersion = m_ui->binaryComboBox->count();
m_ui->binaryComboBox->addItem(version.fileString(false), QVariant::fromValue(version));
}
m_ui->binaryComboBox->setCurrentIndex(bestVersion);
m_recommendedVersion = m_ui->binaryComboBox->itemData(bestVersion).value<URDEVersion>();
m_ui->recommendedBinaryLabel->setText(m_recommendedVersion.fileString(false));
m_ui->binaryComboBox->setEnabled(true);
if (!m_path.isEmpty())
{
checkDownloadedBinary();
m_ui->downloadButton->setEnabled(true);
}
}
void MainWindow::onDownloadPressed()
{
m_updateURDEButton->hide();
QString filename = m_ui->binaryComboBox->currentData().value<URDEVersion>().fileString(true);
printf("Downloading %s\n", filename.toUtf8().data());
m_ui->launchBtn->setEnabled(false);
m_dlManager.fetchBinary(filename, m_path + '/' + filename);
}
void MainWindow::onUpdateURDEPressed()
{
m_ui->heclTabs->setCurrentIndex(1);
onDownloadPressed();
}
void MainWindow::onBinaryDownloaded(const QString& file)
{
QFileInfo path(file);
#ifndef _WIN32
QProcess untar;
untar.setWorkingDirectory(path.dir().absolutePath());
untar.start("tar", {"-xvf", path.fileName()});
untar.waitForFinished();
#if __APPLE__
QFile::rename(path.dir().absoluteFilePath(path.baseName()) + ".app", "urde.app");
#else
QFile::rename(path.dir().absoluteFilePath(path.baseName()), "urde");
#endif
QFile::remove(file);
#else
QFile::rename(file, "urde.exe");
#endif
checkDownloadedBinary();
}
void MainWindow::checkDownloadedBinary()
{
m_updateURDEButton->hide();
#if __APPLE__
QString urdePath = m_path + "/urde.app/Contents/MacOS/urde";
#elif _WIN32
QString urdePath = m_path + "urde.exe";
#else
QString urdePath = m_path + "urde";
#endif
QProcess proc;
proc.start(urdePath, {"--dlpackage"}, QIODevice::ReadOnly);
if (proc.waitForStarted())
{
proc.waitForFinished();
QString dlPackage = QString::fromUtf8(proc.readLine()).trimmed();
if (proc.exitCode() == 100)
{
if (dlPackage.isEmpty())
{
m_ui->currentBinaryLabel->setText(QStringLiteral("unknown"));
}
else
{
URDEVersion v(dlPackage);
m_ui->currentBinaryLabel->setText(v.fileString(false));
if (m_recommendedVersion.isValid() && v.isValid() &&
m_recommendedVersion.getVersion() > v.getVersion())
{
m_updateURDEButton->show();
}
}
}
else
{
m_ui->currentBinaryLabel->setText(QStringLiteral("unknown"));
}
}
else
{
m_ui->currentBinaryLabel->setText(QStringLiteral("none"));
}
}
void MainWindow::setPath(const QString& path)
{
if (!path.isEmpty())
{
m_path = path;
m_settings.setValue(QStringLiteral("working_dir"), m_path);
m_ui->pathEdit->setText(m_path);
m_ui->extractBtn->setEnabled(true);
m_ui->packageBtn->setEnabled(true);
m_ui->downloadButton->setToolTip(QString());
m_ui->downloadButton->setEnabled(m_ui->binaryComboBox->isEnabled());
checkDownloadedBinary();
}
else
{
m_ui->downloadButton->setToolTip(QStringLiteral("Working directory must be set"));
m_ui->downloadButton->setEnabled(false);
m_ui->currentBinaryLabel->setText(QStringLiteral("none"));
}
}
void MainWindow::initSlots()
@ -607,15 +729,8 @@ void MainWindow::initSlots()
if (dialog.selectedFiles().size() <= 0)
return;
QString path = dialog.selectedFiles().at(0);
/* TODO: Add beacon detection */
if (!path.isEmpty())
{
m_path = path;
m_ui->pathEdit->setText(m_path);
m_ui->extractBtn->setEnabled(true);
m_ui->packageBtn->setEnabled(true);
}
setPath(dialog.selectedFiles().at(0));
});
connect(m_ui->packageBtn, &QPushButton::clicked, [=](){
@ -632,6 +747,8 @@ void MainWindow::initSlots()
m_heclProc.setProcessChannelMode(QProcess::ProcessChannelMode::MergedChannels);
m_heclProc.start("../hecl/driver/hecl.exe", {"package", "-y"});
});
connect(m_ui->downloadButton, SIGNAL(clicked()), this, SLOT(onDownloadPressed()));
}
void MainWindow::setTextTermFormatting(QTextEdit* textEdit, const QString& text)

View File

@ -5,8 +5,10 @@
#include <QProcess>
#include <memory>
#include "DownloadManager.hpp"
#include "Common.hpp"
class QTextEdit;
class QTextCharFormat;
class QPushButton;
namespace Ui {
class MainWindow;
@ -20,6 +22,9 @@ class MainWindow : public QMainWindow
QString m_path;
QProcess m_heclProc;
DownloadManager m_dlManager;
QSettings m_settings;
URDEVersion m_recommendedVersion;
QPushButton* m_updateURDEButton;
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
@ -28,7 +33,11 @@ public:
private slots:
void onExtract();
void onReturnPressed();
void onDownloadPressed();
void onUpdateURDEPressed();
private:
void checkDownloadedBinary();
void setPath(const QString& path);
void initSlots();
void onIndexDownloaded(const QStringList& index);
void onBinaryDownloaded(const QString& file);

View File

@ -289,7 +289,7 @@ p, li { white-space: pre-wrap; }
<item row="0" column="1">
<widget class="QLabel" name="currentBinaryLabel">
<property name="text">
<string>fetching...</string>
<string>none</string>
</property>
</widget>
</item>
@ -310,6 +310,12 @@ p, li { white-space: pre-wrap; }
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
@ -481,6 +487,9 @@ p, li { white-space: pre-wrap; }
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>

View File

@ -34,9 +34,6 @@ SysReqTableModel::SysReqTableModel(QObject* parent)
m_osVersion.sprintf("macOS %d.%d", m_macosMajor, m_macosMinor);
else
m_osVersion.sprintf("macOS %d.%d.%d", m_macosMajor, m_macosMinor, m_macosPatch);
#elif _WIN32
#else
m_is64Bit = sysconf(_SC_WORD_BIT) == 64;
#endif
}
@ -84,7 +81,7 @@ QVariant SysReqTableModel::data(const QModelIndex& index, int role) const
{
case 0:
#if ZEUS_ARCH_X86 || ZEUS_ARCH_X86_64
return QStringLiteral("x86, x86_64");
return QStringLiteral("x86_64");
#else
return {};
#endif
@ -107,7 +104,7 @@ QVariant SysReqTableModel::data(const QModelIndex& index, int role) const
{
case 0:
#if ZEUS_ARCH_X86 || ZEUS_ARCH_X86_64
return m_is64Bit ? QStringLiteral("x86_64") : QStringLiteral("x86");
return CurArchitectureString;
#else
return {};
#endif

View File

@ -19,7 +19,6 @@ class SysReqTableModel : public QAbstractTableModel
int m_macosPatch = 0;
#endif
QString m_osVersion;
bool m_is64Bit = true;
public:
SysReqTableModel(QObject* parent = Q_NULLPTR);
int rowCount(const QModelIndex& parent = QModelIndex()) const;
@ -37,6 +36,13 @@ class SysReqTableView : public QTableView
public:
SysReqTableView(QWidget* parent = Q_NULLPTR);
void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE;
const SysReqTableModel& getModel() const { return m_model; }
const VectorISATableView& getVectorISATable() const { return m_vectorISATable; }
bool willRun(const URDEVersion& v) const
{
return v.getArchitecture() == CurArchitecture && v.getPlatform() == CurPlatform &&
m_vectorISATable.willRun(v.getVectorISA());
}
};
#endif // GUI_SYSREQTABLEVIEW_HPP

View File

@ -82,6 +82,29 @@ public:
return VectorISA::AVX2;
}
}
bool willRun(VectorISA visa) const
{
switch (visa)
{
default:
return false;
case VectorISA::X87:
return true;
case VectorISA::SSE:
return m_features.SSE1;
case VectorISA::SSE2:
return m_features.SSE2;
case VectorISA::SSE3:
return m_features.SSE3;
case VectorISA::SSE41:
return m_features.SSE41;
case VectorISA::AVX:
return m_features.AVX;
case VectorISA::AVX2:
return m_features.AVX2;
}
}
};
#endif // GUI_VECTORISATABLEMODELINTEL_HPP

View File

@ -22,6 +22,7 @@ public:
VectorISATableView(QWidget* parent = Q_NULLPTR);
void paintEvent(QPaintEvent* e) Q_DECL_OVERRIDE;
VectorISA getISA() const { return m_model.getISA(m_maxISA); }
bool willRun(VectorISA visa) const { return m_model.willRun(visa); }
};
#endif // GUI_VECTORISATABLEVIEW_HPP

View File

@ -1,6 +1,7 @@
#include <QApplication>
#include <QStyleFactory>
#include "MainWindow.hpp"
#include "Common.hpp"
extern const size_t MAINICON_QT_SZ;
extern const uint8_t MAINICON_QT[];
@ -26,6 +27,8 @@ static QIcon MakeAppIcon()
int main(int argc, char* argv[])
{
InitializePlatform();
QApplication a(argc, argv);
a.setStyle(QStyleFactory::create("Fusion"));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
@ -37,10 +40,10 @@ int main(int argc, char* argv[])
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, QColor(53,53,53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(25,25,25));
darkPalette.setColor(QPalette::Base, QColor(42,42,42));
darkPalette.setColor(QPalette::Disabled, QPalette::Base, QColor(25,25,25,53));
darkPalette.setColor(QPalette::AlternateBase, QColor(53,53,53));
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
darkPalette.setColor(QPalette::ToolTipBase, QColor(42,42,42));
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(255,255,255,120));
@ -52,7 +55,8 @@ int main(int argc, char* argv[])
darkPalette.setColor(QPalette::Link, QColor(42,130,218));
darkPalette.setColor(QPalette::Highlight, QColor(42,130,218));
darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(42,130,218,53));
darkPalette.setColor(QPalette::HighlightedText, Qt::black);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(255,255,255,120));
a.setPalette(darkPalette);
MainWindow w;