refactor: Clean up setup file reader

Previously we already switch to loading the bootstrap file only from the
local file (ec42553910).
This removes the remaining parts of loading the bootstrap file from a
remote location.
This also updates the UI in case of parsing errors of the bootstrap.json.
This commit is contained in:
Lars Toenning
2024-02-04 16:13:30 +01:00
parent 8704d463b8
commit 389431ccef
22 changed files with 106 additions and 1003 deletions

View File

@@ -377,12 +377,6 @@ namespace BlackGui::Components
{
this->initMultiSimulatorCache(&m_modelCaches, file);
}
else if (file.contains(CSwiftDirectories::bootstrapFileName()))
{
CData<TGlobalSetup> setup { this }; //!< data cache setup
const CGlobalSetup s = CGlobalSetup::fromJsonFile(file, true);
setup.set(s);
}
}
// allow the cache files to be generated before we will override them

View File

@@ -37,11 +37,6 @@ namespace BlackGui::Components
ui->comp_CopyConfiguration->setNameFilterDisables(disable);
}
void CCopyConfigurationDialog::setWithBootstrapFile(bool withBootstrapFile)
{
ui->comp_CopyConfiguration->setWithBootstrapFile(withBootstrapFile);
}
bool CCopyConfigurationDialog::event(QEvent *event)
{
if (CGuiApplication::triggerShowHelp(this, event)) { return true; }

View File

@@ -41,9 +41,6 @@ namespace BlackGui::Components
//! \copydoc QFileSystemModel::setNameFilterDisables
void setNameFilterDisables(bool disable);
//! \copydoc CCopyConfigurationComponent::setWithBootstrapFile
void setWithBootstrapFile(bool withBootstrapFile);
protected:
//! \copydoc QObject::event
virtual bool event(QEvent *event) override;

View File

@@ -5,16 +5,11 @@
#include "blackgui/components/copymodelsfromotherswiftversionsdialog.h"
#include "ui_setuploadingdialog.h"
#include "blackgui/guiapplication.h"
#include "blackcore/data/globalsetup.h"
#include "blackcore/setupreader.h"
#include "blackmisc/swiftdirectories.h"
#include "blackmisc/directoryutils.h"
#include "blackmisc/network/urllist.h"
#include <QPushButton>
#include <QDesktopServices>
#include <QTimer>
#include <QPointer>
using namespace BlackMisc;
using namespace BlackMisc::Network;
@@ -27,30 +22,15 @@ namespace BlackGui::Components
ui(new Ui::CSetupLoadingDialog)
{
Q_ASSERT_X(sApp, Q_FUNC_INFO, "Need sApp");
if (this->hasSetupReader())
{
// reset if it was temporarily ignored
sApp->getSetupReader()->setIgnoreCmdLineBootstrapUrl(false);
connect(sApp, &CGuiApplication::setupHandlingCompleted, this, &CSetupLoadingDialog::onSetupHandlingCompleted);
}
ui->setupUi(this);
connect(ui->pb_IgnoreExplicitBootstrapUrl, &QPushButton::clicked, this, &CSetupLoadingDialog::tryAgainWithoutBootstrapUrl);
connect(ui->pb_LoadFromDisk, &QPushButton::clicked, this, &CSetupLoadingDialog::prefillSetupCache);
connect(ui->pb_Help, &QPushButton::clicked, this, &CSetupLoadingDialog::openHelpPage);
connect(ui->pb_CopyFromSwift, &QPushButton::clicked, this, &CSetupLoadingDialog::copyFromOtherSwiftVersions);
connect(ui->pb_OpemDirectory, &QPushButton::clicked, this, &CSetupLoadingDialog::openDirectory);
connect(ui->pb_TryToFix, &QPushButton::clicked, this, &CSetupLoadingDialog::tryToFix);
QPushButton *retry = ui->bb_Dialog->button(QDialogButtonBox::Retry);
retry->setDefault(true);
const QString bootstrapPath = CSwiftDirectories::bootstrapResourceFilePath();
ui->lbl_ownBootstrap->setText("Your boostrap.json file is available at <a href=" + bootstrapPath + ">" + bootstrapPath + "</>");
this->displaySetupCacheInfo();
this->displayCmdBoostrapUrl();
this->displayGlobalSetup();
this->displayOtherVersionsInfo();
ui->comp_Messages->hideFilterBar(); // saves space, we only expect aview messages
// hide unnecessary details
ui->comp_Messages->hideFilterBar();
ui->comp_Messages->showDetails(false);
}
CSetupLoadingDialog::CSetupLoadingDialog(const CStatusMessageList &msgs, QWidget *parent) : CSetupLoadingDialog(parent)
{
@@ -59,124 +39,4 @@ namespace BlackGui::Components
CSetupLoadingDialog::~CSetupLoadingDialog()
{}
bool CSetupLoadingDialog::hasCachedSetup() const
{
return this->hasSetupReader() && sApp->getSetupReader()->hasCachedSetup();
}
bool CSetupLoadingDialog::hasSetupReader() const
{
return sApp && sApp->hasSetupReader();
}
void CSetupLoadingDialog::displayCmdBoostrapUrl()
{
if (!sApp->hasSetupReader()) { return; }
ui->le_CmdLine->setText(sApp->cmdLineArgumentsAsString());
ui->le_BootstrapMode->setText(sApp->getSetupReader()->getBootstrapModeAsString());
const QString bsUrl = sApp->getSetupReader()->getCmdLineBootstrapUrl();
ui->pb_IgnoreExplicitBootstrapUrl->setVisible(!bsUrl.isEmpty());
ui->le_BootstrapUrl->setText(bsUrl);
}
void CSetupLoadingDialog::displayGlobalSetup()
{
const QString gs = sApp->getGlobalSetup().convertToQString("\n", true);
Q_UNUSED(gs)
// ui->comp_Messages->appendPlainTextToConsole(gs);
//! \fixme create plain text console for this (used to be part of the log component, changed by issue T36)
}
void CSetupLoadingDialog::openHelpPage()
{
const CUrl url = sApp->getGlobalSetup().getHelpPageUrl("bootstrap");
if (url.isEmpty()) { return; }
QDesktopServices::openUrl(url);
}
void CSetupLoadingDialog::tryAgainWithoutBootstrapUrl()
{
if (!sApp->hasSetupReader()) { return; }
sApp->getSetupReader()->setIgnoreCmdLineBootstrapUrl(true);
this->accept();
}
void CSetupLoadingDialog::tryToFix()
{
this->prefillSetupCache();
QPushButton *retry = ui->bb_Dialog->button(QDialogButtonBox::Retry);
if (!retry) { return; }
QPointer<CSetupLoadingDialog> myself(this);
QTimer::singleShot(2000, this, [=] {
if (!sApp || !myself) { return; }
retry->click();
});
}
void CSetupLoadingDialog::prefillSetupCache()
{
if (!sApp || sApp->isShuttingDown()) { return; }
if (!this->hasSetupReader()) { return; }
sApp->getSetupReader()->prefillCacheWithLocalResourceBootstrapFile();
this->displaySetupCacheInfo();
}
void CSetupLoadingDialog::displaySetupCacheInfo()
{
if (this->hasSetupReader())
{
// reset if it was temporarily ignored
const CSetupReader *sr = sApp->getSetupReader();
const QDateTime setupTs = sr->getSetupCacheTimestamp();
static const QDateTime zeroTime = QDateTime::fromMSecsSinceEpoch(0);
ui->le_SetupCache->setText(setupTs.isValid() && setupTs > zeroTime ?
setupTs.toString(Qt::ISODateWithMs) :
"No cache timestamp");
}
else
{
ui->le_SetupCache->setText("No setup reader");
}
const bool hasCachedSetup = this->hasCachedSetup();
ui->pb_LoadFromDisk->setEnabled(!hasCachedSetup);
ui->pb_LoadFromDisk->setToolTip(hasCachedSetup ? "Cached setup already available" : "No cached setup");
ui->pb_TryToFix->setEnabled(!hasCachedSetup);
}
void CSetupLoadingDialog::displayOtherVersionsInfo()
{
const int other = CSwiftDirectories::applicationDataDirectoriesCount() - 1;
ui->le_OtherSwiftVersions->setText(QStringLiteral("There is/are %1 other swift version(s) installed").arg(other));
ui->pb_CopyFromSwift->setEnabled(other > 0);
}
void CSetupLoadingDialog::openDirectory()
{
const QUrl url = QUrl::fromLocalFile(CSwiftDirectories::normalizedApplicationDataDirectory());
QDesktopServices::openUrl(url);
}
void CSetupLoadingDialog::copyFromOtherSwiftVersions()
{
if (!m_copyFromOtherSwiftVersion)
{
CCopyModelsFromOtherSwiftVersionsDialog *d = new CCopyModelsFromOtherSwiftVersionsDialog(this);
d->setModal(true);
m_copyFromOtherSwiftVersion.reset(d);
}
const int r = m_copyFromOtherSwiftVersion->exec();
Q_UNUSED(r);
this->displaySetupCacheInfo();
}
void CSetupLoadingDialog::onSetupHandlingCompleted(bool success)
{
Q_UNUSED(success);
this->displaySetupCacheInfo();
}
} // ns

View File

@@ -15,19 +15,14 @@ namespace Ui
}
namespace BlackGui::Components
{
class CCopyModelsFromOtherSwiftVersionsDialog;
/*!
* Setup dialog, if something goes wrong allows to copy bootstrap file
* Setup dialog, if loading the boostrap file fails
*/
class CSetupLoadingDialog : public QDialog
{
Q_OBJECT
public:
//! Ctor
explicit CSetupLoadingDialog(QWidget *parent = nullptr);
//! Ctor with messages
CSetupLoadingDialog(const BlackMisc::CStatusMessageList &msgs, QWidget *parent = nullptr);
@@ -36,46 +31,9 @@ namespace BlackGui::Components
private:
QScopedPointer<Ui::CSetupLoadingDialog> ui;
QScopedPointer<CCopyModelsFromOtherSwiftVersionsDialog> m_copyFromOtherSwiftVersion;
//! Cached setup available?
bool hasCachedSetup() const;
//! Setup reader?
bool hasSetupReader() const;
//! Display bootstrap URL
void displayCmdBoostrapUrl();
//! Display global setup
void displayGlobalSetup();
//! Open the help page
void openHelpPage();
//! Try again without explicit bootstrap URL
void tryAgainWithoutBootstrapUrl();
//! Try to fix
void tryToFix();
//! Prefill setup cache
void prefillSetupCache();
//! Display the setup cache info
void displaySetupCacheInfo();
//! Display other versions info
void displayOtherVersionsInfo();
//! Open directory
void openDirectory();
//! Copy from other swift versions
void copyFromOtherSwiftVersions();
//! Setup loading has been completed
void onSetupHandlingCompleted(bool success);
//! Ctor
explicit CSetupLoadingDialog(QWidget *parent = nullptr);
};
} // ns

