From a626e52bf32cba3900a209e190d02992491e6ccd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 8 Jun 2018 17:36:29 -0400 Subject: [PATCH 02/14] [libcalamares] Introduce more descriptive type name --- src/libcalamares/Settings.cpp | 2 +- src/libcalamares/Settings.h | 6 ++++-- src/libcalamaresui/modulesystem/ModuleManager.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 732afa8d8..087822623 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -175,7 +175,7 @@ Settings::modulesSearchPaths() const } -QList > +Settings::InstanceDescriptionList Settings::customModuleInstances() const { return m_customModuleInstances; diff --git a/src/libcalamares/Settings.h b/src/libcalamares/Settings.h index 42720b986..35527243a 100644 --- a/src/libcalamares/Settings.h +++ b/src/libcalamares/Settings.h @@ -43,7 +43,9 @@ public: QStringList modulesSearchPaths() const; - QList< QMap< QString, QString > > customModuleInstances() const; + using InstanceDescription = QMap< QString, QString >; + using InstanceDescriptionList = QList< InstanceDescription >; + InstanceDescriptionList customModuleInstances() const; QList< QPair< ModuleAction, QStringList > > modulesSequence() const; @@ -60,7 +62,7 @@ private: QStringList m_modulesSearchPaths; - QList< QMap< QString, QString > > m_customModuleInstances; + InstanceDescriptionList m_customModuleInstances; QList< QPair< ModuleAction, QStringList > > m_modulesSequence; QString m_brandingComponentName; diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 83273e924..df77c5602 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -159,7 +159,7 @@ ModuleManager::loadModules() { QTimer::singleShot( 0, this, [ this ]() { - QList< QMap< QString, QString > > customInstances = + Settings::InstanceDescriptionList customInstances = Settings::instance()->customModuleInstances(); const auto modulesSequence = Settings::instance()->modulesSequence(); From dccf6f16f5cec7d7ed94c4ffa028687c58cbfea5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 8 Jun 2018 17:56:23 -0400 Subject: [PATCH 03/14] [libcalamaresui] Lambdas are fun, but not always the solution --- .../modulesystem/ModuleManager.cpp | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index df77c5602..317ca884f 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -154,6 +154,26 @@ ModuleManager::moduleInstance( const QString& instanceKey ) } +/** + * @brief Search a list of instance descriptions for one matching @p module and @p id + * + * @return -1 on failure, otherwise index of the instance that matches. + */ +static int findCustomInstance( const Settings::InstanceDescriptionList& customInstances, + const QString& module, + const QString& id ) +{ + for ( int i = 0; i < customInstances.count(); ++i ) + { + const auto& thisInstance = customInstances[ i ]; + if ( thisInstance.value( "module" ) == module && + thisInstance.value( "id" ) == id ) + return i; + } + return -1; +} + + void ModuleManager::loadModules() { @@ -196,25 +216,11 @@ ModuleManager::loadModules() return; } - auto findCustomInstance = - [ customInstances ]( const QString& module, - const QString& id) -> int - { - for ( int i = 0; i < customInstances.count(); ++i ) - { - auto thisInstance = customInstances[ i ]; - if ( thisInstance.value( "module" ) == module && - thisInstance.value( "id" ) == id ) - return i; - } - return -1; - }; - if ( moduleName != instanceId ) //means this is a custom instance { - if ( findCustomInstance( moduleName, instanceId ) > -1 ) + if ( int found = findCustomInstance( customInstances, moduleName, instanceId ) > -1 ) { - configFileName = customInstances[ findCustomInstance( moduleName, instanceId ) ].value( "config" ); + configFileName = customInstances[ found ].value( "config" ); } else //ought to be a custom instance, but cannot find instance entry { From 1999e4e5c2839628a88ce4816b711af18e171a8c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 8 Jun 2018 18:14:51 -0400 Subject: [PATCH 04/14] [libcalamaresui] Error out consistently when module loading fails - Some module-loading failures were ignored and produce only a warning, instead of erroring out. --- .../modulesystem/ModuleManager.cpp | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 317ca884f..48a2c1476 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -177,6 +177,8 @@ static int findCustomInstance( const Settings::InstanceDescriptionList& customIn void ModuleManager::loadModules() { + static const char GOODBYE[] = "\nCalamares will now quit."; + QTimer::singleShot( 0, this, [ this ]() { Settings::InstanceDescriptionList customInstances = @@ -197,8 +199,8 @@ ModuleManager::loadModules() if ( moduleEntrySplit.length() < 1 || moduleEntrySplit.length() > 2 ) { - cError() << "Wrong module entry format for module" << moduleEntry << '.'; - cError() << "Calamares will now quit."; + cError() << "Wrong module entry format for module" << moduleEntry << '.' + << GOODBYE; qApp->exit( 1 ); return; } @@ -210,8 +212,8 @@ ModuleManager::loadModules() m_availableDescriptorsByModuleName.value( moduleName ).isEmpty() ) { cError() << "Module" << moduleName << "not found in module search paths." - << Logger::DebugList( m_paths ); - cError() << "Calamares will now quit."; + << Logger::DebugList( m_paths ) + << GOODBYE; qApp->exit( 1 ); return; } @@ -224,8 +226,8 @@ ModuleManager::loadModules() } else //ought to be a custom instance, but cannot find instance entry { - cError() << "Custom instance" << moduleEntry << "not found in custom instances section."; - cError() << "Calamares will now quit."; + cError() << "Custom instance" << moduleEntry << "not found in custom instances section." + << GOODBYE; qApp->exit( 1 ); return; } @@ -248,7 +250,7 @@ ModuleManager::loadModules() if ( thisModule && !thisModule->isLoaded() ) { cError() << "Module" << instanceKey << "exists but not loaded." - << "\nCalamares will now quit."; + << GOODBYE; qApp->exit( 1 ); return; } @@ -266,18 +268,18 @@ ModuleManager::loadModules() m_moduleDirectoriesByModuleName.value( moduleName ) ); if ( !thisModule ) { - cWarning() << "Module" << instanceKey << "cannot be created from descriptor."; - Q_ASSERT( thisModule ); - continue; + cError() << "Module" << instanceKey << "cannot be created from descriptor" << configFileName + << GOODBYE; + qApp->exit( 1 ); } // If it's a ViewModule, it also appends the ViewStep to the ViewManager. thisModule->loadSelf(); m_loadedModulesByInstanceKey.insert( instanceKey, thisModule ); if ( !thisModule->isLoaded() ) { - cWarning() << "Module" << moduleName << "loading FAILED"; - Q_ASSERT( thisModule->isLoaded() ); - continue; + cError() << "Module" << instanceKey << "loading FAILED" + << GOODBYE; + qApp->exit( 1 ); } } From a40c36ef493b6a5596515d9d288cc4c91e270834 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Jun 2018 05:59:56 -0400 Subject: [PATCH 05/14] [libcalamaresui] Report on failed module loading - Collect the failed modules, instead of bailing out on the first one (this also prevents crashes caused by quit() called from a timer). - Introduce a slot to report on failed module loading (no UI yet). --- src/calamares/CalamaresApplication.cpp | 8 ++++++ src/calamares/CalamaresApplication.h | 1 + .../modulesystem/ModuleManager.cpp | 28 +++++++++++-------- .../modulesystem/ModuleManager.h | 3 +- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index 2bb0af8df..2f61749b0 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -335,6 +335,8 @@ CalamaresApplication::initView() connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded, this, &CalamaresApplication::initViewSteps ); + connect( m_moduleManager, &Calamares::ModuleManager::modulesFailed, + this, &CalamaresApplication::initFailed ); m_moduleManager->loadModules(); @@ -356,6 +358,12 @@ CalamaresApplication::initViewSteps() cDebug() << "STARTUP: Window now visible and ProgressTreeView populated"; } +void +CalamaresApplication::initFailed(const QStringList& l) +{ + cError() << "STARTUP: failed modules are" << l; + m_mainwindow->show(); +} void CalamaresApplication::initJobQueue() diff --git a/src/calamares/CalamaresApplication.h b/src/calamares/CalamaresApplication.h index 3cfd4f79f..a588afcee 100644 --- a/src/calamares/CalamaresApplication.h +++ b/src/calamares/CalamaresApplication.h @@ -70,6 +70,7 @@ public: private slots: void initView(); void initViewSteps(); + void initFailed( const QStringList& l ); private: void initQmlPath(); diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 48a2c1476..57a82994f 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -181,6 +181,7 @@ ModuleManager::loadModules() QTimer::singleShot( 0, this, [ this ]() { + QStringList failedModules; Settings::InstanceDescriptionList customInstances = Settings::instance()->customModuleInstances(); @@ -201,8 +202,8 @@ ModuleManager::loadModules() { cError() << "Wrong module entry format for module" << moduleEntry << '.' << GOODBYE; - qApp->exit( 1 ); - return; + failedModules.append( moduleEntry ); + continue; } moduleName = moduleEntrySplit.first(); instanceId = moduleEntrySplit.last(); @@ -214,8 +215,8 @@ ModuleManager::loadModules() cError() << "Module" << moduleName << "not found in module search paths." << Logger::DebugList( m_paths ) << GOODBYE; - qApp->exit( 1 ); - return; + failedModules.append( moduleName ); + continue; } if ( moduleName != instanceId ) //means this is a custom instance @@ -228,8 +229,8 @@ ModuleManager::loadModules() { cError() << "Custom instance" << moduleEntry << "not found in custom instances section." << GOODBYE; - qApp->exit( 1 ); - return; + failedModules.append( moduleEntry ); + continue; } } @@ -251,8 +252,8 @@ ModuleManager::loadModules() { cError() << "Module" << instanceKey << "exists but not loaded." << GOODBYE; - qApp->exit( 1 ); - return; + failedModules.append( instanceKey ); + continue; } if ( thisModule && thisModule->isLoaded() ) @@ -270,7 +271,8 @@ ModuleManager::loadModules() { cError() << "Module" << instanceKey << "cannot be created from descriptor" << configFileName << GOODBYE; - qApp->exit( 1 ); + failedModules.append( instanceKey ); + continue; } // If it's a ViewModule, it also appends the ViewStep to the ViewManager. thisModule->loadSelf(); @@ -279,7 +281,8 @@ ModuleManager::loadModules() { cError() << "Module" << instanceKey << "loading FAILED" << GOODBYE; - qApp->exit( 1 ); + failedModules.append( instanceKey ); + continue; } } @@ -300,7 +303,10 @@ ModuleManager::loadModules() } } } - emit modulesLoaded(); + if ( !failedModules.isEmpty() ) + emit modulesFailed( failedModules ); + else + emit modulesLoaded(); } ); } diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index ed7700c40..e1763d93c 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -82,7 +82,8 @@ public: signals: void initDone(); - void modulesLoaded(); + void modulesLoaded(); /// All of the modules were loaded successfully + void modulesFailed( QStringList ); /// .. or not private slots: void doInit(); From 49622a6a3079172b8ba86f9be0e4f3f6d4819ba2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Jun 2018 06:28:31 -0400 Subject: [PATCH 06/14] Tests: expand test-application test_conf - Add -v (verbose) and -b (load via bytearray) - Verbose prints the keys read from the file, - Bytes reads via an indirection through QByteArray, like Settings does --- src/modules/CMakeLists.txt | 2 +- src/modules/test_conf.cpp | 55 +++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 7f93c555a..514d6b4f6 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -6,7 +6,7 @@ set( LIST_SKIPPED_MODULES "" ) if( BUILD_TESTING ) add_executable( test_conf test_conf.cpp ) - target_link_libraries( test_conf ${YAMLCPP_LIBRARY} ) + target_link_libraries( test_conf ${YAMLCPP_LIBRARY} Qt5::Core ) target_include_directories( test_conf PUBLIC ${YAMLCPP_INCLUDE_DIR} ) endif() diff --git a/src/modules/test_conf.cpp b/src/modules/test_conf.cpp index 7ef557a3c..082f626c8 100644 --- a/src/modules/test_conf.cpp +++ b/src/modules/test_conf.cpp @@ -21,43 +21,86 @@ * shipped with each module for correctness -- well, for parseability. */ +#include +#include + #include + #include +#include +#include + using std::cerr; +static const char usage[] = "Usage: test_conf [-v] [-b] ...\n"; + int main(int argc, char** argv) { - if (argc != 2) + bool verbose = false; + bool bytes = false; + + int opt; + while ((opt = getopt(argc, argv, "vb")) != -1) { + switch (opt) { + case 'v': + verbose = true; + break; + case 'b': + bytes = true; + break; + default: /* '?' */ + cerr << usage; + return 1; + } + } + + if ( optind >= argc ) { - cerr << "Usage: test_conf \n"; + cerr << usage; return 1; } + const char* filename = argv[optind]; try { - YAML::Node doc = YAML::LoadFile( argv[1] ); + YAML::Node doc; + if ( bytes ) + { + QFile f( filename ); + if ( f.open( QFile::ReadOnly | QFile::Text ) ) + doc = YAML::Load( f.readAll().constData() ); + } + else + doc = YAML::LoadFile( filename ); if ( doc.IsNull() ) { // Special case: empty config files are valid, // but aren't a map. For the example configs, // this is still an error. - cerr << "WARNING:" << argv[1] << '\n'; + cerr << "WARNING:" << filename << '\n'; cerr << "WARNING: empty YAML\n"; return 1; } if ( !doc.IsMap() ) { - cerr << "WARNING:" << argv[1] << '\n'; + cerr << "WARNING:" << filename << '\n'; cerr << "WARNING: not-a-YAML-map\n"; return 1; } + + if ( verbose ) + { + cerr << "Keys:\n"; + for ( auto i = doc.begin(); i != doc.end(); ++i ) + cerr << i->first.as() << '\n'; + } } catch ( YAML::Exception& e ) { - cerr << "WARNING:" << argv[1] << '\n'; + cerr << "WARNING:" << filename << '\n'; cerr << "WARNING: YAML parser error " << e.what() << '\n'; return 1; } From a732ce11bcf60c6c9ac978200d0bab0e0081cd45 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Jun 2018 08:33:47 -0400 Subject: [PATCH 07/14] [libcalamares] Warn more about badly-formed config --- src/libcalamares/Settings.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 087822623..bc645ab39 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -30,6 +30,32 @@ #include +/** Helper function to grab a QString out of the config, and to warn if not present. */ +static QString +requireString( const YAML::Node& config, const char* key ) +{ + if ( config[ key ] ) + return QString::fromStdString( config[ key ].as< std::string >() ); + else + { + cWarning() << "Required settings.conf key" << key << "is missing."; + return QString(); + } +} + +/** Helper function to grab a bool out of the config, and to warn if not present. */ +static bool +requireBool( const YAML::Node& config, const char* key, bool d ) +{ + if ( config[ key ] ) + return config[ key ].as< bool >(); + else + { + cWarning() << "Required settings.conf key" << key << "is missing."; + return d; + } +} + namespace Calamares { @@ -41,7 +67,6 @@ Settings::instance() return s_instance; } - Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent ) @@ -148,11 +173,9 @@ Settings::Settings( const QString& settingsFilePath, } } - m_brandingComponentName = QString::fromStdString( config[ "branding" ] - .as< std::string >() ); - m_promptInstall = config[ "prompt-install" ].as< bool >(); - - m_doChroot = config[ "dont-chroot" ] ? !config[ "dont-chroot" ].as< bool >() : true; + m_brandingComponentName = requireString( config, "branding" ); + m_promptInstall = requireBool( config, "prompt-install", false ); + m_doChroot = requireBool( config, "dont-chroot", true ); } catch ( YAML::Exception& e ) { From 35124c149e493a1659eed73b6b29dc8ad6d9e5e2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Jun 2018 13:35:12 -0400 Subject: [PATCH 08/14] [libcalamaresui] Drop the 'goodbye' message --- .../modulesystem/ModuleManager.cpp | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 57a82994f..194db65a2 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -177,8 +177,6 @@ static int findCustomInstance( const Settings::InstanceDescriptionList& customIn void ModuleManager::loadModules() { - static const char GOODBYE[] = "\nCalamares will now quit."; - QTimer::singleShot( 0, this, [ this ]() { QStringList failedModules; @@ -200,8 +198,7 @@ ModuleManager::loadModules() if ( moduleEntrySplit.length() < 1 || moduleEntrySplit.length() > 2 ) { - cError() << "Wrong module entry format for module" << moduleEntry << '.' - << GOODBYE; + cError() << "Wrong module entry format for module" << moduleEntry; failedModules.append( moduleEntry ); continue; } @@ -213,8 +210,7 @@ ModuleManager::loadModules() m_availableDescriptorsByModuleName.value( moduleName ).isEmpty() ) { cError() << "Module" << moduleName << "not found in module search paths." - << Logger::DebugList( m_paths ) - << GOODBYE; + << Logger::DebugList( m_paths ); failedModules.append( moduleName ); continue; } @@ -227,8 +223,7 @@ ModuleManager::loadModules() } else //ought to be a custom instance, but cannot find instance entry { - cError() << "Custom instance" << moduleEntry << "not found in custom instances section." - << GOODBYE; + cError() << "Custom instance" << moduleEntry << "not found in custom instances section."; failedModules.append( moduleEntry ); continue; } @@ -250,8 +245,7 @@ ModuleManager::loadModules() m_loadedModulesByInstanceKey.value( instanceKey, nullptr ); if ( thisModule && !thisModule->isLoaded() ) { - cError() << "Module" << instanceKey << "exists but not loaded." - << GOODBYE; + cError() << "Module" << instanceKey << "exists but not loaded."; failedModules.append( instanceKey ); continue; } @@ -269,8 +263,7 @@ ModuleManager::loadModules() m_moduleDirectoriesByModuleName.value( moduleName ) ); if ( !thisModule ) { - cError() << "Module" << instanceKey << "cannot be created from descriptor" << configFileName - << GOODBYE; + cError() << "Module" << instanceKey << "cannot be created from descriptor" << configFileName; failedModules.append( instanceKey ); continue; } @@ -279,8 +272,7 @@ ModuleManager::loadModules() m_loadedModulesByInstanceKey.insert( instanceKey, thisModule ); if ( !thisModule->isLoaded() ) { - cError() << "Module" << instanceKey << "loading FAILED" - << GOODBYE; + cError() << "Module" << instanceKey << "loading FAILED."; failedModules.append( instanceKey ); continue; } From 8b406cac9b57a8e5f535087ea743f2e8fde46c79 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 13 Jun 2018 04:37:52 -0400 Subject: [PATCH 09/14] [libcalamaresui] Improve module loading - Add a TODO for allowing modules to come from somewhere other than the module loader (this would allow "internal" modules that are always present) - Warnings are warnings --- src/libcalamaresui/modulesystem/ViewModule.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ViewModule.cpp b/src/libcalamaresui/modulesystem/ViewModule.cpp index 1f940b30b..317d32712 100644 --- a/src/libcalamaresui/modulesystem/ViewModule.cpp +++ b/src/libcalamaresui/modulesystem/ViewModule.cpp @@ -52,27 +52,32 @@ ViewModule::loadSelf() PluginFactory* pf = qobject_cast< PluginFactory* >( m_loader->instance() ); if ( !pf ) { - cDebug() << Q_FUNC_INFO << "No factory:" << m_loader->errorString(); + cWarning() << Q_FUNC_INFO << "No factory:" << m_loader->errorString(); return; } m_viewStep = pf->create< Calamares::ViewStep >(); if ( !m_viewStep ) { - cDebug() << Q_FUNC_INFO << "create() failed" << m_loader->errorString(); + cWarning() << Q_FUNC_INFO << "create() failed" << m_loader->errorString(); return; } -// cDebug() << "ViewModule loading self for instance" << instanceKey() -// << "\nViewModule at address" << this -// << "\nCalamares::PluginFactory at address" << pf -// << "\nViewStep at address" << m_viewStep; + } + + // TODO: allow internal view steps to be created here; they would + // have to be linked into the main application somehow. + // If any method created the view step, use it now. + if ( m_viewStep ) + { m_viewStep->setModuleInstanceKey( instanceKey() ); m_viewStep->setConfigurationMap( m_configurationMap ); ViewManager::instance()->addViewStep( m_viewStep ); m_loaded = true; cDebug() << "ViewModule" << instanceKey() << "loading complete."; } + else + cWarning() << Q_FUNC_INFO << "No view step was created"; } From 3e24c3c58fce63ec223dc317fda8dc9b15e52aae Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 13 Jun 2018 19:31:00 +0200 Subject: [PATCH 10/14] [libcalamaresui] Provide standardised large font --- src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 9 +++++++++ src/libcalamaresui/utils/CalamaresUtilsGui.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index b05d4ea4f..3c59b0f89 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -226,6 +226,15 @@ defaultFont() } +QFont +largeFont() +{ + QFont f; + f.setPointSize( defaultFontSize() + 4 ); + return f; +} + + void setDefaultFontSize( int points ) { diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index c0905d4d0..98a49db61 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -115,6 +115,7 @@ UIDLLEXPORT void setDefaultFontSize( int points ); UIDLLEXPORT int defaultFontSize(); // in points UIDLLEXPORT int defaultFontHeight(); // in pixels, DPI-specific UIDLLEXPORT QFont defaultFont(); +UIDLLEXPORT QFont largeFont(); UIDLLEXPORT QSize defaultIconSize(); /** From 9918dfb95ffc17fcf0885cb036356d76c7d1f201 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 13 Jun 2018 05:11:31 -0400 Subject: [PATCH 11/14] [libcalamaresui] Reporting on failures - Provide information on failed modules - Disallow further progress when configuration is borked --- src/libcalamaresui/CMakeLists.txt | 1 + src/libcalamaresui/ViewManager.cpp | 15 +++ src/libcalamaresui/ViewManager.h | 6 + .../modulesystem/ModuleManager.cpp | 3 + .../viewpages/BlankViewStep.cpp | 113 ++++++++++++++++++ src/libcalamaresui/viewpages/BlankViewStep.h | 70 +++++++++++ 6 files changed, 208 insertions(+) create mode 100644 src/libcalamaresui/viewpages/BlankViewStep.cpp create mode 100644 src/libcalamaresui/viewpages/BlankViewStep.h diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 6bbb285bb..efd0ebb29 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -15,6 +15,7 @@ set( calamaresui_SOURCES utils/qjsonitem.cpp viewpages/AbstractPage.cpp + viewpages/BlankViewStep.cpp viewpages/ViewStep.cpp widgets/ClickableLabel.cpp diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index e597bf6a3..8777f79d7 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -20,6 +20,7 @@ #include "ViewManager.h" #include "utils/Logger.h" +#include "viewpages/BlankViewStep.h" #include "viewpages/ViewStep.h" #include "ExecutionViewStep.h" #include "JobQueue.h" @@ -172,6 +173,20 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail } +void +ViewManager::onInitFailed( const QStringList& modules) +{ + QString title( tr( "Calamares Initialization Failed" ) ); + QString description( tr( "Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. %1 can not be installed." ) ); + QStringList details; + details << QLatin1Literal("
    "); + for( const auto& m : modules ) + details << QLatin1Literal("
  • ") << m << QLatin1Literal("
  • "); + details << QLatin1Literal("
"); + + insertViewStep( 0, new BlankViewStep( title, description.arg( *Calamares::Branding::ShortProductName ), details.join( QString() ) ) ); +} + ViewStepList ViewManager::viewSteps() const { diff --git a/src/libcalamaresui/ViewManager.h b/src/libcalamaresui/ViewManager.h index e4f215f8f..ee199f725 100644 --- a/src/libcalamaresui/ViewManager.h +++ b/src/libcalamaresui/ViewManager.h @@ -117,6 +117,12 @@ public slots: */ void onInstallationFailed( const QString& message, const QString& details ); + /** @brief Replaces the stack with a view step stating that initialization failed. + * + * @param modules a list of failed modules. + */ + void onInitFailed( const QStringList& modules ); + signals: void currentStepChanged(); void enlarge( QSize enlarge ) const; // See ViewStep::enlarge() diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 194db65a2..6361fa20b 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -296,7 +296,10 @@ ModuleManager::loadModules() } } if ( !failedModules.isEmpty() ) + { + ViewManager::instance()->onInitFailed( failedModules ); emit modulesFailed( failedModules ); + } else emit modulesLoaded(); } ); diff --git a/src/libcalamaresui/viewpages/BlankViewStep.cpp b/src/libcalamaresui/viewpages/BlankViewStep.cpp new file mode 100644 index 000000000..093d19d8b --- /dev/null +++ b/src/libcalamaresui/viewpages/BlankViewStep.cpp @@ -0,0 +1,113 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ +#include "BlankViewStep.h" + +#include "utils/CalamaresUtilsGui.h" + +#include +#include +#include + +namespace Calamares +{ + +BlankViewStep::BlankViewStep( const QString& title, const QString& description, const QString& details, QObject* parent) + : Calamares::ViewStep( parent ) + , m_widget( new QWidget() ) +{ + QBoxLayout* layout = new QVBoxLayout(); + + auto* label = new QLabel( title ); + label->setAlignment( Qt::AlignHCenter ); + label->setFont( CalamaresUtils::largeFont() ); + layout->addWidget( label ); + + label = new QLabel( description ); + label->setWordWrap( true ); + layout->addSpacing( 10 ); + layout->addWidget( label ); + + if ( !details.isEmpty() ) + { + label = new QLabel( details ); + layout->addSpacing( 10 ); + layout->addWidget( label ); + } + + layout->addStretch( 10 ); + + m_widget->setLayout( layout ); +} + +BlankViewStep::~BlankViewStep() +{ +} + +QString +BlankViewStep::prettyName() const +{ + return tr( "Blank Page" ); +} + +void +BlankViewStep::back() +{ +} + +void +BlankViewStep::next() +{ +} + +bool +BlankViewStep::isBackEnabled() const +{ + return false; +} + +bool +BlankViewStep::isNextEnabled() const +{ + return false; +} + +bool +BlankViewStep::isAtBeginning() const +{ + return true; +} + +bool +BlankViewStep::isAtEnd() const +{ + return false; +} + +QWidget* +BlankViewStep::widget() +{ + return m_widget; +} + +Calamares::JobList +BlankViewStep::jobs() const +{ + return JobList(); +} + +} // namespace diff --git a/src/libcalamaresui/viewpages/BlankViewStep.h b/src/libcalamaresui/viewpages/BlankViewStep.h new file mode 100644 index 000000000..5e6938143 --- /dev/null +++ b/src/libcalamaresui/viewpages/BlankViewStep.h @@ -0,0 +1,70 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef BLANKVIEWSTEP_H +#define BLANKVIEWSTEP_H + +#include + +#include +#include + +class QWidget; + +namespace Calamares +{ + +/** @brief A "blank" view step, used for error and status reporting + * + * + */ +class BlankViewStep : public Calamares::ViewStep +{ + Q_OBJECT + +public: + explicit BlankViewStep( const QString& title, const QString& description, const QString& details = QString(), QObject* parent = nullptr ); + virtual ~BlankViewStep() override; + + QString prettyName() const override; + + QWidget* widget() override; + + void next() override; + void back() override; + + bool isNextEnabled() const override; + bool isBackEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + + Calamares::JobList jobs() const override; +#if 0 + void onActivate() override; + + + void setConfigurationMap( const QVariantMap& configurationMap ) override; +#endif + +private: + QWidget* m_widget; +}; + +} // namespace +#endif // BLANKVIEWSTEP_H From bb5ac0326d35d8649d4a504e1a049f06449957e8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Jun 2018 02:31:06 -0400 Subject: [PATCH 12/14] [libcalamaresui] Improve layout of "blank" view step --- src/libcalamaresui/viewpages/BlankViewStep.cpp | 11 ++++++++--- src/libcalamaresui/viewpages/BlankViewStep.h | 9 ++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcalamaresui/viewpages/BlankViewStep.cpp b/src/libcalamaresui/viewpages/BlankViewStep.cpp index 093d19d8b..243305c1f 100644 --- a/src/libcalamaresui/viewpages/BlankViewStep.cpp +++ b/src/libcalamaresui/viewpages/BlankViewStep.cpp @@ -32,6 +32,9 @@ BlankViewStep::BlankViewStep( const QString& title, const QString& description, { QBoxLayout* layout = new QVBoxLayout(); + constexpr int const marginWidth = 10; + constexpr int const spacingHeight = 10; + auto* label = new QLabel( title ); label->setAlignment( Qt::AlignHCenter ); label->setFont( CalamaresUtils::largeFont() ); @@ -39,17 +42,19 @@ BlankViewStep::BlankViewStep( const QString& title, const QString& description, label = new QLabel( description ); label->setWordWrap( true ); - layout->addSpacing( 10 ); + label->setMargin( marginWidth ); + layout->addSpacing( spacingHeight ); layout->addWidget( label ); if ( !details.isEmpty() ) { label = new QLabel( details ); - layout->addSpacing( 10 ); + label->setMargin( marginWidth ); + layout->addSpacing( spacingHeight ); layout->addWidget( label ); } - layout->addStretch( 10 ); + layout->addStretch( 1 ); // Push the rest to the top m_widget->setLayout( layout ); } diff --git a/src/libcalamaresui/viewpages/BlankViewStep.h b/src/libcalamaresui/viewpages/BlankViewStep.h index 5e6938143..a3f46d1d5 100644 --- a/src/libcalamaresui/viewpages/BlankViewStep.h +++ b/src/libcalamaresui/viewpages/BlankViewStep.h @@ -31,7 +31,8 @@ namespace Calamares /** @brief A "blank" view step, used for error and status reporting * - * + * This view step never allows navigation (forward or back); it's a trap. + * It displays a title and explanation, and optional details. */ class BlankViewStep : public Calamares::ViewStep { @@ -55,12 +56,6 @@ public: bool isAtEnd() const override; Calamares::JobList jobs() const override; -#if 0 - void onActivate() override; - - - void setConfigurationMap( const QVariantMap& configurationMap ) override; -#endif private: QWidget* m_widget; From 97a45db4bf87e416f5096c1b92ecaec09bb22dbe Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Jun 2018 02:35:49 -0400 Subject: [PATCH 13/14] [libcalamaresui] Reset font height when changing size - defaultFontHeight() caches the result; clear cache when changing the default size, even though this happens only once in the current codebase. --- src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 3c59b0f89..e4dc6b555 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -239,6 +239,7 @@ void setDefaultFontSize( int points ) { s_defaultFontSize = points; + s_defaultFontHeight = 0; // Recalculate on next call to defaultFontHeight() } From a8426730ca1dd05ccd9f290935566d6e33d52dbe Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Jun 2018 02:48:52 -0400 Subject: [PATCH 14/14] [libcalamaresui] Improve wording of modules failure warning --- src/libcalamaresui/ViewManager.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 8777f79d7..2b9f87db8 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -177,14 +177,21 @@ void ViewManager::onInitFailed( const QStringList& modules) { QString title( tr( "Calamares Initialization Failed" ) ); - QString description( tr( "Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. %1 can not be installed." ) ); - QStringList details; - details << QLatin1Literal("
    "); - for( const auto& m : modules ) - details << QLatin1Literal("
  • ") << m << QLatin1Literal("
  • "); - details << QLatin1Literal("
"); - - insertViewStep( 0, new BlankViewStep( title, description.arg( *Calamares::Branding::ShortProductName ), details.join( QString() ) ) ); + QString description( tr( "%1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution." ) ); + QString detailString; + + if ( modules.count() > 0 ) + { + description.append( tr( "
The following modules could not be loaded:" ) ); + QStringList details; + details << QLatin1Literal("
    "); + for( const auto& m : modules ) + details << QLatin1Literal("
  • ") << m << QLatin1Literal("
  • "); + details << QLatin1Literal("
"); + detailString = details.join( QString() ); + } + + insertViewStep( 0, new BlankViewStep( title, description.arg( *Calamares::Branding::ShortProductName ), detailString ) ); } ViewStepList