diff --git a/forms/loadingscreen.ui b/forms/loadingscreen.ui index d6f52430..4ed06b9f 100644 --- a/forms/loadingscreen.ui +++ b/forms/loadingscreen.ui @@ -3,7 +3,7 @@ LoadingScreen - Qt::ApplicationModal + Qt::WindowModality::ApplicationModal @@ -17,7 +17,7 @@ BusyCursor - Qt::NoContextMenu + Qt::ContextMenuPolicy::NoContextMenu Form @@ -35,7 +35,7 @@ porymap - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter @@ -50,14 +50,14 @@ Version X.x.x - Qt::AlignCenter + Qt::AlignmentFlag::AlignCenter - Qt::Vertical + Qt::Orientation::Vertical @@ -70,16 +70,16 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised - Qt::Horizontal + Qt::Orientation::Horizontal @@ -105,7 +105,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -121,7 +121,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -134,23 +134,16 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Plain + QFrame::Shadow::Plain - - - - Loading..... - - - - TextLabel + Loading.... diff --git a/include/core/parseutil.h b/include/core/parseutil.h index aae86a88..09cc1ecb 100644 --- a/include/core/parseutil.h +++ b/include/core/parseutil.h @@ -44,6 +44,7 @@ class ParseUtil public: ParseUtil(); void setRoot(const QString &dir) { this->root = dir; } + void setUpdatesSplashScreen(bool updates) { this->updatesSplashScreen = updates; } static QString readTextFile(const QString &path, QString *error = nullptr); bool cacheFile(const QString &path, QString *error = nullptr); void clearFileCache() { this->fileCache.clear(); } @@ -105,6 +106,8 @@ private: QHash globalDefineValues; QHash globalDefineExpressions; + bool updatesSplashScreen = false; + int evaluateDefine(const QString &identifier, bool *ok = nullptr); int evaluateExpression(const QString &expression); QList tokenizeExpression(QString expression); @@ -114,6 +117,7 @@ private: void recordErrors(const QStringList &errors); void logRecordedErrors(); QString createErrorMessage(const QString &message, const QString &expression); + void updateSplashScreen(QString path); struct ParsedDefines { QHash expressions; // Map of all define names encountered to their expressions diff --git a/include/ui/loadingscreen.h b/include/ui/loadingscreen.h index df55b01c..ff88e87c 100644 --- a/include/ui/loadingscreen.h +++ b/include/ui/loadingscreen.h @@ -18,8 +18,10 @@ public: explicit PorymapLoadingScreen(QWidget *parent = nullptr); ~PorymapLoadingScreen(); - void setPixmap(QPixmap pixmap); - void showMessage(QString text); + void setPixmap(const QPixmap &pixmap); + void showMessage(const QString &text); + void showMessage(const QString &prefix, const QString &text); + void showLoadingMessage(const QString &text); void start(); void stop (); diff --git a/src/core/parseutil.cpp b/src/core/parseutil.cpp index cba8c223..80252c13 100644 --- a/src/core/parseutil.cpp +++ b/src/core/parseutil.cpp @@ -56,9 +56,17 @@ QString ParseUtil::createErrorMessage(const QString &message, const QString &exp return QString("%1:%2:%3: %4").arg(this->file).arg(lineNum).arg(colNum).arg(message); } +void ParseUtil::updateSplashScreen(QString path) { + if (!this->updatesSplashScreen) + return; + + if (path.startsWith(this->root)) { + path.remove(0, this->root.length()); + } + porysplash->showLoadingMessage(path); +} + QString ParseUtil::readTextFile(const QString &path, QString *error) { - // splash screen message - porysplash->showMessage(path); QFile file(path); if (!file.open(QIODevice::ReadOnly)) { if (error) *error = file.errorString(); @@ -80,6 +88,8 @@ QString ParseUtil::readTextFile(const QString &path, QString *error) { // Note that this doesn't insert any parsed files into the file cache, and we don't // want it to (we read a lot of files only once, storing them all is a waste of memory). QString ParseUtil::loadTextFile(const QString &path, QString *error) { + updateSplashScreen(path); + auto it = this->fileCache.constFind(path); if (it != this->fileCache.constEnd()) { // Load text file from cache @@ -89,6 +99,8 @@ QString ParseUtil::loadTextFile(const QString &path, QString *error) { } bool ParseUtil::cacheFile(const QString &path, QString *error) { + updateSplashScreen(path); + this->fileCache.insert(path, readTextFile(pathWithRoot(path), error)); return !error || error->isEmpty(); } @@ -732,6 +744,8 @@ QStringList ParseUtil::getLabelValues(const QList &list, const QStr } bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error) { + updateSplashScreen(filepath); + QFile file(pathWithRoot(filepath)); if (!file.open(QIODevice::ReadOnly)) { if (error) *error = file.errorString(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3fc7d4bd..e422cfc8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -657,13 +657,15 @@ bool MainWindow::openProject(QString dir, bool initial) { this->statusBar()->showMessage(openMessage); logInfo(openMessage); + porysplash->start(); + + porysplash->showLoadingMessage("config"); userConfig.projectDir = dir; userConfig.load(); projectConfig.projectDir = dir; projectConfig.load(); - porysplash->start(); - + porysplash->showLoadingMessage("custom scripts"); Scripting::init(this); // Create the project @@ -681,6 +683,7 @@ bool MainWindow::openProject(QString dir, bool initial) { this->editor->setProject(project); // Make sure project looks reasonable before attempting to load it + porysplash->showMessage("Verifying project"); if (!checkProjectSanity()) { delete this->editor->project; porysplash->stop(); @@ -719,6 +722,7 @@ bool MainWindow::openProject(QString dir, bool initial) { } bool MainWindow::loadProjectData() { + porysplash->showLoadingMessage("project"); bool success = editor->project->load(); Scripting::populateGlobalObject(this); return success; @@ -745,6 +749,12 @@ bool MainWindow::checkProjectSanity() { } void MainWindow::showProjectOpenFailure() { + if (!this->isVisible()){ + // The main window is not visible during the initial project open; the splash screen is busy providing visual feedback. + // If project opening fails we can immediately display the empty main window (which we need anyway to parent messages to). + restoreWindowState(); + show(); + } RecentErrorMessage::show(QStringLiteral("There was an error opening the project."), this); } @@ -766,6 +776,8 @@ bool MainWindow::isProjectOpen() { } bool MainWindow::setInitialMap() { + porysplash->showMessage("Opening initial map"); + const QString recent = userConfig.recentMapOrLayout; if (editor->project->mapNames.contains(recent)) { // User recently had a map open that still exists. @@ -1184,6 +1196,8 @@ void MainWindow::onLayoutSelectorEditingFinished() { // Update the UI using information we've read from the user's project files. bool MainWindow::setProjectUI() { + porysplash->showLoadingMessage("project UI"); + Project *project = editor->project; this->mapHeaderForm->setProject(project); diff --git a/src/project.cpp b/src/project.cpp index 978f94ff..0e845048 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -76,6 +76,7 @@ bool Project::sanityCheck() { } bool Project::load() { + this->parser.setUpdatesSplashScreen(true); resetFileCache(); this->disabledSettingsNames.clear(); bool success = readGlobalConstants() @@ -116,6 +117,7 @@ bool Project::load() { initNewMapSettings(); applyParsedLimits(); } + this->parser.setUpdatesSplashScreen(false); return success; } diff --git a/src/ui/loadingscreen.cpp b/src/ui/loadingscreen.cpp index 9b60cf92..18642afb 100644 --- a/src/ui/loadingscreen.cpp +++ b/src/ui/loadingscreen.cpp @@ -43,18 +43,37 @@ void PorymapLoadingScreen::stop () { this->hide(); } -void PorymapLoadingScreen::setPixmap(QPixmap pixmap) { +void PorymapLoadingScreen::setPixmap(const QPixmap &pixmap) { if (!this->isVisible()) return; this->ui->labelPixmap->setPixmap(pixmap); } -void PorymapLoadingScreen::showMessage(QString text) { +// Displays the message 'prefixtext...'. The 'text' portion may be elided if it's too long. +void PorymapLoadingScreen::showMessage(const QString &prefix, const QString &text) { if (!this->isVisible()) return; - this->ui->labelText->setText(text.mid(text.lastIndexOf("/") + 1)); + + // Limit text (excluding prefix) to avoid increasing the splash screen's width. + static const QFontMetrics fontMetrics = this->ui->labelText->fontMetrics(); + static const int maxWidth = this->ui->labelText->width() + 1; + int prefixWidth = fontMetrics.horizontalAdvance(prefix); + QString message = fontMetrics.elidedText(text + QStringLiteral("..."), Qt::ElideLeft, qMax(maxWidth - prefixWidth, 0)); + message.prepend(prefix); + + this->ui->labelText->setText(message); QApplication::processEvents(); } +// Displays the message 'text...' +void PorymapLoadingScreen::showMessage(const QString &text) { + showMessage("", text); +} + +// Displays the message 'Loading text...' +void PorymapLoadingScreen::showLoadingMessage(const QString &text) { + showMessage(QStringLiteral("Loading "), text); +} + void PorymapLoadingScreen::updateFrame() { this->frame = (this->frame + 1) % this->splashImage.frameCount(); this->setPixmap(QPixmap::fromImage(this->splashImage.frame(this->frame)));