diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index f128a9240..03398f150 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -12,6 +12,7 @@ set(launcher_SRCS modManager/cmodlistview_moc.cpp modManager/cmodmanager.cpp modManager/imageviewer_moc.cpp + modManager/chroniclesextractor.cpp settingsView/csettingsview_moc.cpp firstLaunch/firstlaunch_moc.cpp main.cpp @@ -42,6 +43,7 @@ set(launcher_HEADERS modManager/cmodlistview_moc.h modManager/cmodmanager.h modManager/imageviewer_moc.h + modManager/chroniclesextractor.h settingsView/csettingsview_moc.h firstLaunch/firstlaunch_moc.h mainwindow_moc.h diff --git a/launcher/modManager/chroniclesextractor.cpp b/launcher/modManager/chroniclesextractor.cpp new file mode 100644 index 000000000..79a6c2919 --- /dev/null +++ b/launcher/modManager/chroniclesextractor.cpp @@ -0,0 +1,58 @@ +/* + * chroniclesextractor.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" + +#include "chroniclesextractor.h" + +void ChroniclesExtractor::installExe(QWidget *parent, QStringList exe) +{ + for(QString f : exe) + { + QFile file(f); + if(!file.open(QIODevice::ReadOnly)) + { + QMessageBox::critical(parent, tr("File cannot opened"), file.errorString()); + continue; + } + + QByteArray magic{"MZ"}; + QByteArray magicFile = file.read(magic.length()); + if(!magicFile.startsWith(magic)) + { + QMessageBox::critical(parent, tr("Invalid file selected"), tr("You have to select an gog installer file!")); + continue; + } + + QByteArray dataBegin = file.read(10'000'000); + const std::map<int, QByteArray> chronicles = { + {1, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Warlords of the Wasteland"), 90}}, + {2, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Conquest of the Underworld"), 92}}, + {3, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Masters of the Elements"), 86}}, + {4, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Clash of the Dragons"), 80}}, + {5, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - The World Tree"), 68}}, + {6, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - The Fiery Moon"), 68}}, + {7, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - Revolt of the Beastmasters"), 92}}, + {8, QByteArray{reinterpret_cast<const char*>(u"Heroes Chronicles - The Sword of Frost"), 76}} + }; + int chronicle = 0; + for (const auto& kv : chronicles) { + if(dataBegin.contains(kv.second)) + { + chronicle = kv.first; + break; + } + } + if(!chronicle) + { + QMessageBox::critical(parent, tr("Invalid file selected"), tr("You have to select an chronicle installer file!")); + continue; + } + } +} \ No newline at end of file diff --git a/launcher/modManager/chroniclesextractor.h b/launcher/modManager/chroniclesextractor.h new file mode 100644 index 000000000..c87751c36 --- /dev/null +++ b/launcher/modManager/chroniclesextractor.h @@ -0,0 +1,20 @@ +/* + * chroniclesextractor.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../StdInc.h" + +class ChroniclesExtractor : public QObject +{ + Q_OBJECT + +public: + static void installExe(QWidget *parent, QStringList exe); +}; \ No newline at end of file diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index 5c351b366..e3459d021 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/launcher/modManager/cmodlistview_moc.cpp @@ -20,6 +20,7 @@ #include "cmodlistmodel_moc.h" #include "cmodmanager.h" #include "cdownloadmanager_moc.h" +#include "chroniclesextractor.h" #include "../settingsView/csettingsview_moc.h" #include "../launcherdirs.h" #include "../jsonutils.h" @@ -55,7 +56,7 @@ void CModListView::dragEnterEvent(QDragEnterEvent* event) { if(event->mimeData()->hasUrls()) for(const auto & url : event->mimeData()->urls()) - for(const auto & ending : QStringList({".zip", ".h3m", ".h3c", ".vmap", ".vcmp", ".json"})) + for(const auto & ending : QStringList({".zip", ".h3m", ".h3c", ".vmap", ".vcmp", ".json", ".exe"})) if(url.fileName().endsWith(ending, Qt::CaseInsensitive)) { event->acceptProposedAction(); @@ -636,8 +637,8 @@ void CModListView::on_installFromFileButton_clicked() // https://bugreports.qt.io/browse/QTBUG-98651 QTimer::singleShot(0, this, [this] { - QString filter = tr("All supported files") + " (*.h3m *.vmap *.h3c *.vcmp *.zip *.json);;" + tr("Maps") + " (*.h3m *.vmap);;" + tr("Campaigns") + " (*.h3c *.vcmp);;" + tr("Configs") + " (*.json);;" + tr("Mods") + " (*.zip)"; - QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files (configs, mods, maps, campaigns) to install..."), QDir::homePath(), filter); + QString filter = tr("All supported files") + " (*.h3m *.vmap *.h3c *.vcmp *.zip *.json *.exe);;" + tr("Maps") + " (*.h3m *.vmap);;" + tr("Campaigns") + " (*.h3c *.vcmp);;" + tr("Configs") + " (*.json);;" + tr("Mods") + " (*.zip);;" + tr("Gog files") + " (*.exe)"; + QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files (configs, mods, maps, campaigns, gog files) to install..."), QDir::homePath(), filter); for(const auto & file : files) { @@ -786,6 +787,7 @@ void CModListView::installFiles(QStringList files) QStringList mods; QStringList maps; QStringList images; + QStringList exe; QVector<QVariantMap> repositories; // TODO: some better way to separate zip's with mods and downloaded repository files @@ -795,6 +797,8 @@ void CModListView::installFiles(QStringList files) mods.push_back(filename); else if(filename.endsWith(".h3m", Qt::CaseInsensitive) || filename.endsWith(".h3c", Qt::CaseInsensitive) || filename.endsWith(".vmap", Qt::CaseInsensitive) || filename.endsWith(".vcmp", Qt::CaseInsensitive)) maps.push_back(filename); + if(filename.endsWith(".exe", Qt::CaseInsensitive)) + exe.push_back(filename); else if(filename.endsWith(".json", Qt::CaseInsensitive)) { //download and merge additional files @@ -832,6 +836,9 @@ void CModListView::installFiles(QStringList files) if(!maps.empty()) installMaps(maps); + if(!exe.empty()) + ChroniclesExtractor::installExe(this, exe); + if(!images.empty()) loadScreenshots(); }