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,167 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* 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 UTILS_COMMANDLIST_H
#define UTILS_COMMANDLIST_H
#include "DllMacro.h"
#include "Job.h"
#include <QStringList>
#include <QVariant>
#include <chrono>
#include <optional>
#include <utility>
class KMacroExpanderBase;
namespace Calamares
{
/**
* Each command can have an associated timeout in seconds. The timeout
* defaults to 10 seconds. Provide some convenience naming and construction.
*/
class DLLEXPORT CommandLine
{
public:
static inline constexpr std::chrono::seconds TimeoutNotSet() { return std::chrono::seconds( -1 ); }
/// An invalid command line
CommandLine() = default;
CommandLine( const QString& s )
: m_command( s )
{
}
CommandLine( const QString& s, std::chrono::seconds t )
: m_command( s )
, m_timeout( t )
{
}
CommandLine( const QString& s, const QStringList& env, std::chrono::seconds t )
: m_command( s )
, m_environment( env )
, m_timeout( t )
{
}
/** @brief Constructs a CommandLine from a map with keys
*
* Relevant keys are *command*, *environment* and *timeout*.
*/
CommandLine( const QVariantMap& m );
QString command() const { return m_command; }
[[nodiscard]] QStringList environment() const { return m_environment; }
std::chrono::seconds timeout() const { return m_timeout; }
bool isVerbose() const { return m_verbose.value_or( false ); }
bool isValid() const { return !m_command.isEmpty(); }
/** @brief Returns a copy of this one command, with variables expanded
*
* The given macro-expander is used to expand the command-line.
* This will normally be a Calamares::String::DictionaryExpander
* instance, which handles the ROOT and USER variables.
*/
DLLEXPORT CommandLine expand( KMacroExpanderBase& expander ) const;
/** @brief As above, with a default macro-expander.
*
* The default macro-expander assumes RunInHost (e.g. ROOT will
* expand to the RootMountPoint set in Global Storage).
*/
DLLEXPORT CommandLine expand() const;
/** @brief If nothing has set verbosity yet, update to @p verbose */
void updateVerbose( bool verbose )
{
if ( !m_verbose.has_value() )
{
m_verbose = verbose;
}
}
/** @brief Unconditionally set verbosity (can also reset it to nullopt) */
void setVerbose( std::optional< bool > v ) { m_verbose = v; }
private:
QString m_command;
QStringList m_environment;
std::chrono::seconds m_timeout = TimeoutNotSet();
std::optional< bool > m_verbose;
};
/** @brief Abbreviation, used internally. */
using CommandList_t = QList< CommandLine >;
/**
* A list of commands; the list may have its own default timeout
* for commands (which is then applied to each individual command
* that doesn't have one of its own).
*
* Documentation for the format of commands can be found in
* `shellprocess.conf`.
*/
class DLLEXPORT CommandList : protected CommandList_t
{
public:
/** @brief empty command-list with timeout to apply to entries. */
CommandList( bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) );
/** @brief command-list constructed from script-entries in @p v
*
* The global settings @p doChroot and @p timeout can be overridden by
* the individual script-entries.
*/
CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) );
CommandList( int ) = delete;
CommandList( const QVariant&, int ) = delete;
bool doChroot() const { return m_doChroot; }
std::chrono::seconds defaultTimeout() const { return m_timeout; }
Calamares::JobResult run();
using CommandList_t::at;
using CommandList_t::cbegin;
using CommandList_t::cend;
using CommandList_t::const_iterator;
using CommandList_t::count;
using CommandList_t::isEmpty;
using CommandList_t::push_back;
using CommandList_t::value_type;
/** @brief Return a copy of this command-list, with variables expanded
*
* Each command-line in the list is expanded with the given @p expander.
* @see CommandLine::expand() for details.
*/
DLLEXPORT CommandList expand( KMacroExpanderBase& expander ) const;
/** @brief As above, with a default macro-expander.
*
* Each command-line in the list is expanded with that default macro-expander.
* @see CommandLine::expand() for details.
*/
DLLEXPORT CommandList expand() const;
/** @brief Applies default-value @p verbose to each entry without an explicit setting. */
DLLEXPORT void updateVerbose( bool verbose );
private:
bool m_doChroot;
std::chrono::seconds m_timeout;
};
} // namespace Calamares
#endif

View File

@@ -0,0 +1,61 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2013-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Originally from Tomahawk, portions:
* SPDX-FileCopyrightText: 2010-2011 Christian Muehlhaeuser <muesli@tomahawk-player.org>
* SPDX-FileCopyrightText: 2010-2011 Leo Franchi <lfranchi@kde.org>
* SPDX-FileCopyrightText: 2010-2012 Jeff Mitchell <jeff@tomahawk-player.org>
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef UTILS_DIRS_H
#define UTILS_DIRS_H
#include "DllMacro.h"
#include <QDir>
namespace Calamares
{
/**
* @brief appDataDir returns the directory with common application data.
* Defaults to CMAKE_INSTALL_FULL_DATADIR (usually /usr/share/calamares).
*/
DLLEXPORT QDir appDataDir();
/**
* @brief appLogDir returns the directory for Calamares logs.
* Defaults to QStandardPaths::CacheLocation (usually ~/.cache/Calamares).
*/
DLLEXPORT QDir appLogDir();
/**
* @brief systemLibDir returns the system's lib directory.
* Defaults to CMAKE_INSTALL_FULL_LIBDIR (usually /usr/lib64 or /usr/lib).
*/
DLLEXPORT QDir systemLibDir();
/**
* Override app data dir. Only for testing purposes.
*/
DLLEXPORT void setAppDataDir( const QDir& dir );
DLLEXPORT bool isAppDataDirOverridden();
/** @brief Setup extra config and data dirs from the XDG variables.
*/
DLLEXPORT void setXdgDirs();
/** @brief Are any extra directories configured? */
DLLEXPORT bool haveExtraDirs();
/** @brief XDG_CONFIG_DIRS, each guaranteed to end with / */
DLLEXPORT QStringList extraConfigDirs();
/** @brief XDG_DATA_DIRS, each guaranteed to end with / */
DLLEXPORT QStringList extraDataDirs();
} // namespace Calamares
#endif

View File

@@ -0,0 +1,46 @@
/* === 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 UTILS_ENTROPY_H
#define UTILS_ENTROPY_H
#include "DllMacro.h"
#include <QByteArray>
namespace Calamares
{
/// @brief Which entropy source was actually used for the entropy.
enum class EntropySource
{
None, ///< Buffer is empty, no random data
URandom, ///< Read from /dev/urandom
Twister ///< Generated by pseudo-random
};
/** @brief Fill buffer @p b with exactly @p size random bytes
*
* The array is cleared and resized, then filled with 0xcb
* "just in case", after which it is filled with random
* bytes from a suitable source. Returns which source was used.
*/
DLLEXPORT EntropySource getEntropy( int size, QByteArray& b );
/** @brief Fill string @p s with exactly @p size random printable ASCII characters
*
* The characters are picked from a set of 64 (2^6). The string
* contains 6 * size bits of entropy. * Returns which source was used.
* @see getEntropy
*/
DLLEXPORT EntropySource getPrintableEntropy( int size, QString& s );
} // namespace Calamares
#endif

View File

@@ -0,0 +1,102 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-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 CALAMARESUTILSGUI_H
#define CALAMARESUTILSGUI_H
#include "DllMacro.h"
#include <QObject>
#include <QPixmap>
#include <QSize>
class QLayout;
namespace Calamares
{
/**
* @brief The ImageType enum lists all common Calamares icons.
* Icons are loaded from SVGs and cached. Each icon has an enum value, through which
* it can be accessed.
* You can forward-declare this as:
* enum ImageType : int;
*/
enum ImageType : int
{
Yes,
No,
Information,
Fail,
Bugs,
Help,
Release,
Donate,
PartitionDisk,
PartitionPartition,
PartitionAlongside,
PartitionEraseAuto,
PartitionManual,
PartitionReplaceOs,
PartitionTable,
BootEnvironment,
Squid,
StatusOk, // Icons for the requirements checker
StatusWarning,
StatusError
};
/**
* @brief The ImageMode enum contains different transformations that can be applied.
* Most of these are currently unused.
*/
enum ImageMode
{
Original,
CoverInCase,
Grid,
DropShadow,
};
/**
* @brief defaultPixmap returns a resized and/or transformed pixmap for a given
* ImageType.
* @param type the ImageType i.e. the enum value for an SVG.
* @param mode the transformation to apply (default: no transformation).
* @param size the target pixmap size (default: original SVG size).
* @return the new pixmap.
*/
UIDLLEXPORT QPixmap defaultPixmap( ImageType type,
ImageMode mode = Calamares::Original,
const QSize& size = QSize( 0, 0 ) );
/**
* @brief unmarginLayout recursively walks the QLayout tree and removes all margins.
* @param layout the layout to unmargin.
*/
UIDLLEXPORT void unmarginLayout( QLayout* layout );
UIDLLEXPORT void setDefaultFontSize( int points );
UIDLLEXPORT int defaultFontSize(); // in points
UIDLLEXPORT int defaultFontHeight(); // in pixels, DPI-specific
UIDLLEXPORT QFont largeFont();
UIDLLEXPORT QSize defaultIconSize();
/**
* @brief Size constants for the main Calamares window.
*/
constexpr int windowMinimumWidth = 800;
constexpr int windowMinimumHeight = 520;
constexpr int windowPreferredWidth = 1024;
constexpr int windowPreferredHeight = 520;
} // namespace Calamares
#endif // CALAMARESUTILSGUI_H