View File

@@ -17,7 +17,7 @@
</size>
</property>
<property name="windowTitle">
<string>Loading the setup (&quot;bootstrap file&quot;)</string>
<string>Loading the setup file failed</string>
</property>
<property name="modal">
<bool>true</bool>
@@ -36,173 +36,29 @@
<number>6</number>
</property>
<item>
<widget class="QGroupBox" name="gb_Details">
<property name="title">
<string>Setup and caches</string>
<widget class="QLabel" name="lbl_Info">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Loading the setup file (bootstrap.json) has failed!&lt;/span&gt; This file is required for &lt;span style=&quot; font-style:italic;&quot;&gt;swift&lt;/span&gt; to work properly. Fix the errors mentioned below and restart swift. You can also replace your bootstrap.json with the latest version available &lt;a href=&quot;https://raw.githubusercontent.com/swift-project/pilotclient/main/resources/share/shared/bootstrap/bootstrap.json&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;from GitHub.&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbl_ownBootstrap">
<property name="text">
<string>TextLabel</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gl_Details" columnstretch="0,0,0,0">
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="2" column="1">
<widget class="QLineEdit" name="le_BootstrapMode">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The mode: 'implicit' means no URL is provided and the value is obtained from an existing setup. 'explicit' means an URL is provided via command line arguments.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbl_BootstrapMode">
<property name="text">
<string>Mode:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="le_SetupCache">
<property name="whatsThis">
<string>Timestamp of the setup cache.</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbl_CmdLine">
<property name="text">
<string>Command:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lbl_BootstrapUrl">
<property name="toolTip">
<string>Where the bootstrap file is located</string>
</property>
<property name="text">
<string>Bootstrap URL:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="le_BootstrapUrl">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The bootstrap URL provided by command line options. This is where the setup data are loaded from.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="le_CmdLine">
<property name="whatsThis">
<string>The command line.</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lbl_SetupCache">
<property name="text">
<string>Setup cache:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lbl_CopyOver">
<property name="text">
<string>Copy over:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="pb_LoadFromDisk">
<property name="whatsThis">
<string>load the cache data from disk, i.e. from the file which came with the installer</string>
</property>
<property name="text">
<string>from disk</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QLabel" name="lbl_Info">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:9pt; font-weight:600;&quot;&gt;Loading the setup (aka &amp;quot;bootstrap file&amp;quot;) has failed!&lt;/span&gt;&lt;span style=&quot; font-size:9pt;&quot;&gt; This file is required for &lt;/span&gt;&lt;span style=&quot; font-size:9pt; font-style:italic;&quot;&gt;swift&lt;/span&gt;&lt;span style=&quot; font-size:9pt;&quot;&gt; to work properly. You can try to load the file again (&amp;quot;Retry&amp;quot;) or give up (&amp;quot;Cancel&amp;quot;). If you have set an explicit bootstrap URL, you can also ignore this URL and use cached setup data (if there are any). If all goes wrong, you can try to load the setup cache from disk.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="pb_IgnoreExplicitBootstrapUrl">
<property name="whatsThis">
<string>ignore the bootstrap URL and try to read from cache</string>
</property>
<property name="text">
<string>ignore</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QPushButton" name="pb_OpemDirectory">
<property name="text">
<string>open dir.</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QPushButton" name="pb_Help">
<property name="text">
<string>help page</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="le_OtherSwiftVersions">
<property name="whatsThis">
<string>Info about other swift versions installed</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="pb_CopyFromSwift">
<property name="whatsThis">
<string>copy cache data from another swift version</string>
</property>
<property name="text">
<string>copy over</string>
</property>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QPushButton" name="pb_TryToFix">
<property name="text">
<string>try to fix</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
@@ -236,7 +92,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Retry</set>
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
@@ -250,18 +106,6 @@
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>le_CmdLine</tabstop>
<tabstop>le_BootstrapMode</tabstop>
<tabstop>le_BootstrapUrl</tabstop>
<tabstop>pb_IgnoreExplicitBootstrapUrl</tabstop>
<tabstop>le_SetupCache</tabstop>
<tabstop>pb_LoadFromDisk</tabstop>
<tabstop>pb_Help</tabstop>
<tabstop>le_OtherSwiftVersions</tabstop>
<tabstop>pb_CopyFromSwift</tabstop>
<tabstop>pb_OpemDirectory</tabstop>
</tabstops>
<resources/>
<connections>
<connection>

