diff --git a/src/modules/netinstall/Config.cpp b/src/modules/netinstall/Config.cpp index 5f703f8d4..2d663829c 100644 --- a/src/modules/netinstall/Config.cpp +++ b/src/modules/netinstall/Config.cpp @@ -54,9 +54,11 @@ Config::status() const case Status::FailedBadData: return tr( "Network Installation. (Disabled: Received invalid groups data)" ); case Status::FailedInternalError: - return tr( "Network Installation. (Disabled: internal error)" ); + return tr( "Network Installation. (Disabled: Internal error)" ); case Status::FailedNetworkError: return tr( "Network Installation. (Disabled: Unable to fetch package lists, check your network connection)" ); + case Status::FailedNoData: + return tr( "Network Installation. (Disabled: No package list)" ); } __builtin_unreachable(); } @@ -89,6 +91,11 @@ Config::loadGroupList( const QVariantList& groupData ) if ( m_model->rowCount() < 1 ) { cWarning() << "NetInstall groups data was empty."; + setStatus( Status::FailedNoData ); + } + else + { + setStatus( Status::Ok ); } emit statusReady(); } @@ -134,7 +141,7 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) m_queue = new LoaderQueue( this ); m_queue->append( SourceItem::makeSourceItem( groupsUrlVariant.toString(), configurationMap ) ); } - else if ( groupsUrlVariant.type() == QVariant::StringList ) + else if ( groupsUrlVariant.type() == QVariant::List ) { m_queue = new LoaderQueue( this ); for ( const auto& s : groupsUrlVariant.toStringList() ) @@ -142,10 +149,11 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) m_queue->append( SourceItem::makeSourceItem( s, configurationMap ) ); } } - if ( m_queue ) + if ( m_queue && m_queue->count() > 0 ) { + cDebug() << "Loading netinstall from" << m_queue->count() << "alternate sources."; connect( m_queue, &LoaderQueue::done, this, &Config::loadingDone ); - QMetaObject::invokeMethod( m_queue, "fetchNext", Qt::QueuedConnection ); + m_queue->load(); } } diff --git a/src/modules/netinstall/Config.h b/src/modules/netinstall/Config.h index d4c3c6f19..b676a7d39 100644 --- a/src/modules/netinstall/Config.h +++ b/src/modules/netinstall/Config.h @@ -47,7 +47,9 @@ public: FailedBadConfiguration, FailedInternalError, FailedNetworkError, - FailedBadData + FailedBadData, + FailedNoData + }; QString status() const; diff --git a/src/modules/netinstall/LoaderQueue.cpp b/src/modules/netinstall/LoaderQueue.cpp index 98245dead..f8ba17cff 100644 --- a/src/modules/netinstall/LoaderQueue.cpp +++ b/src/modules/netinstall/LoaderQueue.cpp @@ -20,6 +20,32 @@ #include #include +/** @brief Call fetchNext() on the queue if it can + * + * On destruction, a new call to fetchNext() is queued, so that + * the queue continues loading. Calling release() before the + * destructor skips the fetchNext(), ending the queue-loading. + */ +class FetchNextUnless +{ +public: + FetchNextUnless( LoaderQueue* q ) + : m_q( q ) + { + } + ~FetchNextUnless() + { + if ( m_q ) + { + QMetaObject::invokeMethod( m_q, "fetchNext", Qt::QueuedConnection ); + } + } + void release() { m_q = nullptr; } + +private: + LoaderQueue* m_q = nullptr; +}; + SourceItem SourceItem::makeSourceItem( const QString& groupsUrl, const QVariantMap& configurationMap ) { @@ -45,6 +71,13 @@ LoaderQueue::append( SourceItem&& i ) m_queue.append( std::move( i ) ); } +void +LoaderQueue::load() +{ + QMetaObject::invokeMethod( this, "fetchNext", Qt::QueuedConnection ); +} + + void LoaderQueue::fetchNext() { @@ -67,13 +100,16 @@ LoaderQueue::fetchNext() } } - void LoaderQueue::fetch( const QUrl& url ) { + FetchNextUnless next( this ); + if ( !url.isValid() ) { m_config->setStatus( Config::Status::FailedBadConfiguration ); + cDebug() << "Invalid URL" << url; + return; } using namespace CalamaresUtils::Network; @@ -85,42 +121,20 @@ LoaderQueue::fetch( const QUrl& url ) if ( !reply ) { - cDebug() << Logger::Continuation << "request failed immediately."; + cDebug() << Logger::SubEntry << "Request failed immediately."; + // If nobody sets a different status, this will remain m_config->setStatus( Config::Status::FailedBadConfiguration ); } else { + // When the network request is done, **then** we might + // do the next item from the queue, so don't call fetchNext() now. + next.release(); m_reply = reply; connect( reply, &QNetworkReply::finished, this, &LoaderQueue::dataArrived ); } } -/** @brief Call fetchNext() on the queue if it can - * - * On destruction, a new call to fetchNext() is queued, so that - * the queue continues loading. Calling release() before the - * destructor skips the fetchNext(), ending the queue-loading. - */ -class FetchNextUnless -{ -public: - FetchNextUnless( LoaderQueue* q ) - : m_q( q ) - { - } - ~FetchNextUnless() - { - if ( m_q ) - { - QMetaObject::invokeMethod( m_q, "fetchNext", Qt::QueuedConnection ); - } - } - void release() { m_q = nullptr; } - -private: - LoaderQueue* m_q = nullptr; -}; - void LoaderQueue::dataArrived() { diff --git a/src/modules/netinstall/LoaderQueue.h b/src/modules/netinstall/LoaderQueue.h index de6c7276f..d7baf58d4 100644 --- a/src/modules/netinstall/LoaderQueue.h +++ b/src/modules/netinstall/LoaderQueue.h @@ -41,7 +41,14 @@ struct SourceItem static SourceItem makeSourceItem( const QString& groupsUrl, const QVariantMap& configurationMap ); }; - +/** @brief Queue of source items to load + * + * Queue things up by calling append() and then kick things off + * by calling load(). This will try to load the items, in order; + * the first one that succeeds will end the loading process. + * + * Signal done() is emitted when done (also when all of the items fail). + */ class LoaderQueue : public QObject { Q_OBJECT @@ -49,9 +56,12 @@ public: LoaderQueue( Config* parent ); void append( SourceItem&& i ); - void fetchNext(); + int count() const { return m_queue.count(); } public Q_SLOTS: + void load(); + + void fetchNext(); void fetch( const QUrl& url ); void dataArrived();