View File

@@ -0,0 +1,32 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2012 Christian Muehlhaeuser <muesli@tomahawk-player.org>
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#ifndef IMAGE_REGISTRY_H
#define IMAGE_REGISTRY_H
#include <QPixmap>
#include "DllMacro.h"
#include "utils/Gui.h"
class UIDLLEXPORT ImageRegistry
{
public:
static ImageRegistry* instance();
explicit ImageRegistry();
QIcon icon( const QString& image, Calamares::ImageMode mode = Calamares::Original );
QPixmap pixmap( const QString& image, const QSize& size, Calamares::ImageMode mode = Calamares::Original );
private:
qint64 cacheKey( const QSize& size );
void putInCache( const QString& image, const QSize& size, Calamares::ImageMode mode, const QPixmap& pixmap );
};
#endif // IMAGE_REGISTRY_H

View File

@@ -0,0 +1,404 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2010-2011 Christian Muehlhaeuser <muesli@tomahawk-player.org>
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-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 UTILS_LOGGER_H
#define UTILS_LOGGER_H
#include "DllMacro.h"
#include <QDebug>
#include <QSharedPointer>
#include <QVariant>
#include <memory>
namespace Logger
{
class Once;
struct FuncSuppressor
{
explicit constexpr FuncSuppressor( const char[] );
const char* m_s;
};
struct NoQuote_t
{
};
struct Quote_t
{
};
DLLEXPORT extern const FuncSuppressor Continuation;
DLLEXPORT extern const FuncSuppressor SubEntry;
DLLEXPORT extern const NoQuote_t NoQuote;
DLLEXPORT extern const Quote_t Quote;
enum
{
LOG_DISABLE = 0,
LOGERROR = 1,
LOGWARNING = 2,
LOGDEBUG = 6,
LOGVERBOSE = 8
};
class DLLEXPORT CDebug : public QDebug
{
public:
explicit CDebug( unsigned int debugLevel = LOGDEBUG, const char* func = nullptr );
virtual ~CDebug();
friend CDebug& operator<<( CDebug&&, const FuncSuppressor& );
friend CDebug& operator<<( CDebug&&, const Once& );
inline unsigned int level() const { return m_debugLevel; }
private:
QString m_msg;
unsigned int m_debugLevel;
const char* m_funcinfo = nullptr;
};
inline CDebug&
operator<<( CDebug&& s, const FuncSuppressor& f )
{
if ( s.m_funcinfo )
{
s.m_funcinfo = nullptr;
s.m_msg = QString( f.m_s );
}
return s;
}
inline QDebug&
operator<<( QDebug& s, const FuncSuppressor& f )
{
return s << f.m_s;
}
inline QDebug&
operator<<( QDebug& s, const NoQuote_t& )
{
return s.noquote().nospace();
}
inline QDebug&
operator<<( QDebug& s, const Quote_t& )
{
return s.quote().space();
}
/**
* @brief The full path of the log file.
*/
DLLEXPORT QString logFile();
/**
* @brief Start logging to the log file.
*
* Call this (once) to start logging to the log file (usually
* ~/.cache/calamares/session.log ). An existing log file is
* rolled over if it is too large.
*/
DLLEXPORT void setupLogfile();
/**
* @brief Set a log level for future logging.
*
* Pass in a value from the LOG* enum, above. Use 0 to
* disable logging. Values greater than LOGVERBOSE are
* limited to LOGVERBOSE, which will log everything.
*
* Practical values are 0, 1, 2, and 6.
*/
DLLEXPORT void setupLogLevel( unsigned int level );
/** @brief Return the configured log-level. */
DLLEXPORT unsigned int logLevel();
/** @brief Would the given @p level really be logged? */
DLLEXPORT bool logLevelEnabled( unsigned int level );
/**
* @brief Row-oriented formatted logging.
*
* Use DebugRow to produce multiple rows of 2-column output
* in a debugging statement. For instance,
* cDebug() << DebugRow<int,int>(1,12)
* << DebugRow<int,int>(2,24)
* will produce a single timestamped debug line with continuations.
* Each DebugRow produces one line of output, with the two values.
*/
template < typename T, typename U >
struct DebugRow
{
public:
explicit DebugRow( const T& t, const U& u )
: first( t )
, second( u )
{
}
const T first;
const U second;
};
/**
* @brief List-oriented formatted logging.
*
* Use DebugList to produce multiple rows of output in a debugging
* statement. For instance,
* cDebug() << DebugList( QStringList() << "foo" << "bar" )
* will produce a single timestamped debug line with continuations.
* Each element of the list of strings will be logged on a separate line.
*/
/* TODO: Calamares 3.3, bump requirements to C++17, and rename
* this to DebugList, dropping the convenience-definition
* below. In C++17, class template argument deduction is
* added, so `DebugList( whatever )` determines the right
* type already (also for QStringList).
*/
template < typename T >
struct DebugListT
{
using list_t = QList< T >;
explicit DebugListT( const list_t& l )
: list( l )
{
}
const list_t& list;
};
///@brief Convenience for QStringList, needs no template parameters
struct DebugList : public DebugListT< QString >
{
explicit DebugList( const list_t& l )
: DebugListT( l )
{
}
};
/**
* @brief Map-oriented formatted logging.
*
* Use DebugMap to produce multiple rows of output in a debugging
* statement from a map. The output is intentionally a bit-yaml-ish.
* cDebug() << DebugMap( map )
* will produce a single timestamped debug line with continuations.
* The continued lines will have a key (from the map) and a value
* on each line.
*/
struct DebugMap
{
public:
explicit DebugMap( const QVariantMap& m )
: map( m )
{
}
const QVariantMap& map;
};
/** @brief When logging commands, don't log everything.
*
* The command-line arguments to some commands may contain the
* encrypted password set by the user. Don't log that password,
* since the log may get posted to bug reports, or stored in
* the target system.
*/
struct RedactedCommand
{
RedactedCommand( const QStringList& l )
: list( l )
{
}
const QStringList& list;
};
DLLEXPORT QDebug& operator<<( QDebug& s, const RedactedCommand& l );
/** @brief When logging "private" identifiers, keep them consistent but private
*
* Send a string to a logger in such a way that each time it is logged,
* it logs the same way, but without revealing the actual contents.
* This can be applied to user names, UUIDs, etc.
*/
struct DLLEXPORT RedactedName
{
RedactedName( const char* context, const QString& s );
RedactedName( const QString& context, const QString& s );
operator QString() const;
private:
const uint m_id;
const QString m_context;
};
inline QDebug&
operator<<( QDebug& s, const RedactedName& n )
{
return s << NoQuote << QString( n ) << Quote;
}
/**
* @brief Formatted logging of a pointer
*
* Pointers are printed as void-pointer, so just an address (unlike, say,
* QObject pointers which show an address and some metadata) preceded
* by an '@'. This avoids C-style (void*) casts in the code.
*
* Shared pointers are indicated by 'S@' and unique pointers by 'U@'.
*/
struct Pointer
{
public:
explicit Pointer( const void* p )
: ptr( p )
, kind( 0 )
{
}
template < typename T >
explicit Pointer( const std::shared_ptr< T >& p )
: ptr( p.get() )
, kind( 'S' )
{
}
template < typename T >
explicit Pointer( const std::unique_ptr< T >& p )
: ptr( p.get() )
, kind( 'U' )
{
}
const void* const ptr;
const char kind;
};
/** @brief output operator for DebugRow */
template < typename T, typename U >
inline QDebug&
operator<<( QDebug& s, const DebugRow< T, U >& t )
{
s << Continuation << t.first << ':' << ' ' << t.second;
return s;
}
/** @brief output operator for DebugList, assuming operator<< for T exists */
template < typename T = QString >
inline QDebug&
operator<<( QDebug& s, const DebugListT< T >& c )
{
for ( const auto& i : c.list )
{
s << Continuation << i;
}
return s;
}
/** @brief supporting method for outputting a DebugMap */
DLLEXPORT QString toString( const QVariant& v );
/** @brief output operator for DebugMap */
inline QDebug&
operator<<( QDebug& s, const DebugMap& t )
{
for ( auto it = t.map.constBegin(); it != t.map.constEnd(); ++it )
{
s << Continuation << it.key().toUtf8().constData() << ':' << ' ' << toString( it.value() ).toUtf8().constData();
}
return s;
}
inline QDebug&
operator<<( QDebug& s, const Pointer& p )
{
s << NoQuote;
if ( p.kind )
{
s << p.kind;
}
s << '@' << p.ptr << Quote;
return s;
}
/** @brief Convenience object for supplying SubEntry to a debug stream
*
* In a function with convoluted control paths, it may be unclear
* when to supply SubEntry to a debug stream -- it is convenient
* for the **first** debug statement from a given function to print
* the function header, and all subsequent onces to get SubEntry.
*
* Create an object of type Once and send it (first) to all CDebug
* objects; this will print the function header only once within the
* lifetime of that Once object.
*/
class Once
{
public:
Once()
: m( true )
{
}
friend CDebug& operator<<( CDebug&&, const Once& );
/** @brief Restore the object to "fresh" state
*
* It may be necessary to allow the Once object to stream the
* function header again -- for instance, after logging an error,
* any following debug log might want to re-introduce the header.
*/
void refresh() { m = true; }
/** @brief Is this object "fresh"?
*
* Once a Once-object has printed (once) it is no longer fresh.
*/
operator bool() const { return m; }
private:
mutable bool m = false;
};
inline CDebug&
operator<<( CDebug&& s, const Once& o )
{
if ( !logLevelEnabled( s.level() ) )
{
// This won't print, so it's not using the "onceness"
return s;
}
if ( o.m )
{
o.m = false;
return s;
}
s.m_funcinfo = nullptr;
s << SubEntry;
return s;
}
} // namespace Logger
#define cVerbose() Logger::CDebug( Logger::LOGVERBOSE, Q_FUNC_INFO )
#define cDebug() Logger::CDebug( Logger::LOGDEBUG, Q_FUNC_INFO )
#define cWarning() Logger::CDebug( Logger::LOGWARNING, Q_FUNC_INFO )
#define cError() Logger::CDebug( Logger::LOGERROR, Q_FUNC_INFO )
#endif

