Initial upload of HyprArch releng configuration

This commit is contained in:
2026-03-03 20:31:33 +00:00
commit 7df61351c0
634 changed files with 36355 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef MODULESYSTEM_ACTIONS_H
#define MODULESYSTEM_ACTIONS_H
namespace Calamares
{
namespace ModuleSystem
{
enum class Action : char
{
Show,
Exec
};
} // namespace ModuleSystem
} // namespace Calamares
#endif

View File

@@ -0,0 +1,147 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_MODULESYSTEM_CONFIG_H
#define CALAMARES_MODULESYSTEM_CONFIG_H
#include "DllMacro.h"
#include <QObject>
#include <QStringList>
#include <QVariantMap>
#include <memory>
namespace Calamares
{
namespace ModuleSystem
{
/** @brief Base class for Config-objects
*
* This centralizes the things every Config-object should
* do and provides one source of preset-data. A Config-object
* for a module can **optionally** inherit from this class
* to get presets-support.
*
* TODO:3.3 This is not optional
* TODO:3.3 Put consistent i18n for Configurations in here too
*/
class DLLEXPORT Config : public QObject
{
Q_OBJECT
public:
Config( QObject* parent = nullptr );
~Config() override;
/** @brief Set the configuration from the config file
*
* Subclasses must implement this to load configuration data;
* that subclass **should** also call loadPresets() with the
* same map, to pick up the "presets" key consistently.
*/
virtual void setConfigurationMap( const QVariantMap& ) = 0;
public Q_SLOTS:
/** @brief Checks if a @p fieldName is editable according to presets
*
* If the field is named as a preset, **and** the field is set
* to not-editable, returns @c false. Otherwise, return @c true.
* Calling this with an unknown field (one for which no presets
* are accepted) will print a warning and return @c true.
*
* @see CONFIG_PREVENT_EDITING
*
* Most setters will call isEditable() to check if the field should
* be editable. Do not count on the setter not being called: the
* UI might not have set the field to fixed / constant / not-editable
* and then you can have the setter called by changes in the UI.
*
* To prevent the UI from changing **and** to make sure that the UI
* reflects the unchanged value (rather than the changed value it
* sent to the Config object), use CONFIG_PREVENT_EDITING, like so:
*
* CONFIG_PREVENT_EDITING( type, "propertyName" );
*
* The ; is necessary. <type> is the type of the property; for instance
* QString. The name of the property is a (constant) string. The
* macro will return (out of the setter it is used in) if the field
* is not editable, and will send a notification event with the old
* value as soon as the event loop resumes.
*/
bool isEditable( const QString& fieldName ) const;
protected:
friend class ApplyPresets;
/** @brief "Builder" class for presets
*
* Derived classes should instantiate this (with themselves,
* and the whole configuration map that is passed to
* setConfigurationMap()) and then call .apply() to apply
* the presets specified in the configuration to the **named**
* QObject properties.
*/
class ApplyPresets
{
public:
/** @brief Create a preset-applier for this config
*
* The @p configurationMap should be the one passed in to
* setConfigurationMap() . Presets are extracted from the
* standard key *presets* and can be applied to the configuration
* with apply() or operator<<.
*/
ApplyPresets( Config& c, const QVariantMap& configurationMap );
~ApplyPresets();
/** @brief Add a preset for the given @p fieldName
*
* This checks for preset-entries in the configuration map that was
* passed in to the constructor.
*/
ApplyPresets& apply( const char* fieldName );
/** @brief Alternate way of writing apply()
*/
ApplyPresets& operator<<( const char* fieldName ) { return apply( fieldName ); }
private:
Config& m_c;
bool m_bogus = true;
const QVariantMap m_map;
};
private:
class Private;
std::unique_ptr< Private > d;
bool m_unlocked = false;
};
} // namespace ModuleSystem
} // namespace Calamares
/// @see Config::isEditable()
//
// This needs to be a macro, because Q_ARG() is a macro that stringifies
// the type name.
#define CONFIG_PREVENT_EDITING( type, fieldName ) \
do \
{ \
if ( !isEditable( QStringLiteral( fieldName ) ) ) \
{ \
auto prop = property( fieldName ); \
const auto& metaobject = metaObject(); \
auto metaprop = metaobject->property( metaobject->indexOfProperty( fieldName ) ); \
if ( metaprop.hasNotifySignal() ) \
{ \
metaprop.notifySignal().invoke( this, Qt::QueuedConnection, Q_ARG( type, prop.value< type >() ) ); \
} \
return; \
} \
} while ( 0 )
#endif

