153757933a
- The architecture of letting someone build up a list of requirements from data emitted by the ModuleManager is broken: if it gets loaded later, it will miss data; passing around complicated objects is no fun anyway. Get rid of it, on the way to "ModuleManager has its own model of requirements".
133 lines
4.1 KiB
C++
133 lines
4.1 KiB
C++
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
|
*
|
|
* Copyright 2019, Adriaan de Groot <groot@kde.org>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "RequirementsChecker.h"
|
|
|
|
#include "modulesystem/Module.h"
|
|
#include "modulesystem/Requirement.h"
|
|
#include "modulesystem/RequirementsModel.h"
|
|
#include "utils/Logger.h"
|
|
|
|
#include <QFuture>
|
|
#include <QFutureWatcher>
|
|
#include <QTimer>
|
|
#include <QtConcurrent/QtConcurrent>
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Calamares
|
|
{
|
|
|
|
RequirementsChecker::RequirementsChecker( QVector< Module* > modules, RequirementsModel* model, QObject* parent )
|
|
: QObject( parent )
|
|
, m_modules( std::move( modules ) )
|
|
, m_model( model )
|
|
, m_progressTimer( nullptr )
|
|
, m_progressTimeouts( 0 )
|
|
{
|
|
m_watchers.reserve( m_modules.count() );
|
|
}
|
|
|
|
RequirementsChecker::~RequirementsChecker() {}
|
|
|
|
void
|
|
RequirementsChecker::run()
|
|
{
|
|
m_progressTimer = new QTimer( this );
|
|
connect( m_progressTimer, &QTimer::timeout, this, &RequirementsChecker::reportProgress );
|
|
m_progressTimer->start( 1200 ); // msec
|
|
|
|
for ( const auto& module : m_modules )
|
|
{
|
|
Watcher* watcher = new Watcher( this );
|
|
watcher->setFuture( QtConcurrent::run( this, &RequirementsChecker::addCheckedRequirements, module ) );
|
|
watcher->setObjectName( module->name() );
|
|
m_watchers.append( watcher );
|
|
connect( watcher, &Watcher::finished, this, &RequirementsChecker::finished );
|
|
}
|
|
|
|
QTimer::singleShot( 0, this, &RequirementsChecker::finished );
|
|
}
|
|
|
|
void
|
|
RequirementsChecker::finished()
|
|
{
|
|
static QMutex finishedMutex;
|
|
QMutexLocker lock( &finishedMutex );
|
|
|
|
if ( m_progressTimer && std::all_of( m_watchers.cbegin(), m_watchers.cend(), []( const Watcher* w ) {
|
|
return w && w->isFinished();
|
|
} ) )
|
|
{
|
|
cDebug() << "All requirements have been checked.";
|
|
if ( m_progressTimer )
|
|
{
|
|
m_progressTimer->stop();
|
|
delete m_progressTimer;
|
|
m_progressTimer = nullptr;
|
|
}
|
|
|
|
m_model->describe();
|
|
QTimer::singleShot( 0, this, &RequirementsChecker::done );
|
|
}
|
|
}
|
|
|
|
void
|
|
RequirementsChecker::addCheckedRequirements( Module* m )
|
|
{
|
|
RequirementsList l = m->checkRequirements();
|
|
cDebug() << "Got" << l.count() << "requirement results from" << m->name();
|
|
if ( l.count() > 0 )
|
|
{
|
|
m_model->addRequirementsList( l );
|
|
}
|
|
|
|
requirementsProgress(
|
|
tr( "Requirements checking for module <i>%1</i> is complete." ).arg( m->name() ) );
|
|
}
|
|
|
|
void
|
|
RequirementsChecker::reportProgress()
|
|
{
|
|
m_progressTimeouts++;
|
|
|
|
QStringList remainingNames;
|
|
auto remaining = std::count_if( m_watchers.cbegin(), m_watchers.cend(), [&]( const Watcher* w ) {
|
|
if ( w && !w->isFinished() )
|
|
{
|
|
remainingNames << w->objectName();
|
|
return true;
|
|
}
|
|
return false;
|
|
} );
|
|
if ( remaining > 0 )
|
|
{
|
|
cDebug() << "Remaining modules:" << remaining << Logger::DebugList( remainingNames );
|
|
unsigned int posInterval = ( m_progressTimer->interval() < 0 ) ? 1000 : uint( m_progressTimer->interval() );
|
|
QString waiting = tr( "Waiting for %n module(s).", "", remaining );
|
|
QString elapsed = tr( "(%n second(s))", "", m_progressTimeouts * posInterval / 1000 );
|
|
emit requirementsProgress( waiting + QString( " " ) + elapsed );
|
|
}
|
|
else
|
|
{
|
|
emit requirementsProgress( tr( "System-requirements checking is complete." ) );
|
|
}
|
|
}
|
|
|
|
} // namespace Calamares
|