View File

@@ -0,0 +1,263 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2019 Collabora Ltd <arnaud.ferraris@collabora.com>
* 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.
*
*
*/
/** @brief Support for "named" enumerations
*
* When a string needs to be one specific string out of a set of
* alternatives -- one "name" from an enumerated set -- then it
* is useful to have an **enum type** for the enumeration so that
* C++ code can work with the (strong) type of the enum, while
* the string can be used for human-readable interaction.
* The `NamedEnumTable<E>` template provides support for naming
* values of an enum.
*/
#ifndef UTILS_NAMEDENUM_H
#define UTILS_NAMEDENUM_H
#include <QString>
#include <initializer_list>
#include <type_traits>
#include <vector>
/** @brief Type for collecting parts of a named enum.
*
* The `NamedEnumTable<E>` template provides support for naming
* values of an enum. It supports mapping strings to enum values
* and mapping enum values to strings.
*
* ## Example
*
* Suppose we have code where there are three alternatives; it is
* useful to have a strong type to make the alternatives visible
* in that code, so the compiler can help check:
*
* ```
* enum class MilkshakeSize { None, Small, Large };
* ```
*
* In a switch() statement, the compiler will check that all kinds
* of milkshakes are dealt with; we can pass a MilkshakeSize to
* a function and rest assured that nobody will call that function
* with a silly value, like `1`.
*
* There is no relation between the C++ identifiers used, and
* any I/O related to that enumeration. In other words,
*
* ```
* std::cout << MilkshakeSize::Small;
* ```
*
* Will **not** print out "Small", or "small", or 1. It won't even
* compile, because there is no mapping of the enum values to
* something that can be output.
*
* By making a `NamedEnumTable<MilkshakeSize>` we can define a mapping
* between strings (names) and enum values, so that we can easily
* output the human-readable name, and also take string input
* and convert it to an enum value. Suppose we have a function
* `milkshakeSizeNames()` that returns a reference to such a table,
* then we can use `find()` to map enums-to-names and names-to-enums.
*
* ```
* const auto& names = milkshakeSizeNames();
* MilkshakeSize sz{ MilkshakeSize::Large };
* std::cout << names.find(sz); // Probably "large"
*
* bool ok;
* sz = names.find( "small", ok ); // Probably MilkshakeSize::Small
* ```
*
* ## Usage
*
* It is recommended to use a static const declaration for the table;
* typical use will define a function that returns a reference to
* the table, for shared use.
*
* The constructor for a table takes an initializer_list; each element
* of the initializer_list is a **pair** consisting of a name and
* an associated enum value. The names should be QStrings. For each enum
* value that is listed, the canonical name should come **first** in the
* table, so that printing the enum values gives the canonical result.
*
* ```
* static const NamedEnumTable<MilkshakeSize>& milkshakeSizeNames()
* {
* static NamedEnumTable<MilkshakeSize> n { // Initializer list for n
* { "large", MilkshakeSize::Large }, // One pair of name-and-value
* { "small", MilkshakeSize::Small },
* { "big", MilkshakeSize::Large }
* };
* return n;
* }
* ```
*
* The function `eNames()`, above, returns a reference to a name table
* for the enum (presumably an enum class) `E`. It is possible to have
* more than one table for an enum, or to make the table locally,
* but **usually** you want one definitive table of names and values.
* The `eNames()` function gives you that definitive table. In Calamres
* code, such functions are usually named after the underlying enum.
*
* Using this particular table, looking up "large" will return `MilkshakeSize::Large`,
* looking up "big" will **also** return `MilkshakeSize::Large`, looking up "derp"
* will return `MilkshakeSize::Large` (because that is the first value in the table)
* but will set the boolean `ok` parameter to false. Conversely, looking
* up `MilkshakeSize::Large` will return "large" (never "big").
*
* Note that this particular table does **not** name MilkshakeSize::None,
* so it is probably wrong: you can't get a string for that enum
* value, and no string will map to MilkshakeSize::None either.
* In general, tables should cover all of the enum values.
*
* Passing an empty initializer_list to the constructor is supported,
* but will cause UB if the table is ever used for looking up a string.
*
*/
template < typename T >
struct NamedEnumTable
{
using string_t = QString;
using enum_t = T;
using pair_t = std::pair< string_t, enum_t >;
using type = std::vector< pair_t >;
type table;
/** @brief Create a table of named enum values.
*
* Use braced-initialisation for NamedEnum, and remember that the
* elements of the list are **pairs**, e.g.
*
* ```
* static const NamedEnumTable<Colors> c{ {"red", Colors::Red } };
* ```
*/
NamedEnumTable( const std::initializer_list< pair_t >& v )
: table( v )
{
/* static_assert( v.size() > 0 ); */
}
/** @brief Find a name @p s in the table.
*
* Searches case-insensitively.
*
* If the name @p s is not found, @p ok is set to @c false and
* the first enum value in the table is returned. Otherwise,
* @p ok is set to @c true and the corresponding value is returned.
* Use the output value of @p ok to determine if the lookup was
* successful: there is otherwise no sensible way to distinguish
* found-the-name-of-the-first-item from not-found.
*/
enum_t find( const string_t& s, bool& ok ) const
{
ok = false;
for ( const auto& p : table )
{
if ( 0 == QString::compare( s, p.first, Qt::CaseInsensitive ) )
{
ok = true;
return p.second;
}
}
// ok is still false
return table.begin()->second;
}
/** @brief Find a name @p s in the table.
*
* Searches case-insensitively.
*
* If the name @p s is not found, the value @p d is returned as
* a default. Otherwise the value corresponding to @p s is returned.
* This is a shortcut over find() using a bool to distinguish
* successful and unsuccesful lookups.
*/
enum_t find( const string_t& s, enum_t d ) const
{
bool ok = false;
enum_t e = find( s, ok );
return ok ? e : d;
}
/** @brief Find a value @p s in the table and return its name.
*
* If @p s is an enum value in the table, return the corresponding
* name (the first name with that value, if there are aliases)
* and set @p ok to @c true.
*
* If the value @p s is not found, @p ok is set to @c false and
* an empty string is returned. This indicates that the table does
* not cover all of the values * in `enum_t` (and @p s is one
* of them), **or** that the passed-in value of @p s is
* not a legal value, e.g. via a static_cast<enum_t>.
*/
string_t find( enum_t s, bool& ok ) const
{
ok = false;
for ( const auto& p : table )
{
if ( s == p.second )
{
ok = true;
return p.first;
}
}
// ok is still false
return string_t();
}
/** @brief Find a value @p s in the table and return its name.
*
* Returns an empty string if the value @p s is not found (this
* indicates that the table does not cover all of the values
* in `enum_t`, **or** that the passed-in value of @p s is
* not a legal value, e.g. via a static_cast<enum_t>).
*/
string_t find( enum_t s ) const
{
bool ok = false;
return find( s, ok );
}
};
/** @brief Smashes an enum value to its underlying type.
*
* While an enum **class** is not an integral type, and its values can't be
* printed or treated like an integer (like an old-style enum can),
* the underlying type **is** integral. This template function
* returns the value of an enum value, in its underlying type.
* This can be useful for debugging purposes, e.g.
*
* ```
* MilkshakeSize sz{ MilkshakeSize::None };
* std::cout << milkshakeSizeNames().find( sz ) << smash( sz );
* ```
*
* This will print both the name and the underlying integer for the
* value; assuming the table from the example is used, there is
* no name for MilkshakeSize::None, so it will print an empty string,
* followed by the integral representation -- probably a 0.
*/
template < typename E >
constexpr typename std::underlying_type< E >::type
smash( const E e )
{
return static_cast< typename std::underlying_type< E >::type >( e );
}
#endif

View File

@@ -0,0 +1,100 @@
/* === 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.
*
*
*/
/** @brief Support for unit-suffixed values.
*
* This combines a value with an (enum) unit indicating what kind
* of value it is, e.g. 10 meters, or 64 pixels. Includes simple
* parsing support for the values written as strings like <value><unit>,
* e.g. "10m" or "64px".
*
* When a suffixed unit value needs validation, define an isValid()
* method; similarly for simple construction from a string (with a fixed
* table of suffixes). Typical use then looks like:
*
* class MyUnit : public NamedSuffix<MyUnitEnum, MyUnitEnum::None>
* {
* public:
* using NamedSuffix::NamedSuffix; // Keep existing constructors
* MyUnit( const QString& s );
* bool isValid() const;
* } ;
*/
#ifndef UTILS_NAMEDSUFFIX_H
#define UTILS_NAMEDSUFFIX_H
#include "NamedEnum.h"
/** @brief Template that takes the enum type to work with and a special none-enum. */
template < typename T, T _none >
class NamedSuffix
{
public:
using unit_t = T;
static constexpr unit_t none = _none;
/** @brief Empty value. */
NamedSuffix()
: m_value( 0 )
, m_unit( none )
{
}
/** @brief Specific value and unit. */
NamedSuffix( qint64 value, unit_t unit )
: m_value( value )
, m_unit( unit )
{
}
/** @brief Construct value and unit from string.
*
* This parses the given string @p s by comparing with the suffixes
* in @p table and uses the first matching suffix as the unit.
*/
NamedSuffix( const NamedEnumTable< T >& table, const QString& s )
: NamedSuffix()
{
for ( const auto& suffix : table.table )
{
if ( s.endsWith( suffix.first ) )
{
m_value = s.left( s.length() - suffix.first.length() ).toLongLong();
m_unit = suffix.second;
break;
}
}
}
/** @brief Construct value from string.
*
* This is not defined in the template, because it should probably
* delegate to the constructor above with a fixed table.
*/
NamedSuffix( const QString& s );
qint64 value() const { return m_value; }
unit_t unit() const { return m_unit; }
/** @brief Check that a value-unit combination is valid.
*
* This is not defined in the template, because validity (e.g.
* range of acceptable values) depends on the kind of unit.
*/
bool isValid() const;
protected:
qint64 m_value;
unit_t m_unit;
};
#endif