View File

@@ -0,0 +1,50 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2016 Kevin Kofler <kevin.kofler@chello.at>
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_CPPJOBMODULE_H
#define CALAMARES_CPPJOBMODULE_H
#include "DllMacro.h"
#include "modulesystem/Module.h"
class QPluginLoader;
namespace Calamares
{
class UIDLLEXPORT CppJobModule : public Module
{
public:
Type type() const override;
Interface interface() const override;
void loadSelf() override;
JobList jobs() const override;
protected:
void initFrom( const ModuleSystem::Descriptor& moduleDescriptor ) override;
private:
explicit CppJobModule();
~CppJobModule() override;
QPluginLoader* m_loader;
job_ptr m_job;
friend Module* Calamares::moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
};
} // namespace Calamares
#endif // CALAMARES_CPPJOBMODULE_H

View File

@@ -0,0 +1,148 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef MODULESYSTEM_DESCRIPTOR_H
#define MODULESYSTEM_DESCRIPTOR_H
#include "DllMacro.h"
#include "utils/NamedEnum.h"
#include <QVariantMap>
namespace Calamares
{
namespace ModuleSystem
{
/**
* @brief The Type enum represents the intended functionality of the module
* Every module is either a job module or a view module.
* A job module is a single Calamares job.
* A view module has a UI (one or more view pages) and zero-to-many jobs.
*/
enum class Type
{
Job,
View
};
DLLEXPORT const NamedEnumTable< Type >& typeNames();
/**
* @brief The Interface enum represents the interface through which the module
* talks to Calamares.
* Not all Type-Interface associations are valid.
*/
enum class Interface
{
QtPlugin, // Jobs or Views
Python, // Jobs only
Process, // Deprecated interface
};
DLLEXPORT const NamedEnumTable< Interface >& interfaceNames();
/**
* @brief Description of a module (obtained from module.desc)
*
* Provides access to the fields of a descriptor, use type() to
* determine which specialized fields make sense for a given
* descriptor (e.g. a Python module has no shared-library path).
*/
class DLLEXPORT Descriptor
{
public:
///@brief an invalid, and empty, descriptor
Descriptor();
/** @brief Fills a descriptor from the loaded (YAML) data.
*
* The @p descriptorPath is used only for debug messages, the
* data is only read from @p moduleDesc.
*
*/
static Descriptor fromDescriptorData( const QVariantMap& moduleDesc, const QString& descriptorPath );
bool isValid() const { return m_isValid; }
QString name() const { return m_name; }
Type type() const { return m_type; }
Interface interface() const { return m_interface; }
bool isEmergency() const { return m_isEmergeny; }
bool hasConfig() const { return m_hasConfig; } // TODO: 3.5 rename to noConfig() to match descriptor key
int weight() const { return m_weight < 1 ? 1 : m_weight; }
bool explicitWeight() const { return m_weight > 0; }
/// @brief The directory where the module.desc lives
QString directory() const { return m_directory; }
void setDirectory( const QString& d ) { m_directory = d; }
const QStringList& requiredModules() const { return m_requiredModules; }
/** @section C++ Modules
*
* The C++ modules are the most general, and are loaded as
* a shared library after which a suitable factory creates
* objects from them.
*/
/// @brief Short path to the shared-library; no extension.
QString load() const { return m_interface == Interface::QtPlugin ? m_script : QString(); }
/** @section Process Job modules
*
* Process Jobs are somewhat deprecated in favor of shellprocess
* and contextualprocess jobs, since those handle multiple configuration
* much more gracefully.
*
* Process Jobs execute one command.
*/
/// @brief The command to execute; passed to the shell
QString command() const { return m_interface == Interface::Process ? m_script : QString(); }
/// @brief Timeout in seconds
int timeout() const { return m_processTimeout; }
/// @brief Run command in chroot?
bool chroot() const { return m_processChroot; }
/** @section Python Job modules
*
* Python job modules have one specific script to load and run.
*/
QString script() const { return m_interface == Interface::Python ? m_script : QString(); }
private:
QString m_name;
QString m_directory;
QStringList m_requiredModules;
int m_weight = -1;
Type m_type;
Interface m_interface;
bool m_isValid = false;
bool m_isEmergeny = false;
bool m_hasConfig = true;
/** @brief The name of the thing to load
*
* - A C++ module loads a shared library (via key *load*),
* - A Python module loads a Python script (via key *script*),
* - A process runs a specific command (via key *command*)
*
* This name-of-the-thing is stored here, regardless of which
* interface is being used.
*/
QString m_script;
int m_processTimeout = 30;
bool m_processChroot = false;
};
} // namespace ModuleSystem
} // namespace Calamares
#endif

