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.
main
Teo Mrnjavac 11 years ago
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;
}
}
namespace Calamares
{
Module::~Module()
{}
Calamares::Module*
Calamares::Module::fromConfigFile( const QString& path )
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;

@ -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

@ -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…
Cancel
Save