View File

@@ -0,0 +1,46 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2019 Bill Auger
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef UTILS_PASTE_H
#define UTILS_PASTE_H
#include "DllMacro.h"
#include <QString>
class QObject;
class QWidget;
namespace Calamares
{
namespace Paste
{
/** @brief Send the current log file to a pastebin
*
* Returns the (string) URL that the pastebin gives us.
*/
UIDLLEXPORT QString doLogUpload( QObject* parent );
/** @brief Send the current log file to a pastebin
*
* As doLogUpload(), but also sets the clipboard and displays
* a message saying it's been done.
*/
UIDLLEXPORT QString doLogUploadUI( QWidget* parent );
/** @brief Is paste enabled?
*
* Checks the branding instance if paste can be done.
*/
UIDLLEXPORT bool isEnabled();
} // namespace Paste
} // namespace Calamares
#endif

View File

@@ -0,0 +1,113 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2018 Scott Harvey <scott@spharvey.me>
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#ifndef LIBCALAMARES_PERMISSIONS_H
#define LIBCALAMARES_PERMISSIONS_H
#include "DllMacro.h"
#include <QString>
namespace Calamares
{
/**
* @brief Represents a <user>:<group>:<file-mode>
*
* The Permissions class takes a QString @p in the form of
* <user>:<group>:<file-mode>, checks it for validity, and makes the three
* components available indivdually.
*/
class DLLEXPORT Permissions
{
public:
/** @brief Constructor
*
* Splits the string @p at the colon (":") into separate elements for
* <user>, <group>, and <file-mode> (permissions), where <file-mode> is any
* value that can be parsed by parseFileMode() . One valid form
* is an **octal** integer. That is, "root:wheel:755" will give
* you an integer value of four-hundred-ninety-three (493),
* corresponding to the UNIX file permissions rwxr-xr-x,
* as one would expect from chmod and other command-line utilities.
*/
Permissions( QString const& p );
/// @brief Default constructor of an invalid Permissions.
Permissions();
/// @brief Was the Permissions object constructed from valid data?
bool isValid() const { return m_valid; }
/// @brief The user (first component, e.g. "root" in "root:wheel:755")
QString username() const { return m_username; }
/// @brief The group (second component, e.g. "wheel" in "root:wheel:755")
QString group() const { return m_group; }
/** @brief The value (file permission) as an integer.
*
* Bear in mind that input is in octal, but integers are just integers;
* naively printing them will get decimal results (e.g. 493 from the
* input of "root:wheel:755"). This is suitable to pass to apply().
*/
int value() const { return m_value; }
/** @brief The value (file permission) as octal string
*
* This is suitable for passing to chmod-the-program, or for
* recreating the original Permissions string.
*/
QString octal() const { return QString::number( value(), 8 ); }
/** @brief Sets the file-access @p mode of @p path
*
* Pass a path that is relative (or absolute) in the **host** system.
*
* @return @c true on success
*/
static bool apply( const QString& path, int mode );
/** @brief Do both chmod and chown on @p path
*
* Note that interpreting user- and group- names for applying the
* permissions can be different between the host system and the target
* system; the target might not have a "live" user, for instance, and
* the host won't have the user-entered username for the installation.
*
* For this call, the names are interpreted in the **host** system.
* Pass a path that is relative (or absolute) in the **host** system.
*
* @return @c true on success of **both** operations
*/
static bool apply( const QString& path, const Permissions& p );
/// Convenience method for apply(const QString&, const Permissions& )
bool apply( const QString& path ) const { return apply( path, *this ); }
private:
void parsePermissions( QString const& p );
QString m_username;
QString m_group;
int m_value;
bool m_valid;
};
/**
* @brief Parses a file-mode and returns it as an integer
*
* Returns -1 on error.
*
* Valid forms of @p mode are:
* - octal representation, with an optional leading 0 and at most three
* octal digits (e.g. 0755 or 644).
* - octal representation with a leading 'o' (letter) and at most three
* octal digits (e.g. o755 or o644). Use this in YAML where a string
* of digits would otherwise be interpreted as a (base-10) integer.
* - "rwx" representation with exactly 9 characters like the output of ls.
*/
DLLEXPORT int parseFileMode( const QString& mode );
} // namespace Calamares
#endif // LIBCALAMARES_PERMISSIONS_H

View File

@@ -0,0 +1,113 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-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 UTILS_PLUGINFACTORY_H
#define UTILS_PLUGINFACTORY_H
#include "DllMacro.h"
#include <QObject>
#define CalamaresPluginFactory_iid "io.calamares.PluginFactory"
/** @brief Plugin factory for Calamares
*
* A Calamares plugin contains just one kind of plugin -- either
* a job, or a viewstep -- so the factory is straightforward.
* It gets a single CreateInstanceFunction and calls that;
* the function is set when registerPlugin() is called in a subclass.
*
*/
class DLLEXPORT CalamaresPluginFactory : public QObject
{
Q_OBJECT
public:
explicit CalamaresPluginFactory() {}
~CalamaresPluginFactory() override;
typedef QObject* ( *CreateInstanceFunction )( QObject* );
template < class T >
T* create( QObject* parent = nullptr )
{
auto* op = fn ? fn( parent ) : nullptr;
if ( !op )
{
return nullptr;
}
T* tp = qobject_cast< T* >( op );
if ( !tp )
{
delete op;
}
return tp;
}
protected:
CreateInstanceFunction fn = nullptr;
};
/** @brief declare a Calamares Plugin Factory
*
* There should be one declaration -- generally alongside the
* class definition for the Job or ViewStep that the plugin is
* going to provide, in the header -- and one definition -- in
* the corresponding implementation.
*/
#define CALAMARES_PLUGIN_FACTORY_DECLARATION( name ) \
class name : public CalamaresPluginFactory \
{ \
Q_OBJECT \
Q_INTERFACES( CalamaresPluginFactory ) \
Q_PLUGIN_METADATA( IID CalamaresPluginFactory_iid ) \
public: \
explicit name(); \
~name() override; \
template < class T > \
static QObject* createInstance( QObject* parent ) \
{ \
return new T( parent ); \
} \
template < class T > \
void registerPlugin() \
{ \
fn = createInstance< T >; \
} \
};
/** @brief Define a Calamares Plugin Factory
*
* This should be done exactly once, generally in the translation
* unit containing the definitions for the main class of the plugin,
* either the Job or the ViewStep definitions.
*
* The @p name must match the name used in the declaration, while
* @p pluginRegistrations should be a single call to `registerPlugin<T>()`
* where `T` is the type (subclass of Job or ViewStep) defined by the
* plugin, eg.
*
* ```
* CALAMARES_PLUGIN_FACTORY_DEFINITION( MyPlugin, registerPlugin<MyPluginJob>() )
* ```
*
* Leaving out the `()` will lead to generally-weird compiler warnings.
*/
#define CALAMARES_PLUGIN_FACTORY_DEFINITION( name, pluginRegistrations ) \
name::name() \
: CalamaresPluginFactory() \
{ \
pluginRegistrations; \
} \
name::~name() {}
Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid )
#endif

View File

@@ -0,0 +1,90 @@
/* === 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 UTILS_QML_H
#define UTILS_QML_H
#include "DllMacro.h"
#include "modulesystem/InstanceKey.h"
#include "utils/NamedEnum.h"
#include <QDir>
class QQuickItem;
namespace Calamares
{
/// @brief the extra directory where Calamares searches for QML files
UIDLLEXPORT QDir qmlModulesDir();
/// @brief sets specific directory for searching for QML files
UIDLLEXPORT void setQmlModulesDir( const QDir& dir );
/** @brief initialize QML search path with branding directories
*
* Picks a suitable branding directory (from the build-dir in debug mode,
* otherwise based on the branding directory) and adds it to the
* QML modules directory; returns @c false if none is found.
*/
UIDLLEXPORT bool initQmlModulesDir();
/** @brief Sets up global Calamares models for QML
*
* This needs to be called at least once to make the global Calamares
* models (Branding, ViewManager, ...) available to QML.
*
* The following objects are made available globally:
* - `io.calamares.ui.Branding` (an object, see Branding.h)
* - `io.calamares.core.ViewManager` (a model, see ViewManager.h)
* - `io.calamares.core.Global` (an object, see GlobalStorage.h)
* Additionally, modules based on QmlViewStep have a context
* property `config` referring to that module's configuration (if any).
*/
UIDLLEXPORT void registerQmlModels();
/** @brief Calls the QML method @p method on @p qmlObject
*
* Pass in only the name of the method (e.g. onActivate). This function
* checks if the method exists (with no arguments) before trying to
* call it, so that no warnings are printed due to missing methods.
*
* If there is a return value from the QML method, it is logged (but not otherwise used).
*/
UIDLLEXPORT void callQmlFunction( QQuickItem* qmlObject, const char* method );
/** @brief Search modes for loading Qml files.
*
* A QML file could be compiled into QRC, or it could live
* in the branding directory (and, in debug-runs, in
* the current-directory). Modules have some control
* over where the search is done.
*/
enum class QmlSearch
{
QrcOnly,
BrandingOnly,
Both
};
/// @brief Names for the search terms (in config files)
UIDLLEXPORT const NamedEnumTable< QmlSearch >& qmlSearchNames();
/** @brief Find a suitable QML file, given the search method and name hints
*
* Returns QString() if nothing is found (which would mean the module
* is badly configured).
*/
UIDLLEXPORT QString searchQmlFile( QmlSearch method,
const QString& configuredName,
const Calamares::ModuleSystem::InstanceKey& i );
UIDLLEXPORT QString searchQmlFile( QmlSearch method, const QString& fileNameNoSuffix );
} // namespace Calamares
#endif