View File

@@ -0,0 +1,117 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef MODULESYSTEM_INSTANCEKEY_H
#define MODULESYSTEM_INSTANCEKEY_H
#include "DllMacro.h"
#include <QDebug>
#include <QList>
#include <QString>
#include <tuple>
#include <utility>
namespace Calamares
{
namespace ModuleSystem
{
/** @brief A module instance's key (`module@id`)
*
* A module instance is identified by both the module's name
* (a Calamares module, e.g. `users`) and an instance id.
* Usually, the instance id is the same as the module name
* and the whole module instance key is `users@users`, but
* it is possible to use the same module more than once
* and then you distinguish those module instances by their
* secondary id (e.g. `users@one`).
*
* This is supported by the *instances* configuration entry
* in `settings.conf`.
*/
class DLLEXPORT InstanceKey
{
public:
/// @brief Create an instance key from explicit module and id.
InstanceKey( const QString& module, const QString& id )
: first( module )
, second( id )
{
if ( second.isEmpty() )
{
second = first;
}
validate();
}
/// @brief Create unusual, invalid instance key
InstanceKey() = default;
/// @brief A valid module has both name and id
bool isValid() const { return !first.isEmpty() && !second.isEmpty(); }
/// @brief A custom module has a non-default id
bool isCustom() const { return first != second; }
QString module() const { return first; }
QString id() const { return second; }
/// @brief Create instance key from stringified version
static InstanceKey fromString( const QString& s );
QString toString() const
{
if ( isValid() )
{
return first + '@' + second;
}
return QString();
}
friend bool operator==( const InstanceKey& lhs, const InstanceKey& rhs ) noexcept
{
return std::tie( lhs.first, lhs.second ) == std::tie( rhs.first, rhs.second );
}
friend bool operator<( const InstanceKey& lhs, const InstanceKey& rhs ) noexcept
{
return std::tie( lhs.first, lhs.second ) < std::tie( rhs.first, rhs.second );
}
private:
/** @brief Check validity and reset module and id if needed. */
void validate()
{
if ( first.contains( '@' ) || second.contains( '@' ) )
{
first = QString();
second = QString();
}
}
QString first;
QString second;
};
using InstanceKeyList = QList< InstanceKey >;
DLLEXPORT QDebug& operator<<( QDebug& s, const Calamares::ModuleSystem::InstanceKey& i );
inline QDebug&
operator<<( QDebug&& s, const Calamares::ModuleSystem::InstanceKey& i )
{
return s << i;
}
} // namespace ModuleSystem
} // namespace Calamares
#endif

View File

