diff --git a/AUTHORS.md b/AUTHORS.md index 44c8fbc2e8..0939409926 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -76,6 +76,7 @@ Programmers Eduard Cot (trombonecot) Eli2 Emanuel Guével (potatoesmaster) + Eris Caffee (eris) eroen escondida Evgeniy Mineev (sandstranger) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f02bed33..2141d20007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,7 @@ Feature #1465: "Reset" argument for AI functions Feature #2491: Ability to make OpenMW "portable" Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record + Feature #2766: Warn user if their version of Morrowind is not the latest. Feature #2780: A way to see current OpenMW version in the console Feature #3245: Grid and angle snapping for the OpenMW-CS Feature #3616: Allow Zoom levels on the World Map diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 167f6b9c26..accb27a48b 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -570,7 +570,7 @@ void Launcher::MainDialog::play() msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setText(tr("
You do not have a game file selected.

\ OpenMW will not start without a game file selected.
")); - msgBox.exec(); + msgBox.exec(); return; } diff --git a/apps/wizard/existinginstallationpage.cpp b/apps/wizard/existinginstallationpage.cpp index 886fcd95db..42b7766693 100644 --- a/apps/wizard/existinginstallationpage.cpp +++ b/apps/wizard/existinginstallationpage.cpp @@ -123,6 +123,11 @@ void Wizard::ExistingInstallationPage::on_browseButton_clicked() return; } + if (!versionIsOK(info.absolutePath())) + { + return; + } + QString path(QDir::toNativeSeparators(info.absolutePath())); QList items = installationsList->findItems(path, Qt::MatchExactly); @@ -165,3 +170,36 @@ int Wizard::ExistingInstallationPage::nextId() const { return MainWizard::Page_LanguageSelection; } + +bool Wizard::ExistingInstallationPage::versionIsOK(QString directory_name) +{ + QDir directory = QDir(directory_name); + QFileInfoList infoList = directory.entryInfoList(QStringList(QString("Morrowind.bsa"))); + if (infoList.size() == 1) + { + qint64 actualFileSize = infoList.at(0).size(); + const qint64 expectedFileSize = 310459500; // Size of Morrowind.bsa in Steam and GOG editions. + + if (actualFileSize == expectedFileSize) + { + return true; + } + + QMessageBox msgBox; + msgBox.setWindowTitle(QObject::tr("Most recent Morrowind not detected")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + msgBox.setText(QObject::tr("
There may be a more recent version of Morrowind available.

\ + Do you wish to continue anyway?
")); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + { + return true; + } + + return false; + } + + return false; +} diff --git a/apps/wizard/existinginstallationpage.hpp b/apps/wizard/existinginstallationpage.hpp index fbbbe432ee..6bdc5df134 100644 --- a/apps/wizard/existinginstallationpage.hpp +++ b/apps/wizard/existinginstallationpage.hpp @@ -3,6 +3,8 @@ #include "ui_existinginstallationpage.h" +#include + namespace Wizard { class MainWizard; @@ -25,9 +27,10 @@ namespace Wizard private: MainWizard *mWizard; + bool versionIsOK(QString directory_name); + protected: void initializePage() override; - }; } diff --git a/apps/wizard/installationpage.cpp b/apps/wizard/installationpage.cpp index 9c90b0bbf7..8aad714be3 100644 --- a/apps/wizard/installationpage.cpp +++ b/apps/wizard/installationpage.cpp @@ -8,8 +8,9 @@ #include "mainwizard.hpp" -Wizard::InstallationPage::InstallationPage(QWidget *parent) : - QWizardPage(parent) +Wizard::InstallationPage::InstallationPage(QWidget *parent, Config::GameSettings &gameSettings) : + QWizardPage(parent), + mGameSettings(gameSettings) { mWizard = qobject_cast(parent); @@ -18,7 +19,7 @@ Wizard::InstallationPage::InstallationPage(QWidget *parent) : mFinished = false; mThread = new QThread(); - mUnshield = new UnshieldWorker(); + mUnshield = new UnshieldWorker(mGameSettings.value("morrowind-bsa-filesize").toLongLong()); mUnshield->moveToThread(mThread); connect(mThread, SIGNAL(started()), @@ -47,6 +48,10 @@ Wizard::InstallationPage::InstallationPage(QWidget *parent) : connect(mUnshield, SIGNAL(requestFileDialog(Wizard::Component)), this, SLOT(showFileDialog(Wizard::Component)), Qt::QueuedConnection); + + connect(mUnshield, SIGNAL(requestOldVersionDialog()), + this, SLOT(showOldVersionDialog()) + , Qt::QueuedConnection); } Wizard::InstallationPage::~InstallationPage() @@ -181,6 +186,34 @@ void Wizard::InstallationPage::showFileDialog(Wizard::Component component) mUnshield->setDiskPath(path); } +void Wizard::InstallationPage::showOldVersionDialog() +{ + logTextEdit->appendHtml(tr("