View File

@@ -0,0 +1,30 @@
/* === 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.
*
*/
/**@file Handle compatibility and deprecations across Qt versions
*
* Since Calamares is supposed to work with Qt 5.15 or Qt 6 or later, it
* covers a lot of changes in the Qt API.
*
* This file adjusts for that by introducing suitable aliases
* and workaround-functions.
*
* For a similar approach for QtCore, see libcalamares/utils/String.h
*/
#ifndef UTILS_QTCOMPAT_H
#define UTILS_QTCOMPAT_H
#include <QPalette>
/* Avoid warnings about QPalette changes */
constexpr static const auto WindowBackground = QPalette::Window;
constexpr static const auto WindowText = QPalette::WindowText;
#endif

View File

@@ -0,0 +1,112 @@
/* === 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 UTILS_RAII_H
#define UTILS_RAII_H
#include <QObject>
#include <QSignalBlocker>
#include <optional>
#include <type_traits>
/** @brief Convenience to zero out and deleteLater of any QObject-derived-class
*
* If, before destruction, preserve is set to @c true, then
* the object is "preserved", and not deleted at all.
*/
template < typename T >
struct cqDeleter
{
T*& p;
bool preserve = false;
~cqDeleter()
{
static_assert( std::is_base_of< QObject, T >::value, "Not a QObject-class" );
if ( !preserve )
{
if ( p )
{
p->deleteLater();
}
p = nullptr;
}
}
};
/// @brief Blocks signals on a QObject until destruction
using cSignalBlocker = QSignalBlocker;
/** @brief Writes a value on destruction to a pointed-to location.
*
* If the pointer is non-null, write the last-given-value if there
* is one to the pointed-to object. This is called the "then-value".
*
*/
template < typename T >
struct cScopedAssignment
{
std::optional< T > m_value;
T* m_pointer;
/** @brief Create a setter with no value set
*
* Until a value is set via operator=(), this pointer-setter
* will do nothing on destruction, leaving the pointed-to
* value unchanged.
*/
cScopedAssignment( T* p )
: m_pointer( p )
{
}
/** @brief Create a setter with a then-value already set
*
* This ensures that on destruction, the value @p v will be written;
* it is equivalent to assigning @p v immediately. The pointed-to
* value is **not** changed (until destruction).
*/
cScopedAssignment( T* p, T then )
: m_value( then )
, m_pointer( p )
{
}
/** @brief Create a setter with a then-value and assign a new value now
*
* As above, but also assign @p now to the thing pointed-to.
*/
cScopedAssignment( T* p, T now, T then )
: m_value( then )
, m_pointer( p )
{
if ( p )
{
*p = now;
}
}
~cScopedAssignment()
{
if ( m_pointer && m_value.has_value() )
{
*m_pointer = m_value.value();
}
}
const T& operator=( const T& then )
{
m_value = then;
return then;
}
};
template < typename T >
cScopedAssignment( T p ) -> cScopedAssignment< decltype( *p ) >;
#endif

View File

@@ -0,0 +1,145 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef UTILS_RETRANSLATOR_H
#define UTILS_RETRANSLATOR_H
#include "DllMacro.h"
#include "locale/Translation.h"
#include <QObject>
#include <QString>
#include <functional>
class QEvent;
class QLocale;
class QTranslator;
namespace Calamares
{
/** @brief changes the application language.
* @param locale the new locale (names as defined by Calamares).
* @param brandingTranslationsPrefix the branding path prefix, from Calamares::Branding.
*/
DLLEXPORT void installTranslator( const Calamares::Locale::Translation::Id& locale,
const QString& brandingTranslationsPrefix );
/** @brief Initializes the translations with the current system settings
*/
DLLEXPORT void installTranslator();
/** @brief The name of the (locale of the) most recently installed translator
*
* May return something different from the locale.name() of the
* QLocale passed in, because Calamares will munge some names and
* may remap translations.
*/
DLLEXPORT Calamares::Locale::Translation::Id translatorLocaleName();
/** @brief Loads <prefix><locale> translations into the given @p translator
*
* This function is not intended for general use: it is for those special
* cases where modules need their own translator / translations for data
* that is locale to the module. Tries to load a .qm from "sensible"
* locations, which are the same ones that installTranslator() would use.
* Takes local-translations into account.
*
* Note that @p prefix should end with an underscore '_' -- this function
* does not introduce one by itself.
*
* @returns @c true on success
*/
DLLEXPORT bool
loadTranslator( const Calamares::Locale::Translation::Id& locale, const QString& prefix, QTranslator* translator );
/** @brief Set @p allow to true to load translations from current dir.
*
* If false, (or never called) the translations are loaded only from
* system locations (the AppData dir) and from QRC (compiled in).
* Enable local translations to test translations stored in the
* current directory.
*/
DLLEXPORT void setAllowLocalTranslation( bool allow );
/** @brief Handles change-of-language events
*
* There is one single Retranslator object. Use `instance()` to get it.
* The top-level widget of the application should call
* `installEventFilter( Retranslator::instance() )`
* to set up event-handling for translation events. The Retranslator
* will emit signal `languageChanged()` if there is such an event.
*
* Normal consumers should not have to use the Retranslator directly,
* but use the macros `CALAMARES_RETRANSLATE*` to set things up
* in code -- the macros will connect to the Retranslator's signals.
*/
class DLLEXPORT Retranslator : public QObject
{
Q_OBJECT
public:
/// @brief Gets the global (single) Retranslator object
static Retranslator* instance();
/// @brief Helper function for attaching lambdas
static void attach( QObject* o, std::function< void( void ) > f );
signals:
void languageChanged();
protected:
bool eventFilter( QObject* obj, QEvent* e ) override;
private:
explicit Retranslator( QObject* parent );
};
} // namespace Calamares
/** @brief Call code for this object when language changes
*
* @p body should be a code block (it does not need braces) that can be wrapped
* up as a lambda. When the language changes, the lambda is called. Note that
* this macro should be used in constructors or other code that is run only
* once, since otherwise you will end up with multiple calls to @p body.
*
* NOTE: unlike plain QObject::connect(), the body is **also** called
* immediately after setting up the connection. This allows
* setup and translation code to be mixed together.
*/
#define CALAMARES_RETRANSLATE( body ) Calamares::Retranslator::attach( this, [ = ] { body } )
/** @brief Call code for the given object (widget) when language changes
*
* This is identical to CALAMARES_RETRANSLATE, except the @p body is called
* for the given object, not this object.
*
* NOTE: unlike plain QObject::connect(), the body is **also** called
* immediately after setting up the connection. This allows
* setup and translation code to be mixed together.
*/
#define CALAMARES_RETRANSLATE_FOR( object, body ) Calamares::Retranslator::attach( object, [ = ] { body } )
/** @brief Call a slot in this object when language changes
*
* Given a slot (in method-function-pointer notation), call that slot when the
* language changes. This is shorthand for connecting the Retranslator's
* signal to the given slot.
*
* NOTE: unlike plain QObject::connect(), the slot is **also** called
* immediately after setting up the connection. This allows
* setup and translation code to be mixed together.
*/
#define CALAMARES_RETRANSLATE_SLOT( slotfunc ) \
do \
{ \
connect( Calamares::Retranslator::instance(), &Calamares::Retranslator::languageChanged, this, slotfunc ); \
( this->*slotfunc )(); \
} while ( false )
#endif

View File