@@ -0,0 +1,169 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef CALAMARES_MODULE_H
#define CALAMARES_MODULE_H
#include "DllMacro.h"
#include "Job.h"
#include "modulesystem/Descriptor.h"
#include "modulesystem/InstanceKey.h"
#include "modulesystem/Requirement.h"
#include <QStringList>
#include <QVariant>
namespace Calamares
{
class Module;
Module* moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
/**
* @brief The Module class is a common supertype for Calamares modules.
* It enforces a common interface for all the different types of modules, and it
* takes care of creating an object of the correct type starting from a module
* descriptor structure.
*/
class DLLEXPORT Module
{
public:
using Type = ModuleSystem::Type;
using Interface = ModuleSystem::Interface;
virtual ~Module();
/**
* @brief name returns the name of this module.
* @return a string with this module's name.
*/
QString name() const { return m_key.module(); }
/**
* @brief instanceId returns the instance id of this module.
* @return a string with this module's instance id.
*/
QString instanceId() const { return m_key.id(); }
/**
* @brief instanceKey returns the instance key of this module.
* @return a string with the instance key.
* A module instance's instance key is modulename\@instanceid.
* For instance, "partition\@partition" (default configuration) or
* "locale\@someconfig" (custom configuration)
*/
ModuleSystem::InstanceKey instanceKey() const { return m_key; }
/**
* @brief location returns the full path of this module's directory.
* @return the path.
*/
QString location() const { return m_directory; }
/**
* @brief Is this an emergency module?
*
* An emergency module is run even if an error occurs
* which would terminate Calamares earlier in the same
* *exec* block. Emergency modules in later exec blocks
* are not run (in the common case where there is only
* one exec block, this doesn't really matter).
*/
bool isEmergency() const { return m_emergency; }
/**
* @brief isLoaded reports on the loaded status of a module.
* @return true if the module's loading phase has finished, otherwise false.
*/
bool isLoaded() const { return m_loaded; }
/**
* @brief configurationMap returns the contents of the configuration file for
* this module instance.
* @return the instance's configuration, already parsed from YAML into a variant map.
*/
QVariantMap configurationMap();
/**
* @brief typeString returns a user-visible string for the module's type.
* @return the type string.
*/
QString typeString() const;
/**
* @brief interface returns a user-visible string for the module's interface.
* @return the interface string.
*/
QString interfaceString() const;
/**
* @brief loadSelf initialized the module.
* Subclasses must reimplement this depending on the module type and interface.
*/
virtual void loadSelf() = 0;
/**
* @brief jobs returns any jobs exposed by this module.
* @return a list of jobs (can be empty).
*/
virtual JobList jobs() const = 0;
/**
* @brief type returns the Type of this module object.
* @return the type enum value.
*/
virtual Type type() const = 0;
/**
* @brief interface the Interface used by this module.
* @return the interface enum value.
*/
virtual Interface interface() const = 0;
/**
* @brief Check the requirements of this module.
*/
virtual RequirementsList checkRequirements();
protected:
explicit Module();
/// @brief For subclasses to read their part of the descriptor
virtual void initFrom( const ModuleSystem::Descriptor& moduleDescriptor ) = 0;
/// @brief Generic part of descriptor reading (and instance id)
void initFrom( const ModuleSystem::Descriptor& moduleDescriptor, const QString& id );
QVariantMap m_configurationMap;
bool m_loaded = false;
bool m_emergency = false; // Based on module and local config
bool m_maybe_emergency = false; // Based on the module.desc
private:
void loadConfigurationFile( const QString& configFileName ); //throws YAML::Exception
QString m_directory;
ModuleSystem::InstanceKey m_key;
friend Module* Calamares::moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
};
} // namespace Calamares
#endif // CALAMARES_MODULE_H

View File