Detected old version of component Morrowind.

")); + mWizard->addLogText(tr("Detected old version of component Morrowind.")); + + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Morrowind Installation")); + msgBox.setIcon(QMessageBox::Information); + msgBox.setText(QObject::tr("There may be a more recent version of Morrowind available.

Do you wish to continue anyway?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + + int ret = msgBox.exec(); + if (ret == QMessageBox::No) + { + logTextEdit->appendHtml(tr("


\ + Error: The installation was aborted by the user

")); + + mWizard->addLogText(QLatin1String("Error: The installation was aborted by the user")); + mWizard->mError = true; + + emit completeChanged(); + return; + } + + mUnshield->wakeAll(); +} + void Wizard::InstallationPage::installationFinished() { QMessageBox msgBox; diff --git a/apps/wizard/installationpage.hpp b/apps/wizard/installationpage.hpp index 97b1fa8bf7..49c92a5f31 100644 --- a/apps/wizard/installationpage.hpp +++ b/apps/wizard/installationpage.hpp @@ -6,6 +6,7 @@ #include "unshield/unshieldworker.hpp" #include "ui_installationpage.h" #include "inisettings.hpp" +#include class QThread; @@ -19,7 +20,7 @@ namespace Wizard { Q_OBJECT public: - InstallationPage(QWidget *parent); + InstallationPage(QWidget *parent, Config::GameSettings &gameSettings); ~InstallationPage() override; int nextId() const override; @@ -34,8 +35,11 @@ namespace Wizard void startInstallation(); + Config::GameSettings &mGameSettings; + private slots: void showFileDialog(Wizard::Component component); + void showOldVersionDialog(); void installationFinished(); void installationError(const QString &text, const QString &details); diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index 7987d9b08d..268aaf15af 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -325,7 +325,7 @@ void Wizard::MainWizard::setupPages() setPage(Page_InstallationTarget, new InstallationTargetPage(this, mCfgMgr)); setPage(Page_ComponentSelection, new ComponentSelectionPage(this)); #ifdef OPENMW_USE_UNSHIELD - setPage(Page_Installation, new InstallationPage(this)); + setPage(Page_Installation, new InstallationPage(this, mGameSettings)); #endif setPage(Page_Import, new ImportPage(this)); setPage(Page_Conclusion, new ConclusionPage(this)); diff --git a/apps/wizard/unshield/unshieldworker.cpp b/apps/wizard/unshield/unshieldworker.cpp index 14a34e8779..3b68f87cc1 100644 --- a/apps/wizard/unshield/unshieldworker.cpp +++ b/apps/wizard/unshield/unshieldworker.cpp @@ -12,8 +12,9 @@ #include #include -Wizard::UnshieldWorker::UnshieldWorker(QObject *parent) : +Wizard::UnshieldWorker::UnshieldWorker(qint64 expectedMorrowindBsaSize, QObject *parent) : QObject(parent), + mExpectedMorrowindBsaSize(expectedMorrowindBsaSize), mIniSettings() { unshield_set_log_level(0); @@ -159,6 +160,11 @@ void Wizard::UnshieldWorker::setIniCodec(QTextCodec *codec) mIniCodec = codec; } +void Wizard::UnshieldWorker::wakeAll() +{ + mWait.wakeAll(); +} + bool Wizard::UnshieldWorker::setupSettings() { // Create Morrowind.ini settings map @@ -478,6 +484,18 @@ bool Wizard::UnshieldWorker::setupComponent(Component component) // Check if we have correct archive, other archives have Morrowind.bsa too if (tribunalFound == bloodmoonFound) { + qint64 actualFileSize = getMorrowindBsaFileSize(file); + if (actualFileSize != mExpectedMorrowindBsaSize) + { + QReadLocker readLock(&mLock); + emit requestOldVersionDialog(); + mWait.wait(&mLock); + if (mStopped) + { + qDebug() << "We are asked to stop !!"; + break; + } + } cabFile = file; found = true; // We have a GoTY disk or a Morrowind-only disk } @@ -492,6 +510,11 @@ bool Wizard::UnshieldWorker::setupComponent(Component component) } + if (cabFile.isEmpty()) + { + break; + } + if (!found) { emit textChanged(tr("Failed to find a valid archive containing %1.bsa! Retrying.").arg(name)); @@ -939,3 +962,42 @@ bool Wizard::UnshieldWorker::findInCab(const QString &fileName, const QString &c unshield_close(unshield); return false; } + +size_t Wizard::UnshieldWorker::getMorrowindBsaFileSize(const QString &cabFile) +{ + QString fileName = QString("Morrowind.bsa"); + QByteArray array(cabFile.toUtf8()); + + Unshield *unshield; + unshield = unshield_open(array.constData()); + + if (!unshield) + { + emit error(tr("Failed to open InstallShield Cabinet File."), tr("Opening %1 failed.").arg(cabFile)); + unshield_close(unshield); + return false; + } + + for (int i = 0; i < unshield_file_group_count(unshield); ++i) + { + UnshieldFileGroup *group = unshield_file_group_get(unshield, i); + + for (size_t j = group->first_file; j <= group->last_file; ++j) + { + + if (unshield_file_is_valid(unshield, j)) + { + QString current(QString::fromUtf8(unshield_file_name(unshield, j))); + if (current.toLower() == fileName.toLower()) + { + size_t fileSize = unshield_file_size(unshield, j); + unshield_close(unshield); + return fileSize; // File is found! + } + } + } + } + + unshield_close(unshield); + return 0; +} diff --git a/apps/wizard/unshield/unshieldworker.hpp b/apps/wizard/unshield/unshieldworker.hpp index 13f4a1168c..483264e990 100644 --- a/apps/wizard/unshield/unshieldworker.hpp +++ b/apps/wizard/unshield/unshieldworker.hpp @@ -12,6 +12,7 @@ #include "../inisettings.hpp" +#include namespace Wizard { @@ -26,7 +27,7 @@ namespace Wizard Q_OBJECT public: - UnshieldWorker(QObject *parent = nullptr); + UnshieldWorker(qint64 expectedMorrowindBsaSize, QObject *parent = nullptr); ~UnshieldWorker() override; void stopWorker(); @@ -38,6 +39,8 @@ namespace Wizard void setPath(const QString &path); void setIniPath(const QString &path); + void wakeAll(); + QString getPath(); QString getIniPath(); @@ -45,8 +48,9 @@ namespace Wizard bool setupSettings(); - private: + size_t getMorrowindBsaFileSize(const QString &cabFile); + private: bool writeSettings(); bool getInstallComponent(Component component); @@ -95,6 +99,8 @@ namespace Wizard bool mStopped; + qint64 mExpectedMorrowindBsaSize; + QString mPath; QString mIniPath; QString mDiskPath; @@ -113,6 +119,7 @@ namespace Wizard signals: void finished(); void requestFileDialog(Wizard::Component component); + void requestOldVersionDialog(); void textChanged(const QString &text);