@@ -0,0 +1,135 @@
/* === 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 UTILS_RUNNER_H
#define UTILS_RUNNER_H
#include "System.h"
#include <QDir>
#include <QObject>
#include <QStringList>
#include <chrono>
#include <memory>
#include <optional>
namespace Calamares
{
namespace Utils
{
using RunLocation = Calamares::System::RunLocation;
using ProcessResult = Calamares::ProcessResult;
/** @brief A Runner wraps a process and handles running it and processing output
*
* This is basically a QProcess, but handles both running in the
* host system (through env(1)) or in the target (by calling chroot(8)).
* It has an output signal that handles output one line at a time
* (unlike QProcess that lets you do the buffering yourself).
* This output processing is only enabled if you do so explicitly.
*
* Use the set*() methods to configure the runner.
*
* If you call enableOutputProcessing(), then you can connect to
* the output() signal to receive each line (including trailing newline!).
*
* Processes are always run with LC_ALL and LANG set to "C".
*/
class DLLEXPORT Runner : public QObject
{
Q_OBJECT
public:
/** @brief Create an empty runner
*
* This is a runner with no commands, nothing; call set*() methods
* to configure it.
*/
Runner();
/** @brief Create a runner with a specified command
*
* Equivalent to Calamares::Utils::Runner::Runner() followed by
* calling setCommand().
*/
Runner( const QStringList& command );
virtual ~Runner() override;
Runner& setCommand( const QStringList& command )
{
m_command = command;
return *this;
}
Runner& setLocation( RunLocation r )
{
m_location = r;
return *this;
}
Runner& setWorkingDirectory( const QDir& directory )
{
m_directory = directory.absolutePath();
return *this;
}
Runner& setWorkingDirectory( const QString& directory )
{
m_directory = directory;
return *this;
}
Runner& setTimeout( std::chrono::seconds timeout )
{
m_timeout = timeout;
return *this;
}
Runner& setInput( const QString& input )
{
m_input = input;
return *this;
}
Runner& setOutputProcessing( bool enable )
{
m_output = enable;
return *this;
}
Runner& enableOutputProcessing()
{
m_output = true;
return *this;
}
ProcessResult run();
/** @brief The executable (argv[0]) that this runner will run
*
* This is the first element of the command; it does not include
* env(1) or chroot(8) which are injected when actually running
* the command.
*/
QString executable() const { return m_command.isEmpty() ? QString() : m_command.first(); }
signals:
void output( QString line );
private:
// What to run, and where.
QStringList m_command;
QString m_directory;
RunLocation m_location { RunLocation::RunInHost };
// Settings for when it actually runs
QString m_input;
std::chrono::milliseconds m_timeout { 0 };
bool m_output = false;
};
} // namespace Utils
} // namespace Calamares
#endif

View File

@@ -0,0 +1,112 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2013-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Originally from Tomahawk, portions:
* SPDX-FileCopyrightText: 2010-2011 Christian Muehlhaeuser <muesli@tomahawk-player.org>
* SPDX-FileCopyrightText: 2010-2011 Leo Franchi <lfranchi@kde.org>
* SPDX-FileCopyrightText: 2010-2012 Jeff Mitchell <jeff@tomahawk-player.org>
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef UTILS_STRING_H
#define UTILS_STRING_H
#include "DllMacro.h"
#include <QString>
/* Qt 5.14 changed the API to QString::split(), adding new overloads
* that take a different enum, then Qt 5.15 deprecated the old ones.
* To avoid overly-many warnings related to the API change, introduce
* Calamares-specific constants that pull from the correct enum.
*/
constexpr static const auto SplitSkipEmptyParts = Qt::SkipEmptyParts;
constexpr static const auto SplitKeepEmptyParts = Qt::KeepEmptyParts;
namespace Calamares
{
/**
* @brief The Calamares::String namespace
*
* This namespace contains functions related to string-handling,
* string-expansion, etc.
*/
namespace String
{
/**
* @brief removeDiacritics replaces letters with diacritics and ligatures with
* alternative forms and digraphs.
* @param string the string to transform.
* @return the output string with plain characters.
*/
DLLEXPORT QString removeDiacritics( const QString& string );
/**
* @brief obscure is a bidirectional obfuscation function, from KStringHandler.
* @param string the input string.
* @return the obfuscated string.
*/
DLLEXPORT QString obscure( const QString& string );
/** @brief Parameter for counting lines at beginning and end of string
*
* This is used by truncateMultiLine() to indicate how many lines from
* the beginning and how many from the end should be kept.
*/
struct LinesStartEnd
{
int atStart = 0;
int atEnd = 0;
};
/** @brief Parameter for counting characters in truncateMultiLine()
*/
struct CharCount
{
int total = 0;
};
/** @brief Truncate a string to some reasonable length for display
*
* Keep the first few, or last few (or both) lines of a possibly lengthy
* message @p string and reduce it to a displayable size (e.g. for
* pop-up windows that display the message). If the message is longer
* than @p chars, then characters are removed from the front (if
* @p lines.atStart is zero) or end (if @p lines.atEnd is zero) or in the middle
* (if both are nonzero).
*
* Asking for 0 lines will make this behave like QString::truncate().
*
* @param string the input string.
* @param lines number of lines to preserve.
* @param chars maximum number of characters in the returned string.
* @return a string built from parts of the input string.
*/
DLLEXPORT QString truncateMultiLine( const QString& string,
LinesStartEnd lines = LinesStartEnd { 3, 5 },
CharCount chars = CharCount { 812 } );
/** @brief Remove all @p c at the beginning of @p string
*
* Modifies the @p string in-place. If @p c is not the first character
* of @p string, the string is left unchanged; otherwise the first character
* is removed and the process repeats.
*/
DLLEXPORT void removeLeading( QString& string, QChar c );
/** @brief Remove all @p c at the end of @p string
*
* Like removeLeading(), but at the end of the string.
*/
DLLEXPORT void removeTrailing( QString& string, QChar c );
} // namespace String
} // namespace Calamares
#endif

View File

@@ -0,0 +1,77 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef UTILS_STRINGEXPANDER_H
#define UTILS_STRINGEXPANDER_H
#include "DllMacro.h"
#include <KMacroExpander>
#include <QString>
#include <QStringList>
#include <memory>
namespace Calamares
{
namespace String
{
/** @brief Expand variables in a string against a dictionary.
*
* This class provides a convenience API for building up a dictionary
* and using it to expand strings. Use the `expand()` method to
* do standard word-based expansion with `$` as macro-symbol.
*
* Unlike straight-up `KMacroExpander::expandMacros()`, this
* provides an API to find out which variables were missing
* from the dictionary during expansion. Use `hasErrors()` and
* `errorNames()` to find out which variables those were.
*
* Call `clearErrors()` to reset the stored errors. Calling
* `expand()` implicitly clears the errors before starting
* a new expansion, as well.
*/
class DLLEXPORT DictionaryExpander : public KWordMacroExpander
{
public:
DictionaryExpander();
DictionaryExpander( DictionaryExpander&& );
virtual ~DictionaryExpander() override;
void insert( const QString& key, const QString& value );
/** @brief As insert(), but supports method-chaining.
*
*/
DictionaryExpander& add( const QString& key, const QString& value )
{
insert( key, value );
return *this;
}
void clearErrors();
bool hasErrors() const;
QStringList errorNames() const;
QString expand( QString s );
protected:
virtual bool expandMacro( const QString& str, QStringList& ret ) override;
private:
struct Private;
std::unique_ptr< Private > d;
};
} // namespace String
} // namespace Calamares
#endif

View File