@@ -0,0 +1,38 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_MODULEFACTORY_H
#define CALAMARES_MODULEFACTORY_H
#include "DllMacro.h"
#include "modulesystem/Descriptor.h"
#include "modulesystem/Module.h"
#include <QString>
namespace Calamares
{
/**
* @brief fromDescriptor creates a new Module object of the correct type.
* @param moduleDescriptor a module descriptor, already parsed into a variant map.
* @param instanceId the instance id of the new module instance.
* @param configFileName the name of the configuration file to read.
* @param moduleDirectory the path to the directory with this module's files.
* @return a pointer to an object of a subtype of Module.
*/
UIDLLEXPORT Module* moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
} // namespace Calamares
#endif // CALAMARES_MODULEFACTORY_H

View File

@@ -0,0 +1,177 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef MODULELOADER_H
#define MODULELOADER_H
#include "DllMacro.h"
#include "modulesystem/Descriptor.h"
#include "modulesystem/InstanceKey.h"
#include "modulesystem/Requirement.h"
#include <QObject>
#include <QStringList>
#include <QVariantMap>
namespace Calamares
{
class Module;
class RequirementsModel;
/**
* @brief The ModuleManager class is a singleton which manages Calamares modules.
*
* It goes through the module search directories and reads module metadata. It then
* constructs objects of type Module, loads them and makes them accessible by their
* instance key.
*/
class UIDLLEXPORT ModuleManager : public QObject
{
Q_OBJECT
public:
explicit ModuleManager( const QStringList& paths, QObject* parent = nullptr );
~ModuleManager() override;
static ModuleManager* instance();
/**
* @brief init goes through the module search directories and gets a list of
* modules available for loading, along with their metadata.
* This information is stored as a map of Module* objects, indexed by name.
*/
void init();
/**
* @brief loadedInstanceKeys returns a list of instance keys for the available
* modules.
* @return a QStringList with the instance keys.
*/
QList< ModuleSystem::InstanceKey > loadedInstanceKeys();
/**
* @brief moduleDescriptor returns the module descriptor structure for a given module.
* @param name the name of the module for which to return the module descriptor.
* @return the module descriptor, as a variant map already parsed from YAML.
*/
ModuleSystem::Descriptor moduleDescriptor( const QString& name );
/** @brief returns the module descriptor structure for the module @p instance
*
* Descriptors are for the module, which may have multiple instances;
* this is the same as moduleDescriptor( instance.module() ).
*/
ModuleSystem::Descriptor moduleDescriptor( const ModuleSystem::InstanceKey& instanceKey )
{
return moduleDescriptor( instanceKey.module() );
}
/**
* @brief moduleInstance returns a Module object for a given instance key.
* @param instanceKey the instance key for a module instance.
* @return a pointer to an object of a subtype of Module.
*/
Module* moduleInstance( const ModuleSystem::InstanceKey& instanceKey );
/**
* @brief loadModules does all of the module loading operation.
* When this is done, the signal modulesLoaded is emitted.
* It is recommended to call this from a single-shot QTimer.
*/
void loadModules();
/**
* @brief Adds a single module (loaded by some other means)
*
* Returns @c true on success (that is, the module's dependencies
* are satisfied, it wasn't already loaded, ...).
*/
bool addModule( Module* );
/**
* @brief Starts asynchronous requirements checking for each module.
* When this is done, the signal requirementsComplete is emitted.
*/
void checkRequirements();
///@brief Gets the model that requirements-checking works on.
RequirementsModel* requirementsModel() { return m_requirementsModel; }
signals:
/** @brief Emitted when all the module **configuration** has been read
*
* This indicates that all of the module.desc files have been
* loaded; bad ones are silently skipped, so this just indicates
* that the module manager is ready for the next phase (loading).
*/
void initDone();
/** @brief Emitted when all the modules are loaded successfully
*
* Each module listed in the settings is loaded. Modules are loaded
* only once, even when instantiated multiple times. If all of
* the listed modules are successfully loaded, this signal is
* emitted (otherwise, it isn't, so you need to wait for **both**
* of the signals).
*
* If this is emitted (i.e. all modules have loaded) then the next
* phase, requirements checking, can be started.
*/
void modulesLoaded();
/** @brief Emitted if any modules failed to load
*
* Modules that failed to load (for any reason) are listed by
* instance key (e.g. "welcome@welcome", "shellprocess@mycustomthing").
*/
void modulesFailed( QStringList );
/** @brief Emitted after all requirements have been checked
*
* The bool @p canContinue indicates if all of the **mandatory** requirements
* are satisfied (e.g. whether installation can continue).
*/
void requirementsComplete( bool canContinue );
private slots:
void doInit();
private:
/**
* Check in a general sense whether the dependencies between
* modules are valid. Returns the number of modules that
* have missing dependencies -- this is **not** a problem
* unless any of those modules are actually used.
*
* Returns 0 on success.
*
* Also modifies m_availableDescriptorsByModuleName to remove
* all the entries that (so that later, when we try to look
* them up, they are not found).
*/
size_t checkDependencies();
/**
* Check for this specific module if its required modules have
* already been loaded (i.e. are in sequence before it).
*
* Returns true if the requirements are met.
*/
bool checkModuleDependencies( const Module& );
QMap< QString, ModuleSystem::Descriptor > m_availableDescriptorsByModuleName;
QMap< ModuleSystem::InstanceKey, Module* > m_loadedModulesByInstanceKey;
const QStringList m_paths;
RequirementsModel* m_requirementsModel;
static ModuleManager* s_instance;
};
} // namespace Calamares
#endif // MODULELOADER_H

