Lots of changes. Module search+load system is now working.
Moved module-related classes to src/calamares/modulesystem. Fixes to startup code path. Made ViewPlugins load into ViewManager. Debug code: ViewManager currently only shows a plugin's prettyName. Added ViewModule as a subclass of Module. Other kinds of plugins should be supported in a similar way.
This commit is contained in:
parent
fae3284bb7
commit
23e91ee475
@ -10,12 +10,14 @@ set( calamaresSources
|
||||
main.cpp
|
||||
CalamaresApplication.cpp
|
||||
CalamaresWindow.cpp
|
||||
Module.cpp
|
||||
ModuleManager.cpp
|
||||
ViewManager.cpp
|
||||
Settings.cpp
|
||||
YamlUtils.cpp
|
||||
|
||||
modulesystem/Module.cpp
|
||||
modulesystem/ModuleManager.cpp
|
||||
modulesystem/ViewModule.cpp
|
||||
|
||||
viewpages/ViewPlugin.cpp
|
||||
viewpages/AbstractPage.cpp
|
||||
)
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include "CalamaresWindow.h"
|
||||
#include "CalamaresVersion.h"
|
||||
#include "ModuleManager.h"
|
||||
#include "modulesystem/ModuleManager.h"
|
||||
#include "Settings.h"
|
||||
#include "utils/CalamaresUtils.h"
|
||||
#include "utils/Logger.h"
|
||||
@ -115,9 +115,9 @@ CalamaresApplication::initPlugins()
|
||||
{
|
||||
m_moduleManager = new Calamares::ModuleManager(
|
||||
Calamares::Settings::instance()->modulesSearchPaths(), this );
|
||||
connect( m_moduleManager, &Calamares::ModuleManager::ready,
|
||||
connect( m_moduleManager, &Calamares::ModuleManager::initDone,
|
||||
this, &CalamaresApplication::onPluginsReady );
|
||||
m_moduleManager->start();
|
||||
m_moduleManager->init();
|
||||
}
|
||||
|
||||
|
||||
@ -128,13 +128,11 @@ CalamaresApplication::onPluginsReady()
|
||||
|
||||
m_mainwindow = new CalamaresWindow();
|
||||
|
||||
// foreach ( QString moduleName, Calamares::Settings::instance()->viewModulesPrepare() )
|
||||
// {
|
||||
// Q_ASSERT( m_moduleManager->availableModules().contains( moduleName ) );
|
||||
// m_moduleManager->module( moduleName )->loadSelf();
|
||||
// }
|
||||
|
||||
m_mainwindow->show();
|
||||
m_moduleManager->loadRequiredModules();
|
||||
connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded, [this]
|
||||
{
|
||||
m_mainwindow->show();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "ViewManager.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QBoxLayout>
|
||||
|
||||
namespace Calamares
|
||||
@ -79,7 +80,9 @@ ViewManager::widget()
|
||||
void
|
||||
ViewManager::addViewPlugin( ViewPlugin* plugin )
|
||||
{
|
||||
|
||||
plugin->setParent( this );
|
||||
m_steps.append( plugin );
|
||||
m_stack->addWidget( new QLabel( plugin->prettyName(), m_stack ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include "viewpages/ViewPlugin.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QQueue>
|
||||
#include <QStackedWidget>
|
||||
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
@ -52,6 +54,8 @@ public slots:
|
||||
private:
|
||||
static ViewManager* s_instance;
|
||||
|
||||
QQueue< ViewPlugin* > m_steps;
|
||||
|
||||
QWidget* m_widget;
|
||||
QStackedWidget* m_stack;
|
||||
QPushButton* m_back;
|
||||
|
@ -18,13 +18,15 @@
|
||||
|
||||
#include "Module.h"
|
||||
|
||||
#include "ViewModule.h"
|
||||
#include "YamlUtils.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
|
||||
|
||||
@ -40,49 +42,55 @@ requires: [] #list of module names that must also be loaded. only appli
|
||||
*/
|
||||
|
||||
void
|
||||
operator>>( const YAML::Node& node, Calamares::Module& m )
|
||||
operator>>( const YAML::Node& node, Calamares::Module* m )
|
||||
{
|
||||
m.m_name = QString::fromStdString( node[ "name" ].as< std::string >() );
|
||||
m->m_name = QString::fromStdString( node[ "name" ].as< std::string >() );
|
||||
|
||||
QString typeString = QString::fromStdString( node[ "type" ].as< std::string >() );
|
||||
if ( typeString == "core" )
|
||||
{
|
||||
m.m_type = Calamares::Module::Core;
|
||||
m->m_type = Calamares::Module::Core;
|
||||
}
|
||||
else if ( typeString == "view" )
|
||||
{
|
||||
m.m_type = Calamares::Module::View;
|
||||
m.m_interface = Calamares::Module::QtPlugin;
|
||||
m->m_type = Calamares::Module::View;
|
||||
m->m_interface = Calamares::Module::QtPlugin;
|
||||
}
|
||||
|
||||
if ( m.m_type != Calamares::Module::View )
|
||||
if ( m->m_type != Calamares::Module::View )
|
||||
{
|
||||
QString interfaceString = QString::fromStdString( node[ "interface" ].as< std::string >() );
|
||||
if ( interfaceString == "qtplugin" )
|
||||
{
|
||||
m.m_interface = Calamares::Module::QtPlugin;
|
||||
m->m_interface = Calamares::Module::QtPlugin;
|
||||
}
|
||||
else if ( interfaceString == "python" )
|
||||
{
|
||||
m.m_interface = Calamares::Module::Python;
|
||||
m->m_interface = Calamares::Module::Python;
|
||||
}
|
||||
else if ( interfaceString == "process" )
|
||||
{
|
||||
m.m_interface = Calamares::Module::Process;
|
||||
m->m_interface = Calamares::Module::Process;
|
||||
}
|
||||
}
|
||||
|
||||
if ( node[ "requires" ] && node[ "requires" ].IsSequence() )
|
||||
{
|
||||
node[ "requires" ] >> m.m_requiredModules;
|
||||
node[ "requires" ] >> m->m_requiredModules;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Calamares::Module*
|
||||
Calamares::Module::fromConfigFile( const QString& path )
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
Module::~Module()
|
||||
{}
|
||||
|
||||
Module*
|
||||
Module::fromConfigFile( const QString& path )
|
||||
{
|
||||
Module* m = nullptr;
|
||||
QFile metadataFile( path );
|
||||
if ( metadataFile.exists() && metadataFile.open( QFile::ReadOnly | QFile::Text ) )
|
||||
{
|
||||
@ -99,13 +107,18 @@ Calamares::Module::fromConfigFile( const QString& path )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Module* m = new Module();
|
||||
moduleDocument >> *m;
|
||||
m = new ViewModule();
|
||||
|
||||
QFileInfo mfi( path );
|
||||
m->m_directory = mfi.absoluteDir().absolutePath();
|
||||
|
||||
m->initFrom( moduleDocument );
|
||||
return m;
|
||||
}
|
||||
catch ( YAML::Exception& e )
|
||||
{
|
||||
cDebug() << "WARNING: YAML parser error " << e.what();
|
||||
delete m;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -114,14 +127,42 @@ Calamares::Module::fromConfigFile( const QString& path )
|
||||
}
|
||||
|
||||
QString
|
||||
Calamares::Module::name()
|
||||
Module::name()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
QStringList
|
||||
Calamares::Module::requiredModules()
|
||||
Module::requiredModules()
|
||||
{
|
||||
return m_requiredModules;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
Module::location()
|
||||
{
|
||||
return m_directory;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Module::isLoaded()
|
||||
{
|
||||
return m_loaded;
|
||||
}
|
||||
|
||||
|
||||
Module::Module()
|
||||
: m_loaded( false )
|
||||
{}
|
||||
|
||||
|
||||
void
|
||||
Module::initFrom( const YAML::Node& node )
|
||||
{
|
||||
node >> this;
|
||||
}
|
||||
|
||||
} //ns
|
@ -16,8 +16,8 @@
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CALAMARESMODULE_H
|
||||
#define CALAMARESMODULE_H
|
||||
#ifndef CALAMARES_MODULE_H
|
||||
#define CALAMARES_MODULE_H
|
||||
|
||||
#include "UiDllMacro.h"
|
||||
|
||||
@ -34,7 +34,7 @@ namespace Calamares
|
||||
class Module;
|
||||
}
|
||||
|
||||
void operator>>( const YAML::Node& node, Calamares::Module& m );
|
||||
void operator>>( const YAML::Node& node, Calamares::Module* m );
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
@ -42,11 +42,6 @@ namespace Calamares
|
||||
class UIDLLEXPORT Module
|
||||
{
|
||||
public:
|
||||
static Module* fromConfigFile( const QString& path );
|
||||
|
||||
QString name();
|
||||
QStringList requiredModules();
|
||||
|
||||
enum Type
|
||||
{
|
||||
Core,
|
||||
@ -59,15 +54,35 @@ public:
|
||||
Python,
|
||||
Process
|
||||
};
|
||||
virtual ~Module();
|
||||
|
||||
static Module* fromConfigFile( const QString& path );
|
||||
|
||||
virtual QString name();
|
||||
virtual QStringList requiredModules();
|
||||
virtual QString location();
|
||||
virtual Type type() = 0;
|
||||
virtual Interface interface() = 0;
|
||||
|
||||
virtual bool isLoaded();
|
||||
|
||||
virtual void loadSelf() = 0;
|
||||
|
||||
protected:
|
||||
explicit Module();
|
||||
virtual void initFrom( const YAML::Node& node );
|
||||
bool m_loaded;
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
Type m_type;
|
||||
Interface m_interface;
|
||||
QStringList m_requiredModules;
|
||||
QString m_directory;
|
||||
|
||||
friend void ::operator>>( const YAML::Node& node, Calamares::Module& m );
|
||||
friend void ::operator>>( const YAML::Node& node, Calamares::Module* m );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CALAMARESMODULE_H
|
||||
#endif // CALAMARES_MODULE_H
|
@ -19,9 +19,11 @@
|
||||
#include "ModuleManager.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
|
||||
@ -46,9 +48,9 @@ ModuleManager::~ModuleManager()
|
||||
|
||||
|
||||
void
|
||||
ModuleManager::start()
|
||||
ModuleManager::init()
|
||||
{
|
||||
QTimer::singleShot( 0, this, SLOT( doWork() ) );
|
||||
QTimer::singleShot( 0, this, SLOT( doInit() ) );
|
||||
}
|
||||
|
||||
|
||||
@ -67,7 +69,14 @@ ModuleManager::module( const QString& name )
|
||||
|
||||
|
||||
void
|
||||
ModuleManager::doWork()
|
||||
ModuleManager::loadRequiredModules()
|
||||
{
|
||||
QTimer::singleShot( 0, this, SLOT( doLoadModules() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModuleManager::doInit()
|
||||
{
|
||||
// We start from a list of paths in m_paths. Each of those is a directory that
|
||||
// might (should) contain Calamares modules of any type/interface.
|
||||
@ -120,7 +129,46 @@ ModuleManager::doWork()
|
||||
// At this point m_availableModules is filled with whatever was found in the
|
||||
// search paths.
|
||||
checkDependencies();
|
||||
emit ready();
|
||||
emit initDone();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModuleManager::doLoadModules()
|
||||
{
|
||||
foreach ( const QString& moduleName, Settings::instance()->viewModulesPrepare() )
|
||||
{
|
||||
if ( !m_availableModules.contains( moduleName ) )
|
||||
{
|
||||
cDebug() << "Module" << moduleName << "not found in module search paths."
|
||||
<< "\nCalamares will now quit.";
|
||||
qApp->quit();
|
||||
}
|
||||
recursiveLoad( moduleName );
|
||||
}
|
||||
emit modulesLoaded();
|
||||
|
||||
//IDEA:
|
||||
// 1) deps are already fine. check if we have all the modules needed by the roster
|
||||
// 2) ask MM to load them from the list provided by Settings
|
||||
// 3) MM must load them asyncly but one at a time, by calling Module::loadSelf
|
||||
// 4) Module must have subclasses that reimplement loadSelf for various module types
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModuleManager::recursiveLoad( const QString& moduleName )
|
||||
{
|
||||
Module* thisModule = m_availableModules.value( moduleName );
|
||||
foreach ( const QString& module, thisModule->requiredModules() )
|
||||
{
|
||||
if ( !m_availableModules.value( module )->isLoaded() )
|
||||
{
|
||||
recursiveLoad( module );
|
||||
}
|
||||
}
|
||||
thisModule->loadSelf();
|
||||
cDebug() << ( thisModule->isLoaded() ? "SUCCESS" : "FAILURE" );
|
||||
}
|
||||
|
||||
|
||||
@ -152,4 +200,5 @@ ModuleManager::checkDependencies()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -37,18 +37,23 @@ public:
|
||||
explicit ModuleManager( const QStringList& paths, QObject* parent = 0 );
|
||||
virtual ~ModuleManager();
|
||||
|
||||
void start();
|
||||
void init();
|
||||
|
||||
QStringList availableModules();
|
||||
Module* module( const QString& name );
|
||||
|
||||
void loadRequiredModules();
|
||||
|
||||
signals:
|
||||
void ready();
|
||||
void initDone();
|
||||
void modulesLoaded();
|
||||
|
||||
private slots:
|
||||
void doWork();
|
||||
void doInit();
|
||||
void doLoadModules();
|
||||
|
||||
private:
|
||||
void recursiveLoad( const QString& moduleName );
|
||||
void checkDependencies();
|
||||
|
||||
QMap< QString, Module* > m_availableModules;
|
106
src/calamares/modulesystem/ViewModule.cpp
Normal file
106
src/calamares/modulesystem/ViewModule.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014, Teo Mrnjavac <teo@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 "ViewModule.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "viewpages/ViewPlugin.h"
|
||||
#include "ViewManager.h"
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QPluginLoader>
|
||||
|
||||
namespace Calamares {
|
||||
|
||||
|
||||
Module::Type
|
||||
ViewModule::type()
|
||||
{
|
||||
return View;
|
||||
}
|
||||
|
||||
|
||||
Module::Interface
|
||||
ViewModule::interface()
|
||||
{
|
||||
return QtPlugin;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewModule::loadSelf()
|
||||
{
|
||||
cDebug() << Q_FUNC_INFO << "for module" << name();
|
||||
if ( m_loader )
|
||||
{
|
||||
ViewPlugin *vp = qobject_cast< ViewPlugin* >( m_loader->instance() );
|
||||
if ( vp )
|
||||
{
|
||||
ViewManager::instance()->addViewPlugin( vp );
|
||||
m_loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewModule::initFrom( const YAML::Node& node )
|
||||
{
|
||||
Module::initFrom( node );
|
||||
QDir directory( location() );
|
||||
QString load;
|
||||
if ( node[ "load" ] )
|
||||
{
|
||||
load = QString::fromStdString( node[ "load" ].as<std::string>() );
|
||||
load = directory.absoluteFilePath( load );
|
||||
}
|
||||
// If a load path is not specified, we look for a plugin to load in the directory.
|
||||
if ( load.isEmpty() || !QLibrary::isLibrary( load ) )
|
||||
{
|
||||
QStringList ls = directory.entryList( QStringList() = { "*.so" } );
|
||||
if ( !ls.isEmpty() )
|
||||
{
|
||||
foreach ( QString entry, ls )
|
||||
{
|
||||
entry = directory.absoluteFilePath( entry );
|
||||
if ( QLibrary::isLibrary( entry ) )
|
||||
{
|
||||
load = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_loader = new QPluginLoader( load );
|
||||
}
|
||||
|
||||
ViewModule::ViewModule()
|
||||
: Module()
|
||||
, m_loader( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
ViewModule::~ViewModule()
|
||||
{
|
||||
delete m_loader;
|
||||
}
|
||||
|
||||
} // namespace Calamares
|
50
src/calamares/modulesystem/ViewModule.h
Normal file
50
src/calamares/modulesystem/ViewModule.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014, Teo Mrnjavac <teo@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/>.
|
||||
*/
|
||||
|
||||
#ifndef CALAMARES_VIEWMODULE_H
|
||||
#define CALAMARES_VIEWMODULE_H
|
||||
|
||||
#include "UiDllMacro.h"
|
||||
#include "Module.h"
|
||||
|
||||
class QPluginLoader;
|
||||
|
||||
namespace Calamares {
|
||||
|
||||
class UIDLLEXPORT ViewModule : public Module
|
||||
{
|
||||
public:
|
||||
Type type() override;
|
||||
Interface interface() override;
|
||||
|
||||
void loadSelf() override;
|
||||
|
||||
protected:
|
||||
void initFrom( const YAML::Node &node ) override;
|
||||
|
||||
private:
|
||||
friend class Module; //so only the superclass can instantiate
|
||||
explicit ViewModule();
|
||||
virtual ~ViewModule();
|
||||
|
||||
QPluginLoader *m_loader;
|
||||
};
|
||||
|
||||
} // namespace Calamares
|
||||
|
||||
#endif // CALAMARES_VIEWMODULE_H
|
@ -35,6 +35,8 @@ public:
|
||||
explicit ViewPlugin( QObject *parent = 0 );
|
||||
virtual ~ViewPlugin() {}
|
||||
|
||||
virtual QString prettyName() = 0;
|
||||
|
||||
signals:
|
||||
void done();
|
||||
|
||||
|
@ -18,7 +18,15 @@
|
||||
|
||||
#include "GreetingViewPlugin.h"
|
||||
|
||||
|
||||
GreetingViewPlugin::GreetingViewPlugin( QObject *parent )
|
||||
: Calamares::ViewPlugin( parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
GreetingViewPlugin::prettyName()
|
||||
{
|
||||
return tr( "Welcome" );
|
||||
}
|
||||
|
@ -30,10 +30,11 @@ class PLUGINDLLEXPORT GreetingViewPlugin : public Calamares::ViewPlugin
|
||||
Q_PLUGIN_METADATA( IID "calamares.ViewPlugin/1.0" )
|
||||
//FILE "module.json" )
|
||||
Q_INTERFACES( Calamares::ViewPlugin )
|
||||
|
||||
public:
|
||||
explicit GreetingViewPlugin(QObject *parent = 0);
|
||||
|
||||
|
||||
QString prettyName() override;
|
||||
};
|
||||
|
||||
#endif // GREETINGPAGEPLUGIN_H
|
||||
|
Loading…
Reference in New Issue
Block a user