@@ -0,0 +1,365 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-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 UTILS_CALAMARESUTILSSYSTEM_H
#define UTILS_CALAMARESUTILSSYSTEM_H
#include "DllMacro.h"
#include "Job.h"
#include <QObject>
#include <QPair>
#include <QString>
#include <chrono>
namespace Calamares
{
class ProcessResult : public QPair< int, QString >
{
public:
enum class Code : int
{
Crashed = -1, // Must match special return values from QProcess
FailedToStart = -2, // Must match special return values from QProcess
NoWorkingDirectory = -3,
TimedOut = -4
};
/** @brief Implicit one-argument constructor has no output, only a return code */
ProcessResult( Code r )
: QPair< int, QString >( static_cast< int >( r ), QString() )
{
}
ProcessResult( int r, QString s )
: QPair< int, QString >( r, s )
{
}
int getExitCode() const { return first; }
QString getOutput() const { return second; }
/** @brief Explain a typical external process failure.
*
* @param errorCode Return code from runCommand() or similar
* (negative values get special explanation). The member
* function uses the exit code stored in the ProcessResult
* @param output (error) output from the command, used when there is
* an error to report (exit code > 0). The member
* function uses the output stored in the ProcessResult.
* @param command String or split-up string of the command
* that was invoked.
* @param timeout Timeout passed to the process runner, for explaining
* error code -4 (timeout).
*/
static DLLEXPORT Calamares::JobResult
explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout );
/// @brief Convenience wrapper for explainProcess()
inline Calamares::JobResult explainProcess( const QString& command, std::chrono::seconds timeout ) const
{
return explainProcess( getExitCode(), command, getOutput(), timeout );
}
/// @brief Convenience wrapper for explainProcess()
inline Calamares::JobResult explainProcess( const QStringList& command, std::chrono::seconds timeout ) const
{
return explainProcess( getExitCode(), command.join( ' ' ), getOutput(), timeout );
}
};
/** @brief The result of a create*() action, for status
*
* A CreationResult has a status field, can be converted to bool
* (true only on success) and can report the full pathname of
* the thing created if it was successful.
*/
class CreationResult : public QPair< int, QString >
{
public:
enum class Code : int
{
// These are "not failed", but only OK is a success
OK = 0,
AlreadyExists = 1,
// These are "failed"
Invalid = -1,
Failed = -2
};
CreationResult( Code r )
: QPair< int, QString >( static_cast< int >( r ), QString() )
{
}
explicit CreationResult( const QString& path )
: QPair< int, QString >( 0, path )
{
}
Code code() const { return static_cast< Code >( first ); }
QString path() const { return second; }
bool failed() const { return first < 0; }
operator bool() const { return first == 0; }
};
/**
* @brief The System class is a singleton with utility functions that perform
* system-specific operations.
*/
class DLLEXPORT System : public QObject
{
Q_OBJECT
public:
/**
* @brief System the constructor. Only call this once in a Calamares instance.
* @param doChroot set to true if all external commands should run in the
* target system chroot, otherwise false to run everything on the current system.
* @param parent the QObject parent.
*/
explicit System( bool doChroot, QObject* parent = nullptr );
~System() override;
static System* instance();
/** (Typed) Boolean describing where a particular command should be run,
* whether in the host (live) system or in the (chroot) target system.
*/
enum class RunLocation
{
RunInHost,
RunInTarget
};
/** @brief Runs a command in the host or the target (select explicitly)
*
* @param location whether to run in the host or the target
* @param args the command with arguments, as a string list.
* @param workingPath the current working directory for the QProcess
* call (optional).
* @param stdInput the input string to send to the running process as
* standard input (optional).
* @param timeoutSec the timeout after which the process will be
* killed (optional, default is 0 i.e. no timeout).
*
* @returns the program's exit code and its output (if any). Special
* exit codes (which will never have any output) are:
* Crashed = QProcess crash
* FailedToStart = QProcess cannot start
* NoWorkingDirectory = bad arguments
* TimedOut = QProcess timeout
*/
static DLLEXPORT ProcessResult runCommand( RunLocation location,
const QStringList& args,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) );
/** @brief Convenience wrapper for runCommand() in the host
*
* Runs the given command-line @p args in the **host** in the current direcory
* with no input, and the given @p timeoutSec for completion.
*/
static inline ProcessResult runCommand( const QStringList& args, std::chrono::seconds timeoutSec )
{
return runCommand( RunLocation::RunInHost, args, QString(), QString(), timeoutSec );
}
/** @brief Convenience wrapper for runCommand().
*
* Runs the command in the location specified through the boolean
* doChroot(), which is what you usually want for running commands
* during installation.
*/
inline ProcessResult targetEnvCommand( const QStringList& args,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) )
{
return runCommand(
m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, args, workingPath, stdInput, timeoutSec );
}
/** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code */
inline int targetEnvCall( const QStringList& args,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) )
{
return targetEnvCommand( args, workingPath, stdInput, timeoutSec ).first;
}
/** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code */
inline int targetEnvCall( const QString& command,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) )
{
return targetEnvCall( QStringList { command }, workingPath, stdInput, timeoutSec );
}
/** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code
*
* Places the called program's output in the @p output string.
*/
int targetEnvOutput( const QStringList& args,
QString& output,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) )
{
auto r = targetEnvCommand( args, workingPath, stdInput, timeoutSec );
output = r.second;
return r.first;
}
/** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code
*
* Places the called program's output in the @p output string.
*/
inline int targetEnvOutput( const QString& command,
QString& output,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) )
{
return targetEnvOutput( QStringList { command }, output, workingPath, stdInput, timeoutSec );
}
/** @brief Gets a path to a file in the target system, from the host.
*
* @param path Path to the file; this is interpreted
* from the root of the target system (whatever that may be,
* but / in the chroot, or / in OEM modes).
*
* @return The complete path to the target file, from
* the root of the host system, or empty on failure.
*
* For instance, during installation where the target root is
* mounted on /tmp/calamares-something, asking for targetPath("/etc/passwd")
* will give you /tmp/calamares-something/etc/passwd.
*
* No attempt is made to canonicalize anything, since paths might not exist.
*/
DLLEXPORT QString targetPath( const QString& path ) const;
enum class WriteMode
{
KeepExisting,
Overwrite
};
/** @brief Create a (small-ish) file in the target system.
*
* @param path Path to the file; this is interpreted
* from the root of the target system (whatever that may be,
* but / in the chroot, or / in OEM modes).
* @param contents Actual content of the file.
*
* If the target already exists:
* - returns AlreadyExists as a result (and does not overwrite),
* - **unless** @p mode is set to Overwrite, then it tries writing as
* usual and will not return AlreadyExists.
*
* @return The complete canonical path to the target file from the
* root of the host system, or empty on failure. (Here, it is
* possible to be canonical because the file exists).
*/
DLLEXPORT CreationResult createTargetFile( const QString& path,
const QByteArray& contents,
WriteMode mode = WriteMode::KeepExisting ) const;
/** @brief Remove a file from the target system.
*
* @param path Path to the file; this is interpreted from the root
* of the target system (@see targetPath()).
*
* Does no error checking to see if the target file was really removed.
*/
DLLEXPORT void removeTargetFile( const QString& path ) const;
/** @brief Reads a file from the target system.
*
* @param path Path to the file; this is interpreted from the root of
* the target system (@see targetPath()).
*
* Does no error checking, and returns an empty list if the file does
* not exist.
*
* NOTE: This function is now basically the same as QFile::readAll(),
* splitting into lines, but Calamares may need to change
* permissions or raise privileges to actually read the file,
* which is why there is an API.
*
* NOTE: Since this buffers the whole file in memory, reading big files
* is not recommended.
*/
DLLEXPORT QStringList readTargetFile( const QString& path ) const;
/** @brief Ensure that the directory @p path exists
*
* @param path a full pathname to a desired directory.
*
* All the directory components including the last path component are
* created, as needed. Returns true on success.
*
* @see QDir::mkpath
*/
DLLEXPORT bool createTargetDirs( const QString& path ) const;
/** @brief Convenience to create parent directories of a file path.
*
* Creates all the parent directories until the last
* component of @p filePath . @see createTargetDirs()
*/
DLLEXPORT bool createTargetParentDirs( const QString& filePath ) const;
/**
* @brief getTotalMemoryB returns the total main memory, in bytes.
*
* Since it is difficult to get the RAM memory size exactly -- either
* by reading information from the DIMMs, which may fail on virtual hosts
* or from asking the kernel, which doesn't report some memory areas --
* this returns a pair of guessed-size (in bytes) and a "guesstimate factor"
* which says how good the guess is. Generally, assume the *real* memory
* available is size * guesstimate.
*
* If nothing can be found, returns a 0 size and 0 guesstimate.
*
* @return size, guesstimate-factor
*/
DLLEXPORT QPair< quint64, qreal > getTotalMemoryB() const;
/**
* @brief getCpuDescription returns a string describing the CPU.
*
* Returns the value of the "model name" line in /proc/cpuinfo.
*/
DLLEXPORT QString getCpuDescription() const;
/**
* @brief getTotalDiskB returns the total disk attached, in bytes.
*
* If nothing can be found, returns a 0.
*/
DLLEXPORT quint64 getTotalDiskB() const;
DLLEXPORT bool doChroot() const;
private:
static System* s_instance;
bool m_doChroot;
};
} // namespace Calamares
#endif

View File

@@ -0,0 +1,77 @@
/* === 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 UTILS_TRAITS_H
#define UTILS_TRAITS_H
#include <type_traits>
namespace Calamares
{
/** @brief Traits machinery lives in this namespace
*
* The primary purpose of this namespace is to hold machinery that
* is created by the DECLARE_HAS_METHOD macro.
*
* The DECLARE_HAS_METHOD macro builds machinery to check whether
* a class has a particular named method. This can be used to
* specialize templates elsewhere for use with classes with, or without,
* the named method.
*
* To use the machinery (which is not that sophisticated):
*
* - Put `DECLARE_HAS_METHOD(myFunction)` somewhere in file scope.
* This puts together the machinery for detecting if `myFunction`
* is a method of some class.
* - At global scope, `has_myFunction<T>` is now either std::true_type,
* if the type `T` has a method `T::myFunction`, or std::false_type,
* if it does not.
*
* To specialize template methods based on the presence of the named
* method, write **three** overloads:
*
* - `template<class T> myMethod(args ..., const std::true_type& )`
* This is the implementation where class T has `myFunction`.
* - `template<class T> myMethod(args ..., const std::false_type& )`
* This is the implementation without.
* - `template<class T> myMethod(args ...)` is the general implementation,
* which can call the specialized implementations with
* `return myMethod(args ..., has_myFunction<T>{})`
*/
namespace Traits
{
template < class >
struct sfinae_true : std::true_type
{
};
} // namespace Traits
} // namespace Calamares
#define DECLARE_HAS_METHOD( m ) \
namespace Calamares \
{ \
namespace Traits \
{ \
struct has_##m \
{ \
template < class T > \
static auto f( int ) -> sfinae_true< decltype( &T::m ) >; \
template < class T > \
static auto f( long ) -> std::false_type; \
template < class T > \
using t = decltype( f< T >( 0 ) ); \
}; \
} \
} \
template < class T > \
using has_##m = Calamares::Traits::has_##m ::t< T >;
#endif

View File

@@ -0,0 +1,50 @@
/* === 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 UTILS_UMASK_H
#define UTILS_UMASK_H
#include "DllMacro.h"
#include <sys/types.h>
namespace Calamares
{
/** @brief Wrapper for umask(2)
*
* Like umask(2), sets the umask and returns the previous value of the mask.
*/
DLLEXPORT mode_t setUMask( mode_t u );
/** @brief RAII for setting and re-setting umask.
*
* Create an object of this class to set the umask,
* and the umask is reset to its original value when
* the object goes out of scope.
*/
class DLLEXPORT UMask
{
public:
UMask( mode_t u );
~UMask();
/** @brief a "safe" umask
*
* This umask will switch off group- and other- permissions for
* files, so that the file cannot be read, written, or executed
* except by the owner.
*/
static constexpr mode_t Safe = 077; // octal!
private:
mode_t m_mode;
};
} // namespace Calamares
#endif

View File