View File

@@ -129,7 +129,6 @@ namespace BlackGui
{
CGuiApplication::registerMetadata();
CApplication::init(false); // base class without metadata
if (this->hasSetupReader()) { this->getSetupReader()->setCheckCmdLineBootstrapUrl(false); } // no connect checks on setup reader (handled with interactive setup loading)
CGuiApplication::adjustPalette();
this->setWindowIcon(icon);
this->settingsChanged();
@@ -138,9 +137,6 @@ namespace BlackGui
connect(&m_styleSheetUtility, &CStyleSheetUtility::styleSheetsChanged, this, &CGuiApplication::onStyleSheetsChanged, Qt::QueuedConnection);
connect(this, &CGuiApplication::startUpCompleted, this, &CGuiApplication::superviseWindowMinSizes, Qt::QueuedConnection);
// splash screen
connect(this->getSetupReader(), &CSetupReader::setupLoadingMessages, this, &CGuiApplication::displaySplashMessages, Qt::QueuedConnection);
}
}
@@ -1094,48 +1090,21 @@ namespace BlackGui
m_minHeightChars = heightChars;
}
bool CGuiApplication::interactivelySynchronizeSetup(int timeoutMs)
void CGuiApplication::displaySetupLoadFailure(BlackMisc::CStatusMessageList msgs)
{
bool ok = false;
do
if (msgs.hasErrorMessages())
{
const CStatusMessageList msgs = this->synchronizeSetup(timeoutMs);
if (msgs.hasErrorMessages())
CSetupLoadingDialog dialog(msgs, BlackGui::CGuiApplication::mainApplicationWidget());
if (sGui)
{
CSetupLoadingDialog dialog(msgs, this->mainApplicationWidget());
if (sGui)
{
static const QString style = sGui->getStyleSheetUtility().styles(
{ CStyleSheetUtility::fileNameFonts(),
CStyleSheetUtility::fileNameStandardWidget() });
dialog.setStyleSheet(style);
}
static const QString style = sGui->getStyleSheetUtility().styles(
{ CStyleSheetUtility::fileNameFonts(),
CStyleSheetUtility::fileNameStandardWidget() });
dialog.setStyleSheet(style);
}
const int r = dialog.exec();
if (r == QDialog::Rejected)
{
break; // exit with false state, as file was not loaded
}
else
{
// run loop again and sync again
}
}
else
{
// setup loaded
ok = true;
break;
}
dialog.exec();
}
while (!ok);
return ok;
}
bool CGuiApplication::parseAndSynchronizeSetup(int timeoutMs)
{
if (!this->parseAndStartupCheck()) { return false; }
return this->interactivelySynchronizeSetup(timeoutMs);
}
QDialog::DialogCode CGuiApplication::showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent)

View File

@@ -217,13 +217,8 @@ namespace BlackGui
//! \deprecated kept for experimental tests
void setMinimumSizeInCharacters(int widthChars, int heightChars);
//! Wait for setup, in case it fails display a dialog how to continue
bool interactivelySynchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
//! Combined function
//! \see parseAndStartupCheck
//! \see interactivelySynchronizeSetup
virtual bool parseAndSynchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs()) override;
//! \copydoc BlackCore::CApplication::displaySetupLoadFailure
void displaySetupLoadFailure(BlackMisc::CStatusMessageList msgs) override;
//! Show close dialog
//! \remark will modify CApplication::saveSettingsOnShutdown