View File

@@ -0,0 +1,91 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_MODULESYSTEM_PRESET_H
#define CALAMARES_MODULESYSTEM_PRESET_H
#include <QString>
#include <QVariantMap>
#include <QVector>
namespace Calamares
{
namespace ModuleSystem
{
/** @brief The settings for a single field
*
* The settings apply to a single field; **often** this will
* correspond to a single value or property of a Config
* object, but there is no guarantee of a correspondence
* between names here and names in the code.
*
* The value is stored as a string; consumers (e.g. the UI)
* will need to translate the value to whatever is actually
* used (e.g. in the case of an integer field).
*
* By default, presets are still editable. Set that to @c false
* to make the field unchangeable (again, the UI is responsible
* for setting that up).
*/
struct PresetField
{
QString fieldName;
QVariant value;
bool editable = true;
bool isValid() const { return !fieldName.isEmpty(); }
};
/** @brief All the presets for one UI entity
*
* This is a collection of presets read from a module
* configuration file, one setting per field.
*/
class Presets : public QVector< PresetField >
{
public:
/** @brief Reads preset entries from the map
*
* The map's keys are used as field name, and each value entry
* should specify an initial value and whether the entry is editable.
* Fields are editable by default.
*/
explicit Presets( const QVariantMap& configurationMap );
/** @brief Reads preset entries from the @p configurationMap
*
* As above, but only field names that occur in @p recognizedKeys
* are kept; others are discarded.
*/
Presets( const QVariantMap& configurationMap, const QStringList& recognizedKeys );
/** @brief Creates an empty presets map
*
* This constructor is primarily intended for use by the ApplyPresets
* helper class, which will reserve suitable space and load
* presets on-demand.
*/
Presets() = default;
/** @brief Is the given @p fieldName editable?
*
* Fields are editable by default, so if there is no explicit setting,
* returns @c true.
*/
bool isEditable( const QString& fieldName ) const;
/** @brief Finds the settings for a field @p fieldName
*
* If there is no such field, returns an invalid PresetField.
*/
PresetField find( const QString& fieldName ) const;
};
} // namespace ModuleSystem
} // namespace Calamares
#endif

View File