@@ -0,0 +1,181 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
* SPDX-FileCopyrightText: 2019 Collabora Ltd <arnaud.ferraris@collabora.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
*
* Calamares is Free Software: see the License-Identifier above.
*
*
*/
#ifndef UTILS_UNITS_H
#define UTILS_UNITS_H
#include <QtCore/QIntegerForSize>
namespace Calamares
{
/// @brief Type for expressing units
using intunit_t = quint64;
namespace Units
{
/** User defined literals, 1_KB is 1 KiloByte (= 10^3 bytes) */
constexpr qint64
operator""_KB( unsigned long long m )
{
return qint64( m ) * 1000;
}
/** User defined literals, 1_KiB is 1 KibiByte (= 2^10 bytes) */
constexpr qint64
operator""_KiB( unsigned long long m )
{
return qint64( m ) * 1024;
}
/** User defined literals, 1_MB is 1 MegaByte (= 10^6 bytes) */
constexpr qint64
operator""_MB( unsigned long long m )
{
return operator""_KB( m ) * 1000;
}
/** User defined literals, 1_MiB is 1 MibiByte (= 2^20 bytes) */
constexpr qint64
operator""_MiB( unsigned long long m )
{
return operator""_KiB( m ) * 1024;
}
/** User defined literals, 1_GB is 1 GigaByte (= 10^9 bytes) */
constexpr qint64
operator""_GB( unsigned long long m )
{
return operator""_MB( m ) * 1000;
}
/** User defined literals, 1_GiB is 1 GibiByte (= 2^30 bytes) */
constexpr qint64
operator""_GiB( unsigned long long m )
{
return operator""_MiB( m ) * 1024;
}
} // namespace Units
constexpr qint64
KBtoBytes( unsigned long long m )
{
return Units::operator""_KB( m );
}
constexpr qint64
KiBtoBytes( unsigned long long m )
{
return Units::operator""_KiB( m );
}
constexpr qint64
MBtoBytes( unsigned long long m )
{
return Units::operator""_MB( m );
}
constexpr qint64
MiBtoBytes( unsigned long long m )
{
return Units::operator""_MiB( m );
}
constexpr qint64
GBtoBytes( unsigned long long m )
{
return Units::operator""_GB( m );
}
constexpr qint64
GiBtoBytes( unsigned long long m )
{
return Units::operator""_GiB( m );
}
constexpr qint64
KBtoBytes( double m )
{
return qint64( m * 1000 );
}
constexpr qint64
KiBtoBytes( double m )
{
return qint64( m * 1024 );
}
constexpr qint64
MBtoBytes( double m )
{
return qint64( m * 1000 * 1000 );
}
constexpr qint64
MiBtoBytes( double m )
{
return qint64( m * 1024 * 1024 );
}
constexpr qint64
GBtoBytes( double m )
{
return qint64( m * 1000 * 1000 * 1000 );
}
constexpr qint64
GiBtoBytes( double m )
{
return qint64( m * 1024 * 1024 * 1024 );
}
constexpr int
BytesToMiB( qint64 b )
{
return int( b / 1024 / 1024 );
}
// TODO: deprecate signed version
constexpr int
BytesToGiB( qint64 b )
{
return int( b / 1024 / 1024 / 1024 );
}
constexpr intunit_t
BytesToGiB( intunit_t b )
{
return b / 1024 / 1024 / 1024;
}
constexpr qint64
alignBytesToBlockSize( qint64 bytes, qint64 blocksize )
{
qint64 blocks = bytes / blocksize;
if ( blocks * blocksize != bytes )
{
++blocks;
}
return blocks * blocksize;
}
constexpr qint64
bytesToSectors( qint64 bytes, qint64 blocksize )
{
return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize ), MiBtoBytes( 1ULL ) ) / blocksize;
}
} // namespace Calamares
#endif

View File

@@ -0,0 +1,78 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2013-2016 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 UTILS_VARIANT_H
#define UTILS_VARIANT_H
#include "DllMacro.h"
#include <QList>
#include <QString>
#include <QVariantMap>
namespace Calamares
{
/**
* Get a bool value from a mapping with a given key; returns @p d if no value.
*/
DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d = false );
/** @brief Get a string value from a mapping with a given key; returns @p d if no value.
*
* The value must be an actual string; numbers are not automatically converted to strings,
* nor are lists flattened or converted.
*/
DLLEXPORT QString getString( const QVariantMap& map, const QString& key, const QString& d = QString() );
/** @brief Get a string list from a mapping with a given key; returns @p d if no value.
*
* This is slightly more lenient than getString(), and a single-string value will
* be returned as a 1-item list.
*/
DLLEXPORT QStringList getStringList( const QVariantMap& map, const QString& key, const QStringList& d = QStringList() );
/**
* Get a list from a mapping with a given key; returns @p d if no value.
*/
DLLEXPORT QList< QVariant >
getList( const QVariantMap& map, const QString& key, const QList< QVariant >& d = QList< QVariant >() );
/**
* Get an integer value from a mapping with a given key; returns @p d if no value.
*/
DLLEXPORT qint64 getInteger( const QVariantMap& map, const QString& key, qint64 d = 0 );
/**
* Get an unsigned integer value from a mapping with a given key; returns @p d if no value.
*/
DLLEXPORT quint64 getUnsignedInteger( const QVariantMap& map, const QString& key, quint64 d = 0 );
/**
* Get a double value from a mapping with a given key (integers are converted); returns @p d if no value.
*/
DLLEXPORT double getDouble( const QVariantMap& map, const QString& key, double d = 0.0 );
/**
* Returns a sub-map (i.e. a nested map) from a given mapping with a
* given key. @p success is set to true if the @p key exists
* in @p map and converts to a map, false otherwise.
*
* Returns @p d if there is no such key or it is not a map-value.
* (e.g. if @p success is false).
*/
DLLEXPORT QVariantMap getSubMap( const QVariantMap& map,
const QString& key,
bool& success,
const QVariantMap& d = QVariantMap() );
} // namespace Calamares
#endif

View File

@@ -0,0 +1,85 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
/*
* YAML conversions and YAML convenience header.
*
* Includes the system YAMLCPP headers without warnings (by switching off
* the expected warnings) and provides a handful of methods for
* converting between YAML and QVariant.
*/
#ifndef UTILS_YAML_H
#define UTILS_YAML_H
#include "DllMacro.h"
#include <QStringList>
#include <QVariant>
#include <QVariantList>
#include <QVariantMap>
class QByteArray;
class QFileInfo;
// The yaml-cpp headers are not C++11 warning-proof, especially
// with picky compilers like Clang 8. Since we use Clang for the
// find-all-the-warnings case, switch those warnings off for
// the we-can't-change-them system headers.
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG( "-Wzero-as-null-pointer-constant" )
QT_WARNING_DISABLE_CLANG( "-Wshadow" )
QT_WARNING_DISABLE_CLANG( "-Wfloat-equal" )
QT_WARNING_DISABLE_CLANG( "-Wsuggest-destructor-override" )
#include <yaml-cpp/yaml.h>
QT_WARNING_POP
/// @brief Appends all the elements of @p node to the string list @p v
DLLEXPORT void operator>>( const ::YAML::Node& node, QStringList& v );
namespace Calamares
{
namespace YAML
{
/**
* Loads a given @p filename and returns the YAML data
* as a QVariantMap. If filename doesn't exist, or is
* malformed in some way, returns an empty map and sets
* @p *ok to false. Otherwise sets @p *ok to true.
*/
DLLEXPORT QVariantMap load( const QString& filename, bool* ok = nullptr );
/** Convenience overload. */
DLLEXPORT QVariantMap load( const QFileInfo&, bool* ok = nullptr );
DLLEXPORT QVariant toVariant( const ::YAML::Node& node );
DLLEXPORT QVariant scalarToVariant( const ::YAML::Node& scalarNode );
DLLEXPORT QVariantList sequenceToVariant( const ::YAML::Node& sequenceNode );
DLLEXPORT QVariantMap mapToVariant( const ::YAML::Node& mapNode );
/// @brief Returns all the elements of @p listNode in a StringList
DLLEXPORT QStringList toStringList( const ::YAML::Node& listNode );
/// @brief Save a @p map to @p filename as YAML
DLLEXPORT bool save( const QString& filename, const QVariantMap& map );
/**
* Given an exception from the YAML parser library, explain
* what is going on in terms of the data passed to the parser.
* Uses @p label when labeling the data source (e.g. "netinstall data")
*/
DLLEXPORT void explainException( const ::YAML::Exception& e, const QByteArray& data, const char* label );
DLLEXPORT void explainException( const ::YAML::Exception& e, const QByteArray& data, const QString& label );
DLLEXPORT void explainException( const ::YAML::Exception& e, const QByteArray& data );
} // namespace YAML
} // namespace Calamares
#endif

View File

@@ -0,0 +1,35 @@
/* === 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.
*
*
*/
/* @file Turn off warnings on MOC-generated code
*
* This header file exists **only** to reduce warnings during compilation.
* Code generated by Qt's MOC, in combination with Clang (version 6 or later,
* I'm fairly sure) and the plenty-of-warnings settings that Calamares uses,
* triggers tons of warnings. Since those warnings are not something we
* can do anything about, turn them off by `#include`ing this header
* before a MOC file.
*
* Note that not many files in Calamares use MOC directly: mostly CMake's
* automoc does all the work for us.
*/
#ifdef __clang__
#include <qglobal.h>
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG( "-Wextra-semi-stmt" )
QT_WARNING_DISABLE_CLANG( "-Wredundant-parens" )
QT_WARNING_DISABLE_CLANG( "-Wreserved-identifier" )
#if __clang_major__ >= 17
QT_WARNING_DISABLE_CLANG( "-Wunsafe-buffer-usage" )
#endif
QT_WARNING_POP
#endif