@@ -0,0 +1,52 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_PROCESSJOBMODULE_H
#define CALAMARES_PROCESSJOBMODULE_H
#include "DllMacro.h"
#include "modulesystem/Module.h"
#include <chrono>
namespace Calamares
{
class UIDLLEXPORT ProcessJobModule : public Module
{
public:
Type type() const override;
Interface interface() const override;
void loadSelf() override;
JobList jobs() const override;
protected:
void initFrom( const ModuleSystem::Descriptor& moduleDescriptor ) override;
private:
explicit ProcessJobModule();
~ProcessJobModule() override;
QString m_command;
QString m_workingPath;
std::chrono::seconds m_secondsTimeout;
bool m_runInChroot;
job_ptr m_job;
friend Module* Calamares::moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
};
} // namespace Calamares
#endif // CALAMARES_PROCESSJOBMODULE_H

View File

@@ -0,0 +1,47 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_PYTHONJOBMODULE_H
#define CALAMARES_PYTHONJOBMODULE_H
#include "DllMacro.h"
#include "modulesystem/Module.h"
namespace Calamares
{
class UIDLLEXPORT PythonJobModule : public Module
{
public:
Type type() const override;
Interface interface() const override;
void loadSelf() override;
JobList jobs() const override;
protected:
void initFrom( const ModuleSystem::Descriptor& moduleDescriptor ) override;
private:
explicit PythonJobModule();
~PythonJobModule() override;
QString m_scriptFileName;
QString m_workingPath;
job_ptr m_job;
friend Module* Calamares::moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
};
} // namespace Calamares
#endif // CALAMARES_PYTHONJOBMODULE_H

View File

@@ -0,0 +1,61 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef CALAMARES_REQUIREMENT_H
#define CALAMARES_REQUIREMENT_H
#include "DllMacro.h"
#include <QList>
#include <QMetaType>
#include <QString>
#include <functional>
namespace Calamares
{
/**
* An indication of a requirement, which is checked in preparation
* for system installation. An entry has a name and some explanation functions
* (functions, because they need to respond to translations).
*
* A requirement can be *satisfied* or not.
* A requirement can be optional (i.e. a "good to have") or mandatory.
*
* Requirements which are not satisfied, and also mandatory, will prevent the
* installation from proceeding.
*/
struct RequirementEntry
{
using TextFunction = std::function< QString() >;
/// @brief name of this requirement; not shown to user and used as ID
QString name;
/// @brief Detailed description of this requirement, for use in user-visible lists
TextFunction enumerationText;
/// @brief User-visible string to show that the requirement is not met, short form
TextFunction negatedText;
bool satisfied;
bool mandatory;
/// @brief Convenience to check if this entry should be shown in details dialog
bool hasDetails() const { return !enumerationText().isEmpty(); }
};
using RequirementsList = QList< RequirementEntry >;
} // namespace Calamares
Q_DECLARE_METATYPE( Calamares::RequirementEntry )
#endif

View File

@@ -0,0 +1,73 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef CALAMARES_REQUIREMENTSCHECKER_H
#define CALAMARES_REQUIREMENTSCHECKER_H
#include "DllMacro.h"
#include "modulesystem/Requirement.h"
#include <QFutureWatcher>
#include <QObject>
#include <QTimer>
#include <QVector>
namespace Calamares
{
class Module;
class RequirementsModel;
/** @brief A manager-class that checks all the module requirements
*
* Asynchronously checks the requirements for each module, and
* emits progress signals as appropriate.
*/
class DLLEXPORT RequirementsChecker : public QObject
{
Q_OBJECT
public:
RequirementsChecker( QVector< Module* > modules, RequirementsModel* model, QObject* parent = nullptr );
~RequirementsChecker() override;
public Q_SLOTS:
/// @brief Start checking all the requirements
void run();
/// @brief Called when requirements are reported by a module
void addCheckedRequirements( Module* );
/// @brief Called when all requirements have been checked
void finished();
/// @brief Called periodically while requirements are being checked
void reportProgress();
signals:
/// @brief Human-readable progress message
void requirementsProgress( const QString& );
/// @brief Emitted after requirementsComplete
void done();
private:
QVector< Module* > m_modules;
using Watcher = QFutureWatcher< void >;
QVector< Watcher* > m_watchers;
RequirementsModel* m_model;
QTimer* m_progressTimer;
unsigned m_progressTimeouts;
};
} // namespace Calamares
#endif

View File

@@ -0,0 +1,100 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef CALAMARES_REQUIREMENTSMODEL_H
#define CALAMARES_REQUIREMENTSMODEL_H
#include "Requirement.h"
#include "DllMacro.h"
#include <QAbstractListModel>
#include <QMutex>
namespace Calamares
{
class RequirementsChecker;
/** @brief System requirements from each module and their checked-status
*
* A Calamares module can have system requirements (e.g. check for
* internet, or amount of RAM, or an available disk) which can
* be stated and checked.
*
* This model collects those requirements, can run the checks, and
* reports on the overall status of those checks.
*/
class DLLEXPORT RequirementsModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY( bool satisfiedRequirements READ satisfiedRequirements NOTIFY satisfiedRequirementsChanged FINAL )
Q_PROPERTY( bool satisfiedMandatory READ satisfiedMandatory NOTIFY satisfiedMandatoryChanged FINAL )
Q_PROPERTY( QString progressMessage READ progressMessage NOTIFY progressMessageChanged FINAL )
public:
using QAbstractListModel::QAbstractListModel;
enum Roles : short
{
NegatedText = Qt::DisplayRole,
Details = Qt::ToolTipRole,
Name = Qt::UserRole,
Satisfied,
Mandatory,
HasDetails
};
// No Q_ENUM because these are exposed through roleNames()
///@brief Are all the requirements satisfied?
bool satisfiedRequirements() const { return m_satisfiedRequirements; }
///@brief Are all the **mandatory** requirements satisfied?
bool satisfiedMandatory() const { return m_satisfiedMandatory; }
///@brief Message (from an ongoing check) about progress
QString progressMessage() const { return m_progressMessage; }
QVariant data( const QModelIndex& index, int role ) const override;
int rowCount( const QModelIndex& ) const override; // TODO 3.4 use qsizetype
int count() const { return static_cast< int >( m_requirements.count() ); } // TODO 3.4 use qsizetype
///@brief Debugging tool, describe the checking-state
void describe() const;
///@brief Update progress message (called by the checker)
void setProgressMessage( const QString& m );
///@brief Append some requirements; resets the model
void addRequirementsList( const Calamares::RequirementsList& requirements );
///@brief Check the whole list, emit signals satisfied...()
void reCheckList();
signals:
void satisfiedRequirementsChanged( bool value );
void satisfiedMandatoryChanged( bool value );
void progressMessageChanged( QString message );
protected:
QHash< int, QByteArray > roleNames() const override;
///@brief Clears the requirements; resets the model
void clear();
private:
QString m_progressMessage;
QMutex m_addLock;
RequirementsList m_requirements;
bool m_satisfiedRequirements = false;
bool m_satisfiedMandatory = false;
};
} // namespace Calamares
#endif

View File

@@ -0,0 +1,53 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CALAMARES_VIEWMODULE_H
#define CALAMARES_VIEWMODULE_H
#include "DllMacro.h"
#include "modulesystem/Module.h"
class QPluginLoader;
namespace Calamares
{
class ViewStep;
class UIDLLEXPORT ViewModule : public Module
{
public:
Type type() const override;
Interface interface() const override;
void loadSelf() override;
JobList jobs() const override;
RequirementsList checkRequirements() override;
protected:
void initFrom( const ModuleSystem::Descriptor& moduleDescriptor ) override;
private:
explicit ViewModule();
~ViewModule() override;
QPluginLoader* m_loader;
ViewStep* m_viewStep = nullptr;
friend Module* Calamares::moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor,
const QString& instanceId,
const QString& configFileName,
const QString& moduleDirectory );
};
} // namespace Calamares
#endif // CALAMARES_VIEWMODULE_H