Merge branch 'calamares' of https://github.com/calamares/calamares into development
This commit is contained in:
commit
16c6e2c6d3
13
CHANGES
13
CHANGES
@ -10,12 +10,15 @@ website will have to do for older versions.
|
||||
# 3.2.40 (unreleased) #
|
||||
|
||||
This release contains contributions from (alphabetically by first name):
|
||||
- Anke Boersma
|
||||
- Anubhav Choudhary (SoK success!)
|
||||
- Emmanuel Arias (new contributor! welcome!)
|
||||
- Erik Dubois
|
||||
- Jerrod Frost (new contributor! welcome!)
|
||||
- Jia Chao (new contributor! welcome!)
|
||||
- Joe Kamprad
|
||||
- Lisa Vitolo (blast from the past!)
|
||||
- Omer I.S. (new contributor! welcome!)
|
||||
|
||||
In project news, chat (instant-messaging) communications has largely
|
||||
moved to Matrix and Libera.Chat. CI notifications -- issues and build
|
||||
@ -33,9 +36,14 @@ results -- are sent to Matrix only.
|
||||
- The "upload log file" now has a configurable log-file-size. (Thanks Anubhav)
|
||||
|
||||
## Modules ##
|
||||
- *bootloader* can now install an aarch64 (ARM) compatible EFI GRUB. (Thanks Jia)
|
||||
- *displaymanager* example configuration has been shuffled around a bit,
|
||||
for better results when the live image is running XFCE. Also lists
|
||||
more potential display managers. #1205 (Thanks Erik)
|
||||
- *keyboard* now switches on an alternate `en_US` keyboard layout when
|
||||
Arabic or Hebrew is selected as primary layout. (Thanks Omer)
|
||||
- *localeq* now has a fully functional offline option (alongside the default
|
||||
interactive map option, which requires internet).
|
||||
- The *netinstall* module can now fall back to alternative URLs when
|
||||
loading groups data. The first URL to yield a non-empty groups
|
||||
collection is accepted. No changes are needed in the configuration. #1673
|
||||
@ -47,6 +55,11 @@ results -- are sent to Matrix only.
|
||||
- A long-neglected pull request from Lisa Vitolo for the *partition*
|
||||
module -- allowing to set filesystem labels during manual partitioning --
|
||||
has been revived and merged.
|
||||
- The *partition* manager has had a long-standing bug with partition-flags
|
||||
and manual partitioning resolved. This may help resolve some installation
|
||||
issues on UEFI systems. #1724
|
||||
- *usersq* is further implemented and can now be used for a successful install.
|
||||
Not all warning messages available in the regular users module are implemented.
|
||||
|
||||
|
||||
# 3.2.39.3 (2021-04-14) #
|
||||
|
@ -18,18 +18,25 @@
|
||||
#include "GlobalStorage.h"
|
||||
#include "Job.h"
|
||||
#include "JobQueue.h"
|
||||
#include "PythonJob.h"
|
||||
#include "Settings.h"
|
||||
#include "ViewManager.h"
|
||||
#include "modulesystem/Module.h"
|
||||
#include "modulesystem/ModuleManager.h"
|
||||
#include "modulesystem/ViewModule.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Yaml.h"
|
||||
#include "viewpages/ExecutionViewStep.h"
|
||||
|
||||
// Optional features of Calamares
|
||||
// - Python support
|
||||
// - QML support
|
||||
#ifdef WITH_PYTHON
|
||||
#include "PythonJob.h"
|
||||
#endif
|
||||
#ifdef WITH_QML
|
||||
#include "utils/Qml.h"
|
||||
#endif
|
||||
#include "utils/Yaml.h"
|
||||
#include "viewpages/ExecutionViewStep.h"
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineOption>
|
||||
@ -55,6 +62,7 @@ struct ModuleConfig
|
||||
QString m_language;
|
||||
QString m_branding;
|
||||
bool m_ui;
|
||||
bool m_pythonInjection;
|
||||
};
|
||||
|
||||
static ModuleConfig
|
||||
@ -79,7 +87,6 @@ handle_args( QCoreApplication& a )
|
||||
QStringLiteral( "Enable UI" ) );
|
||||
QCommandLineOption slideshowOption( QStringList() << QStringLiteral( "s" ) << QStringLiteral( "slideshow" ),
|
||||
QStringLiteral( "Run slideshow module" ) );
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription( "Calamares module tester" );
|
||||
parser.addHelpOption();
|
||||
@ -92,6 +99,12 @@ handle_args( QCoreApplication& a )
|
||||
parser.addOption( brandOption );
|
||||
parser.addOption( uiOption );
|
||||
parser.addOption( slideshowOption );
|
||||
#ifdef WITH_PYTHON
|
||||
QCommandLineOption pythonOption( QStringList() << QStringLiteral( "P" ) << QStringLiteral( "no-injected-python" ),
|
||||
QStringLiteral( "Do not disable potentially-harmful Python commands" ) );
|
||||
parser.addOption( pythonOption );
|
||||
#endif
|
||||
|
||||
parser.addPositionalArgument( "module", "Path or name of module to run." );
|
||||
parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" );
|
||||
|
||||
@ -116,12 +129,21 @@ handle_args( QCoreApplication& a )
|
||||
jobSettings = args.at( 1 );
|
||||
}
|
||||
|
||||
bool pythonInjection = true;
|
||||
#ifdef WITH_PYTHON
|
||||
if ( parser.isSet( pythonOption ) )
|
||||
{
|
||||
pythonInjection = false;
|
||||
}
|
||||
#endif
|
||||
return ModuleConfig { parser.isSet( slideshowOption ) ? QStringLiteral( "-" ) : args.first(),
|
||||
jobSettings,
|
||||
parser.value( globalOption ),
|
||||
parser.value( langOption ),
|
||||
parser.value( brandOption ),
|
||||
parser.isSet( slideshowOption ) || parser.isSet( uiOption ) };
|
||||
parser.isSet( slideshowOption ) || parser.isSet( uiOption ),
|
||||
pythonInjection
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,10 +388,15 @@ createApplication( int& argc, char* argv[] )
|
||||
return new QCoreApplication( argc, argv );
|
||||
}
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
static const char pythonPreScript[] = R"(
|
||||
# This is Python code executed by Python modules *before* the
|
||||
# script file (e.g. main.py) is executed. Beware " before )
|
||||
# because it's a C++ raw-string.
|
||||
#
|
||||
# Calls to suprocess methods that execute something are
|
||||
# suppressed and logged -- scripts should really be using libcalamares
|
||||
# methods instead.
|
||||
_calamares_subprocess = __import__("subprocess", globals(), locals(), [], 0)
|
||||
import sys
|
||||
import libcalamares
|
||||
@ -382,10 +409,13 @@ class fake_subprocess(object):
|
||||
def check_call(*args, **kwargs):
|
||||
libcalamares.utils.debug("subprocess.check_call(%r,%r) X subverted to call" % (args, kwargs))
|
||||
return 0
|
||||
for attr in ("CalledProcessError",):
|
||||
setattr(fake_subprocess,attr,getattr(_calamares_subprocess,attr))
|
||||
sys.modules["subprocess"] = fake_subprocess
|
||||
libcalamares.utils.debug('pre-script for testing purposes injected')
|
||||
|
||||
)";
|
||||
#endif
|
||||
|
||||
int
|
||||
main( int argc, char* argv[] )
|
||||
@ -416,10 +446,15 @@ main( int argc, char* argv[] )
|
||||
gs->insert( "localeConf", vm );
|
||||
}
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
if ( module.m_pythonInjection )
|
||||
{
|
||||
Calamares::PythonJob::setInjectedPreScript(pythonPreScript);
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_QML
|
||||
CalamaresUtils::initQmlModulesDir(); // don't care if failed
|
||||
#endif
|
||||
Calamares::PythonJob::setInjectedPreScript(pythonPreScript);
|
||||
|
||||
cDebug() << "Calamares module-loader testing" << module.moduleName();
|
||||
Calamares::Module* m = load_module( module );
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
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;
|
||||
@ -315,6 +317,12 @@ private:
|
||||
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;
|
||||
@ -327,6 +335,7 @@ operator<<( CDebug&& s, const Once& o )
|
||||
|
||||
} // 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 )
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <QObject>
|
||||
#include <QSignalBlocker>
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
|
||||
/** @brief Convenience to zero out and deleteLater of any QObject-derived-class
|
||||
@ -58,4 +59,20 @@ struct cBoolSetter
|
||||
/// @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.
|
||||
*/
|
||||
template < typename T >
|
||||
struct cPointerSetter
|
||||
{
|
||||
std::optional< T > m_value;
|
||||
T* m_pointer;
|
||||
|
||||
cPointerSetter( T* p ) : m_pointer(p) {}
|
||||
~cPointerSetter() { if ( m_pointer && m_value.has_value() ) { *m_pointer = m_value.value(); } }
|
||||
|
||||
const T& operator=(const T& v) { m_value = v; return v; }
|
||||
};
|
||||
#endif
|
||||
|
@ -46,25 +46,27 @@ private Q_SLOTS:
|
||||
|
||||
void testCommands();
|
||||
|
||||
/** @brief Test that all the UMask objects work correctly. */
|
||||
/** @section Test that all the UMask objects work correctly. */
|
||||
void testUmask();
|
||||
|
||||
/** @brief Tests the entropy functions. */
|
||||
/** @section Tests the entropy functions. */
|
||||
void testEntropy();
|
||||
void testPrintableEntropy();
|
||||
void testOddSizedPrintable();
|
||||
|
||||
/** @brief Tests the RAII bits. */
|
||||
/** @section Tests the RAII bits. */
|
||||
void testBoolSetter();
|
||||
void testPointerSetter();
|
||||
|
||||
/** @brief Tests the Traits bits. */
|
||||
/** @section Tests the Traits bits. */
|
||||
void testTraits();
|
||||
|
||||
/** @section Testing the variants-methods */
|
||||
void testVariantStringListCode();
|
||||
void testVariantStringListYAMLDashed();
|
||||
void testVariantStringListYAMLBracketed();
|
||||
|
||||
/** @brief Test smart string truncation. */
|
||||
/** @section Test smart string truncation. */
|
||||
void testStringTruncation();
|
||||
void testStringTruncationShorter();
|
||||
void testStringTruncationDegenerate();
|
||||
@ -360,6 +362,50 @@ LibCalamaresTests::testBoolSetter()
|
||||
QVERIFY( b );
|
||||
}
|
||||
|
||||
void
|
||||
LibCalamaresTests::testPointerSetter()
|
||||
{
|
||||
int special = 17;
|
||||
|
||||
QCOMPARE( special, 17 );
|
||||
{
|
||||
cPointerSetter p( &special );
|
||||
}
|
||||
QCOMPARE( special, 17 );
|
||||
{
|
||||
cPointerSetter p( &special );
|
||||
p = 18;
|
||||
}
|
||||
QCOMPARE( special, 18 );
|
||||
{
|
||||
cPointerSetter p( &special );
|
||||
p = 20;
|
||||
p = 3;
|
||||
}
|
||||
QCOMPARE( special, 3 );
|
||||
{
|
||||
cPointerSetter<int> p( nullptr );
|
||||
}
|
||||
QCOMPARE( special, 3 );
|
||||
{
|
||||
// "don't do this" .. order of destructors is important
|
||||
cPointerSetter p( &special );
|
||||
cPointerSetter q( &special );
|
||||
p = 17;
|
||||
}
|
||||
QCOMPARE( special, 17 );
|
||||
{
|
||||
// "don't do this" .. order of destructors is important
|
||||
cPointerSetter p( &special );
|
||||
cPointerSetter q( &special );
|
||||
p = 34;
|
||||
q = 2;
|
||||
// q destroyed first, then p
|
||||
}
|
||||
QCOMPARE( special, 34 );
|
||||
}
|
||||
|
||||
|
||||
/* Demonstration of Traits support for has-a-method or not.
|
||||
*
|
||||
* We have two classes, c1 and c2; one has a method do_the_thing() and the
|
||||
@ -431,17 +477,31 @@ LibCalamaresTests::testVariantStringListCode()
|
||||
QCOMPARE( getStringList( m, key ), QStringList {} );
|
||||
m.insert( key, 17 );
|
||||
QCOMPARE( getStringList( m, key ), QStringList {} );
|
||||
m.insert( key, QString( "more strings" ) );
|
||||
QCOMPARE( getStringList( m, key ),
|
||||
QStringList { "more strings" } ); // A single string **can** be considered a stringlist!
|
||||
m.insert( key, QVariant {} );
|
||||
QCOMPARE( getStringList( m, key ), QStringList {} );
|
||||
}
|
||||
|
||||
{
|
||||
// Things that are stringlists
|
||||
// Things that are **like** stringlists
|
||||
QVariantMap m;
|
||||
m.insert( key, QString( "astring" ) );
|
||||
QCOMPARE( getStringList( m, key ).count(), 1 );
|
||||
QCOMPARE( getStringList( m, key ),
|
||||
QStringList { "astring" } ); // A single string **can** be considered a stringlist!
|
||||
m.insert( key, QString( "more strings" ) );
|
||||
QCOMPARE( getStringList( m, key ).count(), 1 );
|
||||
QCOMPARE( getStringList( m, key ),
|
||||
QStringList { "more strings" } );
|
||||
m.insert( key, QString() );
|
||||
QCOMPARE( getStringList( m, key ).count(), 1 );
|
||||
QCOMPARE( getStringList( m, key ), QStringList { QString() } );
|
||||
}
|
||||
|
||||
{
|
||||
// Things that are definitely stringlists
|
||||
QVariantMap m;
|
||||
m.insert( key, QStringList { "aap", "noot" } );
|
||||
QCOMPARE( getStringList( m, key ).count(), 2 );
|
||||
QVERIFY( getStringList( m, key ).contains( "aap" ) );
|
||||
QVERIFY( !getStringList( m, key ).contains( "mies" ) );
|
||||
}
|
||||
|
@ -25,13 +25,17 @@ namespace CalamaresUtils
|
||||
*/
|
||||
DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d = false );
|
||||
|
||||
/**
|
||||
* Get a string value from a mapping with a given key; returns @p d if no value.
|
||||
/** @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() );
|
||||
|
||||
/**
|
||||
* Get a string list from a mapping with a given key; returns @p d if no value.
|
||||
/** @brief Get a string list from a mapping with a given key; returns @p d if no value.
|
||||
*
|
||||
* This is slightly more lenient that 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() );
|
||||
|
||||
|
@ -613,4 +613,10 @@ ViewManager::isSetupMode() const
|
||||
return s ? s->isSetupMode() : false;
|
||||
}
|
||||
|
||||
QString
|
||||
ViewManager::logFilePath() const
|
||||
{
|
||||
return Logger::logFile();
|
||||
}
|
||||
|
||||
} // namespace Calamares
|
||||
|
@ -54,6 +54,7 @@ class UIDLLEXPORT ViewManager : public QAbstractListModel
|
||||
Q_PROPERTY( bool isDebugMode READ isDebugMode CONSTANT FINAL )
|
||||
Q_PROPERTY( bool isChrootMode READ isChrootMode CONSTANT FINAL )
|
||||
Q_PROPERTY( bool isSetupMode READ isSetupMode CONSTANT FINAL )
|
||||
Q_PROPERTY( QString logFilePath READ logFilePath CONSTANT FINAL )
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -208,6 +209,8 @@ public Q_SLOTS:
|
||||
bool isChrootMode() const;
|
||||
/// @brief Proxy to Settings::isSetupMode() default @c false
|
||||
bool isSetupMode() const;
|
||||
/// @brief Proxy to Logger::logFile(), default empty
|
||||
QString logFilePath() const;
|
||||
|
||||
signals:
|
||||
void currentStepChanged();
|
||||
|
@ -281,6 +281,33 @@ def install_systemd_boot(efi_directory):
|
||||
create_loader(loader_path, distribution_translated)
|
||||
|
||||
|
||||
def get_grub_efi_parameters():
|
||||
"""
|
||||
Returns a 3-tuple of suitable parameters for GRUB EFI installation,
|
||||
depending on the host machine architecture. The return is
|
||||
- target name
|
||||
- grub.efi name
|
||||
- boot.efi name
|
||||
all three are strings. May return None if there is no suitable
|
||||
set for the current machine. May return unsuitable values if the
|
||||
host architecture is unknown (e.g. defaults to x86_64).
|
||||
"""
|
||||
import platform
|
||||
efi_bitness = efi_word_size()
|
||||
cpu_type = platform.machine()
|
||||
|
||||
if efi_bitness == "32":
|
||||
# Assume all 32-bitters are legacy x86
|
||||
return ("i386-efi", "grubia32.efi", "bootia32.efi")
|
||||
elif efi_bitness == "64" and cpu_type == "aarch64":
|
||||
return ("arm64-efi", "grubaa64.efi", "bootaa64.efi")
|
||||
elif efi_bitness == "64":
|
||||
# If it's not ARM, must by AMD64
|
||||
return ("x86_64-efi", "grubx64.efi", "bootx64.efi")
|
||||
libcalamares.utils.warning("Could not find GRUB parameters for bits {b} and cpu {c}".format(b=repr(efi_bitness), c=repr(cpu_type)))
|
||||
return None
|
||||
|
||||
|
||||
def install_grub(efi_directory, fw_type):
|
||||
"""
|
||||
Installs grub as bootloader, either in pc or efi mode.
|
||||
@ -297,16 +324,8 @@ def install_grub(efi_directory, fw_type):
|
||||
os.makedirs(install_efi_directory)
|
||||
|
||||
efi_bootloader_id = efi_label()
|
||||
efi_bitness = efi_word_size()
|
||||
|
||||
if efi_bitness == "32":
|
||||
efi_target = "i386-efi"
|
||||
efi_grub_file = "grubia32.efi"
|
||||
efi_boot_file = "bootia32.efi"
|
||||
elif efi_bitness == "64":
|
||||
efi_target = "x86_64-efi"
|
||||
efi_grub_file = "grubx64.efi"
|
||||
efi_boot_file = "bootx64.efi"
|
||||
efi_target, efi_grub_file, efi_boot_file = get_grub_efi_parameters()
|
||||
|
||||
check_target_env_call([libcalamares.job.configuration["grubInstall"],
|
||||
"--target=" + efi_target,
|
||||
|
@ -7,3 +7,5 @@
|
||||
ru us - ruwin_alt_sh-UTF-8
|
||||
ua us - ua-utf
|
||||
gr us - gr
|
||||
he us - he
|
||||
ar us - ar
|
||||
|
@ -168,7 +168,7 @@ Column {
|
||||
hoverEnabled: true
|
||||
property var coordinate: map.toCoordinate(Qt.point(mouseX, mouseY))
|
||||
Label {
|
||||
x: parent.mouseX - width
|
||||
x: parent.mouseX - width -5
|
||||
y: parent.mouseY - height - 5
|
||||
text: "%1, %2".arg(
|
||||
parent.coordinate.latitude).arg(parent.coordinate.longitude)
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
*/
|
||||
void updateGlobalStorage( const QStringList& selected ) const;
|
||||
/// As updateGlobalStorage() with an empty selection list
|
||||
void updateGlobalStorage() const { updateGlobalStorage( QStringList() ); }
|
||||
void fillGSSecondaryConfiguration() const { updateGlobalStorage( QStringList() ); }
|
||||
|
||||
private:
|
||||
PackageListModel* m_model = nullptr;
|
||||
|
@ -49,9 +49,11 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND
|
||||
TYPE viewmodule
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
Config.cpp
|
||||
PartitionViewStep.cpp
|
||||
|
||||
core/BootLoaderModel.cpp
|
||||
core/ColorUtils.cpp
|
||||
core/Config.cpp
|
||||
core/DeviceList.cpp
|
||||
core/DeviceModel.cpp
|
||||
core/KPMHelpers.cpp
|
||||
@ -75,7 +77,6 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND
|
||||
gui/PartitionLabelsView.cpp
|
||||
gui/PartitionSizeController.cpp
|
||||
gui/PartitionSplitterWidget.cpp
|
||||
gui/PartitionViewStep.cpp
|
||||
gui/ResizeVolumeGroupDialog.cpp
|
||||
gui/ScanningDialog.cpp
|
||||
gui/ReplaceWidget.cpp
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "core/PartUtils.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/Logger.h"
|
||||
@ -180,7 +182,7 @@ Config::setInstallChoice( InstallChoice c )
|
||||
if ( c != m_installChoice )
|
||||
{
|
||||
m_installChoice = c;
|
||||
emit installChoiceChanged( c );
|
||||
Q_EMIT installChoiceChanged( c );
|
||||
::updateGlobalStorage( c, m_swapChoice );
|
||||
}
|
||||
}
|
||||
@ -202,16 +204,98 @@ Config::setSwapChoice( Config::SwapChoice c )
|
||||
if ( c != m_swapChoice )
|
||||
{
|
||||
m_swapChoice = c;
|
||||
emit swapChoiceChanged( c );
|
||||
Q_EMIT swapChoiceChanged( c );
|
||||
::updateGlobalStorage( m_installChoice, c );
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Config::allowManualPartitioning() const
|
||||
void
|
||||
Config::setEraseFsTypeChoice( const QString& choice )
|
||||
{
|
||||
QString canonicalChoice = PartUtils::canonicalFilesystemName( choice, nullptr );
|
||||
if ( canonicalChoice != m_eraseFsTypeChoice )
|
||||
{
|
||||
m_eraseFsTypeChoice = canonicalChoice;
|
||||
Q_EMIT eraseModeFilesystemChanged( canonicalChoice );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configurationMap )
|
||||
{
|
||||
// Set up firmwareType global storage entry. This is used, e.g. by the bootloader module.
|
||||
QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) );
|
||||
gs->insert( "firmwareType", firmwareType );
|
||||
|
||||
gs->insert( "efiSystemPartition", CalamaresUtils::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) ) );
|
||||
|
||||
// Read and parse key efiSystemPartitionSize
|
||||
if ( configurationMap.contains( "efiSystemPartitionSize" ) )
|
||||
{
|
||||
gs->insert( "efiSystemPartitionSize", CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ) );
|
||||
}
|
||||
|
||||
// Read and parse key efiSystemPartitionName
|
||||
if ( configurationMap.contains( "efiSystemPartitionName" ) )
|
||||
{
|
||||
gs->insert( "efiSystemPartitionName", CalamaresUtils::getString( configurationMap, "efiSystemPartitionName" ) );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::fillConfigurationFSTypes(const QVariantMap& configurationMap)
|
||||
{
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
return gs->value( "allowManualPartitioning" ).toBool();
|
||||
|
||||
|
||||
// The defaultFileSystemType setting needs a bit more processing,
|
||||
// as we want to cover various cases (such as different cases)
|
||||
QString fsName = CalamaresUtils::getString( configurationMap, "defaultFileSystemType" );
|
||||
QString fsRealName;
|
||||
FileSystem::Type fsType = FileSystem::Type::Unknown;
|
||||
if ( fsName.isEmpty() )
|
||||
{
|
||||
cWarning() << "Partition-module setting *defaultFileSystemType* is missing, will use ext4";
|
||||
fsRealName = PartUtils::canonicalFilesystemName( QStringLiteral("ext4"), &fsType );
|
||||
}
|
||||
else
|
||||
{
|
||||
fsRealName = PartUtils::canonicalFilesystemName( fsName, &fsType );
|
||||
if ( fsType == FileSystem::Type::Unknown )
|
||||
{
|
||||
cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << fsName << ") using ext4 instead";
|
||||
fsRealName = PartUtils::canonicalFilesystemName( QStringLiteral("ext4"), &fsType );
|
||||
}
|
||||
else if ( fsRealName != fsName )
|
||||
{
|
||||
cWarning() << "Partition-module setting *defaultFileSystemType* changed to" << fsRealName;
|
||||
}
|
||||
}
|
||||
Q_ASSERT( fsType != FileSystem::Type::Unknown );
|
||||
m_defaultFsType = fsType;
|
||||
gs->insert( "defaultFileSystemType", fsRealName );
|
||||
|
||||
// TODO: canonicalize the names? How is translation supposed to work?
|
||||
m_eraseFsTypes = CalamaresUtils::getStringList( configurationMap, "availableFileSystemTypes" );
|
||||
if ( !m_eraseFsTypes.contains( fsRealName ) )
|
||||
{
|
||||
if ( !m_eraseFsTypes.isEmpty() )
|
||||
{
|
||||
// Explicitly set, and doesn't include the default
|
||||
cWarning() << "Partition-module *availableFileSystemTypes* does not contain the default" << fsRealName;
|
||||
m_eraseFsTypes.prepend( fsRealName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not explicitly set, so it's empty; don't complain
|
||||
m_eraseFsTypes = QStringList { fsRealName };
|
||||
}
|
||||
}
|
||||
|
||||
Q_ASSERT( !m_eraseFsTypes.isEmpty() );
|
||||
Q_ASSERT( m_eraseFsTypes.contains( fsRealName ) );
|
||||
m_eraseFsTypeChoice = fsRealName;
|
||||
Q_EMIT eraseModeFilesystemChanged( m_eraseFsTypeChoice );
|
||||
}
|
||||
|
||||
|
||||
@ -236,27 +320,18 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
}
|
||||
setSwapChoice( m_initialSwapChoice );
|
||||
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
gs->insert( "allowManualPartitioning",
|
||||
CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true ) );
|
||||
m_allowManualPartitioning = CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true );
|
||||
|
||||
if ( configurationMap.contains( "requiredPartitionTableType" )
|
||||
&& configurationMap.value( "requiredPartitionTableType" ).type() == QVariant::List )
|
||||
{
|
||||
m_requiredPartitionTableType.clear();
|
||||
m_requiredPartitionTableType.append( configurationMap.value( "requiredPartitionTableType" ).toStringList() );
|
||||
}
|
||||
else if ( configurationMap.contains( "requiredPartitionTableType" )
|
||||
&& configurationMap.value( "requiredPartitionTableType" ).type() == QVariant::String )
|
||||
{
|
||||
m_requiredPartitionTableType.clear();
|
||||
m_requiredPartitionTableType.append( configurationMap.value( "requiredPartitionTableType" ).toString() );
|
||||
}
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
m_requiredPartitionTableType = CalamaresUtils::getStringList( configurationMap, "requiredPartitionTableType" );
|
||||
gs->insert( "requiredPartitionTableType", m_requiredPartitionTableType );
|
||||
|
||||
fillGSConfigurationEFI(gs, configurationMap);
|
||||
fillConfigurationFSTypes( configurationMap );
|
||||
}
|
||||
|
||||
void
|
||||
Config::updateGlobalStorage() const
|
||||
Config::fillGSSecondaryConfiguration() const
|
||||
{
|
||||
// If there's no setting (e.g. from the welcome page) for required storage
|
||||
// then use ours, if it was set.
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include "utils/NamedEnum.h"
|
||||
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
|
||||
@ -24,6 +26,9 @@ class Config : public QObject
|
||||
///@brief The swap choice (None, Small, Hibernate, ...) which only makes sense when Erase is chosen
|
||||
Q_PROPERTY( SwapChoice swapChoice READ swapChoice WRITE setSwapChoice NOTIFY swapChoiceChanged )
|
||||
|
||||
///@brief Name of the FS that will be used when erasing type disk (e.g. "default filesystem")
|
||||
Q_PROPERTY( QString eraseModeFilesystem READ eraseFsType WRITE setEraseFsTypeChoice NOTIFY eraseModeFilesystemChanged )
|
||||
|
||||
Q_PROPERTY( bool allowManualPartitioning READ allowManualPartitioning CONSTANT FINAL )
|
||||
|
||||
public:
|
||||
@ -54,8 +59,19 @@ public:
|
||||
static const NamedEnumTable< SwapChoice >& swapChoiceNames();
|
||||
using SwapChoiceSet = QSet< SwapChoice >;
|
||||
|
||||
using EraseFsTypesSet = QStringList;
|
||||
|
||||
void setConfigurationMap( const QVariantMap& );
|
||||
void updateGlobalStorage() const;
|
||||
/** @brief Set GS values where other modules configuration has priority
|
||||
*
|
||||
* Some "required" values are duplicated between modules; if some
|
||||
* othe module hasn't already set the GS value, take a value from
|
||||
* the partitioning configuration.
|
||||
*
|
||||
* Applicable GS keys:
|
||||
* - requiredStorageGiB
|
||||
*/
|
||||
void fillGSSecondaryConfiguration() const;
|
||||
|
||||
/** @brief What kind of installation (partitioning) is requested **initially**?
|
||||
*
|
||||
@ -94,20 +110,44 @@ public:
|
||||
*/
|
||||
SwapChoice swapChoice() const { return m_swapChoice; }
|
||||
|
||||
///@brief Is manual partitioning allowed (not explicitly disnabled in the config file)?
|
||||
bool allowManualPartitioning() const;
|
||||
/** @brief Get the list of configured FS types to use with *erase* mode
|
||||
*
|
||||
* This list is not empty.
|
||||
*/
|
||||
EraseFsTypesSet eraseFsTypes() const { return m_eraseFsTypes; }
|
||||
|
||||
/** @brief Currently-selected FS type for *erase* mode
|
||||
*/
|
||||
QString eraseFsType() const { return m_eraseFsTypeChoice; }
|
||||
|
||||
/** @brief Configured default FS type (for other modes than erase)
|
||||
*
|
||||
* This is not "Unknown" or "Unformatted"
|
||||
*/
|
||||
FileSystem::Type defaultFsType() const { return m_defaultFsType; }
|
||||
|
||||
///@brief Is manual partitioning allowed (not explicitly disabled in the config file)?
|
||||
bool allowManualPartitioning() const { return m_allowManualPartitioning; }
|
||||
|
||||
public Q_SLOTS:
|
||||
void setInstallChoice( int ); ///< Translates a button ID or so to InstallChoice
|
||||
void setInstallChoice( InstallChoice );
|
||||
void setSwapChoice( int ); ///< Translates a button ID or so to SwapChoice
|
||||
void setSwapChoice( SwapChoice );
|
||||
void setEraseFsTypeChoice( const QString& filesystemName ); ///< See property eraseModeFilesystem
|
||||
|
||||
Q_SIGNALS:
|
||||
void installChoiceChanged( InstallChoice );
|
||||
void swapChoiceChanged( SwapChoice );
|
||||
void eraseModeFilesystemChanged( const QString& );
|
||||
|
||||
private:
|
||||
/** @brief Handle FS-type configuration, for erase and default */
|
||||
void fillConfigurationFSTypes( const QVariantMap& configurationMap );
|
||||
EraseFsTypesSet m_eraseFsTypes;
|
||||
QString m_eraseFsTypeChoice;
|
||||
FileSystem::Type m_defaultFsType;
|
||||
|
||||
SwapChoiceSet m_swapChoices;
|
||||
SwapChoice m_initialSwapChoice = NoSwap;
|
||||
SwapChoice m_swapChoice = NoSwap;
|
||||
@ -115,6 +155,8 @@ private:
|
||||
InstallChoice m_installChoice = NoChoice;
|
||||
qreal m_requiredStorageGiB = 0.0; // May duplicate setting in the welcome module
|
||||
QStringList m_requiredPartitionTableType;
|
||||
|
||||
bool m_allowManualPartitioning = true;
|
||||
};
|
||||
|
||||
/** @brief Given a set of swap choices, return a sensible value from it.
|
@ -11,10 +11,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gui/PartitionViewStep.h"
|
||||
#include "PartitionViewStep.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "core/BootLoaderModel.h"
|
||||
#include "core/Config.h"
|
||||
#include "core/DeviceModel.h"
|
||||
#include "core/PartitionCoreModule.h"
|
||||
#include "gui/ChoicePage.h"
|
||||
@ -327,7 +327,7 @@ PartitionViewStep::isNextEnabled() const
|
||||
void
|
||||
PartitionViewStep::nextPossiblyChanged( bool )
|
||||
{
|
||||
emit nextStatusChanged( isNextEnabled() );
|
||||
Q_EMIT nextStatusChanged( isNextEnabled() );
|
||||
}
|
||||
|
||||
bool
|
||||
@ -368,7 +368,7 @@ PartitionViewStep::isAtEnd() const
|
||||
void
|
||||
PartitionViewStep::onActivate()
|
||||
{
|
||||
m_config->updateGlobalStorage();
|
||||
m_config->fillGSSecondaryConfiguration();
|
||||
|
||||
// if we're coming back to PVS from the next VS
|
||||
if ( m_widget->currentWidget() == m_choicePage && m_config->installChoice() == Config::InstallChoice::Alongside )
|
||||
@ -403,8 +403,7 @@ shouldWarnForGPTOnBIOS( const PartitionCoreModule* core )
|
||||
&& ( partition->fileSystem().type() == FileSystem::Unformatted )
|
||||
&& ( partition->capacity() >= 8_MiB ) )
|
||||
{
|
||||
cDebug() << Logger::SubEntry << "Partition" << partition->devicePath()
|
||||
<< partition->partitionPath()
|
||||
cDebug() << Logger::SubEntry << "Partition" << partition->devicePath() << partition->partitionPath()
|
||||
<< "is a suitable bios_grub partition";
|
||||
return false;
|
||||
}
|
||||
@ -542,32 +541,11 @@ PartitionViewStep::onLeave()
|
||||
void
|
||||
PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
Logger::Once o;
|
||||
|
||||
m_config->setConfigurationMap( configurationMap );
|
||||
|
||||
// Copy the efiSystemPartition setting to the global storage. It is needed not only in
|
||||
// the EraseDiskPage, but also in the bootloader configuration modules (grub, bootloader).
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
QString efiSP = CalamaresUtils::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) );
|
||||
gs->insert( "efiSystemPartition", efiSP );
|
||||
|
||||
// Set up firmwareType global storage entry. This is used, e.g. by the bootloader module.
|
||||
QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) );
|
||||
cDebug() << o << "Setting firmwareType to" << firmwareType;
|
||||
gs->insert( "firmwareType", firmwareType );
|
||||
|
||||
// Read and parse key efiSystemPartitionSize
|
||||
if ( configurationMap.contains( "efiSystemPartitionSize" ) )
|
||||
{
|
||||
gs->insert( "efiSystemPartitionSize", CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ) );
|
||||
}
|
||||
|
||||
// Read and parse key efiSystemPartitionName
|
||||
if ( configurationMap.contains( "efiSystemPartitionName" ) )
|
||||
{
|
||||
gs->insert( "efiSystemPartitionName", CalamaresUtils::getString( configurationMap, "efiSystemPartitionName" ) );
|
||||
}
|
||||
|
||||
// Read and parse key swapPartitionName
|
||||
if ( configurationMap.contains( "swapPartitionName" ) )
|
||||
@ -583,30 +561,6 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
gs->insert( "enableLuksAutomatedPartitioning",
|
||||
CalamaresUtils::getBool( configurationMap, "enableLuksAutomatedPartitioning", true ) );
|
||||
|
||||
// The defaultFileSystemType setting needs a bit more processing,
|
||||
// as we want to cover various cases (such as different cases)
|
||||
QString fsName = CalamaresUtils::getString( configurationMap, "defaultFileSystemType" );
|
||||
FileSystem::Type fsType;
|
||||
if ( fsName.isEmpty() )
|
||||
{
|
||||
cWarning() << "Partition-module setting *defaultFileSystemType* is missing, will use ext4";
|
||||
}
|
||||
QString fsRealName = PartUtils::findFS( fsName, &fsType );
|
||||
if ( fsRealName == fsName )
|
||||
{
|
||||
cDebug() << o << "Partition-module setting *defaultFileSystemType*" << fsRealName;
|
||||
}
|
||||
else if ( fsType != FileSystem::Unknown )
|
||||
{
|
||||
cWarning() << "Partition-module setting *defaultFileSystemType* changed" << fsRealName;
|
||||
}
|
||||
else
|
||||
{
|
||||
cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << fsName << ") using" << fsRealName
|
||||
<< "instead.";
|
||||
}
|
||||
gs->insert( "defaultFileSystemType", fsRealName );
|
||||
|
||||
QString partitionTableName = CalamaresUtils::getString( configurationMap, "defaultPartitionTableType" );
|
||||
if ( partitionTableName.isEmpty() )
|
||||
{
|
||||
@ -628,7 +582,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule );
|
||||
m_future->setFuture( future );
|
||||
|
||||
m_core->initLayout( fsType == FileSystem::Unknown ? FileSystem::Ext4 : fsType,
|
||||
m_core->initLayout( m_config->defaultFsType(),
|
||||
configurationMap.value( "partitionLayout" ).toList() );
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
#include "DeviceList.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "partition/PartitionIterator.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <kpmcore/backend/corebackend.h>
|
||||
#include <kpmcore/backend/corebackendmanager.h>
|
||||
|
@ -132,7 +132,7 @@ DeviceModel::swapDevice( Device* oldDevice, Device* newDevice )
|
||||
|
||||
m_devices[ indexOfOldDevice ] = newDevice;
|
||||
|
||||
emit dataChanged( index( indexOfOldDevice ), index( indexOfOldDevice ) );
|
||||
Q_EMIT dataChanged( index( indexOfOldDevice ), index( indexOfOldDevice ) );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "partition/PartitionQuery.h"
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/RAII.h"
|
||||
|
||||
#include <kpmcore/backend/corebackend.h>
|
||||
#include <kpmcore/backend/corebackendmanager.h>
|
||||
@ -177,7 +178,8 @@ canBeResized( Partition* candidate, const Logger::Once& o )
|
||||
|
||||
if ( availableStorageB > advisedStorageB )
|
||||
{
|
||||
cDebug() << o << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install.";
|
||||
cDebug() << o << "Partition" << convenienceName( candidate )
|
||||
<< "authorized for resize + autopartition install.";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -412,8 +414,14 @@ runOsprober( DeviceModel* dm )
|
||||
FstabEntryList fstabEntries = lookForFstabEntries( path );
|
||||
QString homePath = findPartitionPathForMountPoint( fstabEntries, "/home" );
|
||||
|
||||
osproberEntries.append(
|
||||
{ prettyName, path, file, QString(), canBeResized( dm, path, o ), lineColumns, fstabEntries, homePath } );
|
||||
osproberEntries.append( { prettyName,
|
||||
path,
|
||||
file,
|
||||
QString(),
|
||||
canBeResized( dm, path, o ),
|
||||
lineColumns,
|
||||
fstabEntries,
|
||||
homePath } );
|
||||
osproberCleanLines.append( line );
|
||||
}
|
||||
}
|
||||
@ -472,21 +480,19 @@ isEfiBootable( const Partition* candidate )
|
||||
}
|
||||
|
||||
QString
|
||||
findFS( QString fsName, FileSystem::Type* fsType )
|
||||
canonicalFilesystemName( const QString& fsName, FileSystem::Type* fsType )
|
||||
{
|
||||
QStringList fsLanguage { QLatin1String( "C" ) }; // Required language list to turn off localization
|
||||
cPointerSetter type( fsType );
|
||||
if ( fsName.isEmpty() )
|
||||
{
|
||||
fsName = QStringLiteral( "ext4" );
|
||||
type = FileSystem::Ext4;
|
||||
return QStringLiteral( "ext4" );
|
||||
}
|
||||
|
||||
FileSystem::Type tmpType = FileSystem::typeForName( fsName, fsLanguage );
|
||||
if ( tmpType != FileSystem::Unknown )
|
||||
QStringList fsLanguage { QLatin1String( "C" ) }; // Required language list to turn off localization
|
||||
|
||||
if ( ( type = FileSystem::typeForName( fsName, fsLanguage ) ) != FileSystem::Unknown )
|
||||
{
|
||||
if ( fsType )
|
||||
{
|
||||
*fsType = tmpType;
|
||||
}
|
||||
return fsName;
|
||||
}
|
||||
|
||||
@ -506,7 +512,6 @@ findFS( QString fsName, FileSystem::Type* fsType )
|
||||
}
|
||||
|
||||
cWarning() << "Filesystem" << fsName << "not found, using ext4";
|
||||
fsName = QStringLiteral( "ext4" );
|
||||
// fsType can be used to check whether fsName was a valid filesystem.
|
||||
if ( fsType )
|
||||
{
|
||||
@ -526,7 +531,8 @@ findFS( QString fsName, FileSystem::Type* fsType )
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return fsName;
|
||||
type = FileSystem::Unknown;
|
||||
return QStringLiteral( "ext4" );
|
||||
}
|
||||
|
||||
} // namespace PartUtils
|
||||
|
@ -91,11 +91,13 @@ bool isEfiBootable( const Partition* candidate );
|
||||
/** @brief translate @p fsName into a recognized name and type
|
||||
*
|
||||
* Makes several attempts to translate the string into a
|
||||
* name that KPMCore will recognize.
|
||||
* name that KPMCore will recognize. Returns the canonical
|
||||
* filesystem name (e.g. asking for "EXT4" will return "ext4").
|
||||
*
|
||||
* The corresponding filesystem type is stored in @p fsType, and
|
||||
* its value is FileSystem::Unknown if @p fsName is not recognized.
|
||||
*/
|
||||
QString findFS( QString fsName, FileSystem::Type* fsType );
|
||||
QString canonicalFilesystemName( const QString& fsName, FileSystem::Type* fsType );
|
||||
|
||||
} // namespace PartUtils
|
||||
|
||||
|
@ -16,13 +16,12 @@
|
||||
#include "core/PartitionCoreModule.h"
|
||||
#include "core/PartitionInfo.h"
|
||||
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
#include "utils/NamedEnum.h"
|
||||
#include "utils/Units.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/NamedEnum.h"
|
||||
#include "utils/Units.h"
|
||||
|
||||
#include <kpmcore/core/device.h>
|
||||
#include <kpmcore/core/partition.h>
|
||||
@ -109,6 +108,12 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
|
||||
partType = isEfi ? PartitionTable::gpt : PartitionTable::msdos;
|
||||
}
|
||||
|
||||
// Looking up the defaultFsType (which should name a filesystem type)
|
||||
// will log an error and set the type to Unknown if there's something wrong.
|
||||
FileSystem::Type type = FileSystem::Unknown;
|
||||
PartUtils::canonicalFilesystemName( o.defaultFsType, &type );
|
||||
core->initLayout( type == FileSystem::Unknown ? FileSystem::Ext4 : type );
|
||||
|
||||
core->createPartitionTable( dev, partType );
|
||||
|
||||
if ( isEfi )
|
||||
|
@ -10,7 +10,7 @@
|
||||
#ifndef PARTITIONACTIONS_H
|
||||
#define PARTITIONACTIONS_H
|
||||
|
||||
#include "core/Config.h"
|
||||
#include "Config.h"
|
||||
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
|
@ -687,7 +687,7 @@ void
|
||||
PartitionCoreModule::refreshPartition( Device* device, Partition* )
|
||||
{
|
||||
// Keep it simple for now: reset the model. This can be improved to cause
|
||||
// the model to emit dataChanged() for the affected row instead, avoiding
|
||||
// the model to Q_EMIT dataChanged() for the affected row instead, avoiding
|
||||
// the loss of the current selection.
|
||||
auto model = partitionModelForDevice( device );
|
||||
Q_ASSERT( model );
|
||||
@ -966,7 +966,7 @@ PartitionCoreModule::revert()
|
||||
m_deviceInfos.clear();
|
||||
doInit();
|
||||
updateIsDirty();
|
||||
emit reverted();
|
||||
Q_EMIT reverted();
|
||||
}
|
||||
|
||||
|
||||
@ -1040,7 +1040,7 @@ PartitionCoreModule::revertDevice( Device* dev, bool individualRevert )
|
||||
{
|
||||
refreshAfterModelChange();
|
||||
}
|
||||
emit deviceReverted( newDev );
|
||||
Q_EMIT deviceReverted( newDev );
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ PartitionLayout::PartitionEntry::PartitionEntry( const QString& label,
|
||||
, partMinSize( minSize )
|
||||
, partMaxSize( maxSize )
|
||||
{
|
||||
PartUtils::findFS( fs, &partFileSystem );
|
||||
PartUtils::canonicalFilesystemName( fs, &partFileSystem );
|
||||
}
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ PartitionLayout::addEntry( const PartitionEntry& entry )
|
||||
void
|
||||
PartitionLayout::init( FileSystem::Type defaultFsType, const QVariantList& config )
|
||||
{
|
||||
bool ok;
|
||||
bool ok = true; // bogus argument to getSubMap()
|
||||
|
||||
m_partLayout.clear();
|
||||
|
||||
@ -130,10 +130,71 @@ PartitionLayout::init( FileSystem::Type defaultFsType, const QVariantList& confi
|
||||
|
||||
if ( !m_partLayout.count() )
|
||||
{
|
||||
addEntry( { defaultFsType, QString( "/" ), QString( "100%" ) } );
|
||||
// Unknown will be translated to defaultFsType at apply-time
|
||||
addEntry( { FileSystem::Type::Unknown, QString( "/" ), QString( "100%" ) } );
|
||||
}
|
||||
|
||||
setDefaultFsType( defaultFsType );
|
||||
}
|
||||
|
||||
void
|
||||
PartitionLayout::setDefaultFsType(FileSystem::Type defaultFsType)
|
||||
{
|
||||
using T = FileSystem::Type;
|
||||
switch ( defaultFsType )
|
||||
{
|
||||
case T::Unknown:
|
||||
case T::Unformatted:
|
||||
case T::Extended:
|
||||
case T::LinuxSwap:
|
||||
case T::Luks:
|
||||
case T::Ocfs2:
|
||||
case T::Lvm2_PV:
|
||||
case T::Udf:
|
||||
case T::Iso9660:
|
||||
case T::Luks2:
|
||||
case T::LinuxRaidMember:
|
||||
case T::BitLocker:
|
||||
// bad bad
|
||||
cWarning() << "The selected default FS" << defaultFsType << "is not suitable." << "Using ext4 instead.";
|
||||
defaultFsType = T::Ext4;
|
||||
break;
|
||||
case T::Ext2:
|
||||
case T::Ext3:
|
||||
case T::Ext4:
|
||||
case T::Fat32:
|
||||
case T::Ntfs:
|
||||
case T::Reiser4:
|
||||
case T::ReiserFS:
|
||||
case T::Xfs:
|
||||
case T::Jfs:
|
||||
case T::Btrfs:
|
||||
case T::Exfat:
|
||||
case T::F2fs:
|
||||
// ok
|
||||
break;
|
||||
case T::Fat12:
|
||||
case T::Fat16:
|
||||
case T::Hfs:
|
||||
case T::HfsPlus:
|
||||
case T::Ufs:
|
||||
case T::Hpfs:
|
||||
case T::Zfs:
|
||||
case T::Nilfs2:
|
||||
case T::Apfs:
|
||||
case T::Minix:
|
||||
// weird
|
||||
cWarning() << "The selected default FS" << defaultFsType << "is unusual, but not wrong.";
|
||||
break;
|
||||
default:
|
||||
cWarning() << "The selected default FS" << defaultFsType << "is not known to Calamares." << "Using ext4 instead.";
|
||||
defaultFsType = T::Ext4;
|
||||
}
|
||||
|
||||
m_defaultFsType = defaultFsType;
|
||||
}
|
||||
|
||||
|
||||
QList< Partition* >
|
||||
PartitionLayout::createPartitions( Device* dev,
|
||||
qint64 firstSector,
|
||||
@ -142,6 +203,9 @@ PartitionLayout::createPartitions( Device* dev,
|
||||
PartitionNode* parent,
|
||||
const PartitionRole& role )
|
||||
{
|
||||
// Make sure the default FS is sensible; warn and use ext4 if not
|
||||
setDefaultFsType( m_defaultFsType );
|
||||
|
||||
QList< Partition* > partList;
|
||||
// Map each partition entry to its requested size (0 when calculated later)
|
||||
QMap< const PartitionLayout::PartitionEntry*, qint64 > partSectorsMap;
|
||||
@ -210,6 +274,8 @@ PartitionLayout::createPartitions( Device* dev,
|
||||
}
|
||||
}
|
||||
|
||||
auto correctFS = [d=m_defaultFsType]( FileSystem::Type t ) { return t == FileSystem::Type::Unknown ? d : t; };
|
||||
|
||||
// Create the partitions.
|
||||
currentSector = firstSector;
|
||||
availableSectors = totalSectors;
|
||||
@ -229,7 +295,7 @@ PartitionLayout::createPartitions( Device* dev,
|
||||
part = KPMHelpers::createNewPartition( parent,
|
||||
*dev,
|
||||
role,
|
||||
entry.partFileSystem,
|
||||
correctFS( entry.partFileSystem ),
|
||||
entry.partLabel,
|
||||
currentSector,
|
||||
currentSector + sectors - 1,
|
||||
@ -240,7 +306,7 @@ PartitionLayout::createPartitions( Device* dev,
|
||||
part = KPMHelpers::createNewEncryptedPartition( parent,
|
||||
*dev,
|
||||
role,
|
||||
entry.partFileSystem,
|
||||
correctFS( entry.partFileSystem ),
|
||||
entry.partLabel,
|
||||
currentSector,
|
||||
currentSector + sectors - 1,
|
||||
|
@ -87,11 +87,28 @@ public:
|
||||
*
|
||||
* @p config is a list of partition entries (in QVariant form,
|
||||
* read from YAML). If no entries are given, then a single
|
||||
* partition is created with the given @p defaultFsType
|
||||
* partition is created with type Unkown.
|
||||
*
|
||||
* Any partitions with FS type Unknown will get the default filesystem
|
||||
* that is set at **apply** time (e.g. when createPartitions() is
|
||||
* called as well.
|
||||
*
|
||||
* @see setDefaultFsType()
|
||||
*/
|
||||
void init( FileSystem::Type defaultFsType, const QVariantList& config );
|
||||
/** @brief add an entry as if it had been listed in the config
|
||||
*
|
||||
* The same comments about filesystem type apply.
|
||||
*/
|
||||
bool addEntry( const PartitionEntry& entry );
|
||||
|
||||
/** @brief set the default filesystem type
|
||||
*
|
||||
* Any partitions in the layout with type Unknown will get
|
||||
* the default type when createPartitions() is called.
|
||||
*/
|
||||
void setDefaultFsType( FileSystem::Type defaultFsType );
|
||||
|
||||
/**
|
||||
* @brief Apply the current partition layout to the selected drive space.
|
||||
* @return A list of Partition objects.
|
||||
@ -105,6 +122,7 @@ public:
|
||||
|
||||
private:
|
||||
QList< PartitionEntry > m_partLayout;
|
||||
FileSystem::Type m_defaultFsType = FileSystem::Type::Unknown;
|
||||
};
|
||||
|
||||
#endif /* PARTITIONLAYOUT_H */
|
||||
|
@ -327,5 +327,5 @@ PartitionModel::partitionForIndex( const QModelIndex& index ) const
|
||||
void
|
||||
PartitionModel::update()
|
||||
{
|
||||
emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
|
||||
Q_EMIT dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
/**
|
||||
* This helper class must be instantiated on the stack *before* making
|
||||
* changes to the device represented by this model. It will cause the model
|
||||
* to emit modelAboutToBeReset() when instantiated and modelReset() when
|
||||
* to Q_EMIT modelAboutToBeReset() when instantiated and modelReset() when
|
||||
* destructed.
|
||||
*/
|
||||
class ResetHelper
|
||||
|
@ -11,15 +11,9 @@
|
||||
|
||||
#include "ChoicePage.h"
|
||||
|
||||
#include "BootInfoWidget.h"
|
||||
#include "DeviceInfoWidget.h"
|
||||
#include "PartitionBarsView.h"
|
||||
#include "PartitionLabelsView.h"
|
||||
#include "PartitionSplitterWidget.h"
|
||||
#include "ReplaceWidget.h"
|
||||
#include "ScanningDialog.h"
|
||||
#include "Config.h"
|
||||
|
||||
#include "core/BootLoaderModel.h"
|
||||
#include "core/Config.h"
|
||||
#include "core/DeviceModel.h"
|
||||
#include "core/KPMHelpers.h"
|
||||
#include "core/OsproberEntry.h"
|
||||
@ -28,6 +22,13 @@
|
||||
#include "core/PartitionCoreModule.h"
|
||||
#include "core/PartitionInfo.h"
|
||||
#include "core/PartitionModel.h"
|
||||
#include "gui/BootInfoWidget.h"
|
||||
#include "gui/DeviceInfoWidget.h"
|
||||
#include "gui/PartitionBarsView.h"
|
||||
#include "gui/PartitionLabelsView.h"
|
||||
#include "gui/PartitionSplitterWidget.h"
|
||||
#include "gui/ReplaceWidget.h"
|
||||
#include "gui/ScanningDialog.h"
|
||||
|
||||
#include "Branding.h"
|
||||
#include "GlobalStorage.h"
|
||||
@ -144,7 +145,8 @@ ChoicePage::~ChoicePage() {}
|
||||
* this avoids cases where the popup would truncate data being drawn
|
||||
* because the overall box is sized too narrow.
|
||||
*/
|
||||
void setModelToComboBox( QComboBox* box, QAbstractItemModel* model )
|
||||
void
|
||||
setModelToComboBox( QComboBox* box, QAbstractItemModel* model )
|
||||
{
|
||||
box->setModel( model );
|
||||
if ( model->rowCount() > 0 )
|
||||
@ -268,6 +270,15 @@ ChoicePage::setupChoices()
|
||||
m_eraseButton->addOptionsComboBox( m_eraseSwapChoiceComboBox );
|
||||
}
|
||||
|
||||
if ( m_config->eraseFsTypes().count() > 1)
|
||||
{
|
||||
m_eraseFsTypesChoiceComboBox = new QComboBox;
|
||||
m_eraseFsTypesChoiceComboBox->addItems(m_config->eraseFsTypes());
|
||||
connect( m_eraseFsTypesChoiceComboBox, &QComboBox::currentTextChanged, m_config, &Config::setEraseFsTypeChoice );
|
||||
connect( m_config, &Config::eraseModeFilesystemChanged, this, &ChoicePage::onActionChanged );
|
||||
m_eraseButton->addOptionsComboBox( m_eraseFsTypesChoiceComboBox );
|
||||
}
|
||||
|
||||
m_itemsLayout->addWidget( m_alongsideButton );
|
||||
m_itemsLayout->addWidget( m_replaceButton );
|
||||
m_itemsLayout->addWidget( m_eraseButton );
|
||||
@ -292,7 +303,7 @@ ChoicePage::setupChoices()
|
||||
m_config->setInstallChoice( id );
|
||||
updateNextEnabled();
|
||||
|
||||
emit actionChosen();
|
||||
Q_EMIT actionChosen();
|
||||
}
|
||||
else // An action was unpicked, either on its own or because of another selection.
|
||||
{
|
||||
@ -302,7 +313,7 @@ ChoicePage::setupChoices()
|
||||
m_config->setInstallChoice( InstallChoice::NoChoice );
|
||||
updateNextEnabled();
|
||||
|
||||
emit actionChosen();
|
||||
Q_EMIT actionChosen();
|
||||
}
|
||||
}
|
||||
} );
|
||||
@ -425,8 +436,8 @@ ChoicePage::continueApplyDeviceChoice()
|
||||
checkInstallChoiceRadioButton( m_config->installChoice() );
|
||||
}
|
||||
|
||||
emit actionChosen();
|
||||
emit deviceChosen();
|
||||
Q_EMIT actionChosen();
|
||||
Q_EMIT deviceChosen();
|
||||
}
|
||||
|
||||
|
||||
@ -464,9 +475,8 @@ ChoicePage::applyActionChoice( InstallChoice choice )
|
||||
case InstallChoice::Erase:
|
||||
{
|
||||
auto gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
|
||||
PartitionActions::Choices::AutoPartitionOptions options { gs->value( "defaultPartitionTableType" ).toString(),
|
||||
gs->value( "defaultFileSystemType" ).toString(),
|
||||
m_config->eraseFsType(),
|
||||
m_encryptWidget->passphrase(),
|
||||
gs->value( "efiSystemPartition" ).toString(),
|
||||
CalamaresUtils::GiBtoBytes(
|
||||
@ -482,14 +492,14 @@ ChoicePage::applyActionChoice( InstallChoice choice )
|
||||
} ),
|
||||
[=] {
|
||||
PartitionActions::doAutopartition( m_core, selectedDevice(), options );
|
||||
emit deviceChosen();
|
||||
Q_EMIT deviceChosen();
|
||||
},
|
||||
this );
|
||||
}
|
||||
else
|
||||
{
|
||||
PartitionActions::doAutopartition( m_core, selectedDevice(), options );
|
||||
emit deviceChosen();
|
||||
Q_EMIT deviceChosen();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1005,7 +1015,8 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice )
|
||||
|
||||
SelectionFilter filter = []( const QModelIndex& index ) {
|
||||
return PartUtils::canBeResized(
|
||||
static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ), Logger::Once() );
|
||||
static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ),
|
||||
Logger::Once() );
|
||||
};
|
||||
m_beforePartitionBarsView->setSelectionFilter( filter );
|
||||
m_beforePartitionLabelsView->setSelectionFilter( filter );
|
||||
@ -1094,7 +1105,8 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice )
|
||||
{
|
||||
SelectionFilter filter = []( const QModelIndex& index ) {
|
||||
return PartUtils::canBeReplaced(
|
||||
static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ), Logger::Once() );
|
||||
static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ),
|
||||
Logger::Once() );
|
||||
};
|
||||
m_beforePartitionBarsView->setSelectionFilter( filter );
|
||||
m_beforePartitionLabelsView->setSelectionFilter( filter );
|
||||
@ -1592,7 +1604,7 @@ ChoicePage::updateNextEnabled()
|
||||
if ( enabled != m_nextEnabled )
|
||||
{
|
||||
m_nextEnabled = enabled;
|
||||
emit nextStatusChanged( enabled );
|
||||
Q_EMIT nextStatusChanged( enabled );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "ui_ChoicePage.h"
|
||||
|
||||
|
||||
#include "core/Config.h"
|
||||
#include "Config.h"
|
||||
#include "core/OsproberEntry.h"
|
||||
|
||||
#include <QMutex>
|
||||
@ -138,7 +138,9 @@ private:
|
||||
Calamares::PrettyRadioButton* m_eraseButton;
|
||||
Calamares::PrettyRadioButton* m_replaceButton;
|
||||
Calamares::PrettyRadioButton* m_somethingElseButton;
|
||||
QComboBox* m_eraseSwapChoiceComboBox; // UI, see also m_eraseSwapChoice
|
||||
QComboBox* m_eraseSwapChoiceComboBox = nullptr; // UI, see also Config's swap choice
|
||||
QComboBox* m_eraseFsTypesChoiceComboBox = nullptr; // UI, see also Config's erase-mode FS
|
||||
|
||||
|
||||
DeviceInfoWidget* m_deviceInfoWidget;
|
||||
|
||||
|
@ -52,7 +52,6 @@ static QSet< FileSystem::Type > s_unmountableFS( { FileSystem::Unformatted,
|
||||
|
||||
CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
PartitionNode* parentPartition,
|
||||
Partition* partition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: QDialog( parentWidget )
|
||||
@ -81,9 +80,6 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
m_ui->lvNameLineEdit->setValidator( validator );
|
||||
}
|
||||
|
||||
standardMountPoints( *( m_ui->mountPointComboBox ),
|
||||
partition ? PartitionInfo::mountPoint( partition ) : QString() );
|
||||
|
||||
if ( device->partitionTable()->type() == PartitionTable::msdos
|
||||
|| device->partitionTable()->type() == PartitionTable::msdos_sectorbased )
|
||||
{
|
||||
@ -96,7 +92,7 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
|
||||
// File system; the config value is translated (best-effort) to a type
|
||||
FileSystem::Type defaultFSType;
|
||||
QString untranslatedFSName = PartUtils::findFS(
|
||||
QString untranslatedFSName = PartUtils::canonicalFilesystemName(
|
||||
Calamares::JobQueue::instance()->globalStorage()->value( "defaultFileSystemType" ).toString(), &defaultFSType );
|
||||
if ( defaultFSType == FileSystem::Type::Unknown )
|
||||
{
|
||||
@ -132,13 +128,47 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
// Select a default
|
||||
m_ui->fsComboBox->setCurrentIndex( defaultFsIndex );
|
||||
updateMountPointUi();
|
||||
checkMountPointSelection();
|
||||
}
|
||||
|
||||
CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
const FreeSpace& freeSpacePartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: CreatePartitionDialog( device, freeSpacePartition.p->parent(), usedMountPoints, parentWidget )
|
||||
{
|
||||
standardMountPoints( *( m_ui->mountPointComboBox ), QString() );
|
||||
setFlagList( *( m_ui->m_listFlags ),
|
||||
static_cast< PartitionTable::Flags >( ~PartitionTable::Flags::Int( 0 ) ),
|
||||
partition ? PartitionInfo::flags( partition ) : PartitionTable::Flags() );
|
||||
PartitionTable::Flags() );
|
||||
initPartResizerWidget( freeSpacePartition.p );
|
||||
}
|
||||
|
||||
// Checks the initial selection.
|
||||
checkMountPointSelection();
|
||||
CreatePartitionDialog::CreatePartitionDialog( Device* device,
|
||||
const FreshPartition& existingNewPartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget )
|
||||
: CreatePartitionDialog( device, existingNewPartition.p->parent(), usedMountPoints, parentWidget )
|
||||
{
|
||||
standardMountPoints( *( m_ui->mountPointComboBox ), PartitionInfo::mountPoint( existingNewPartition.p ) );
|
||||
setFlagList( *( m_ui->m_listFlags ),
|
||||
static_cast< PartitionTable::Flags >( ~PartitionTable::Flags::Int( 0 ) ),
|
||||
PartitionInfo::flags( existingNewPartition.p ) );
|
||||
|
||||
const bool isExtended = existingNewPartition.p->roles().has( PartitionRole::Extended );
|
||||
if ( isExtended )
|
||||
{
|
||||
cDebug() << "Editing extended partitions is not supported.";
|
||||
return;
|
||||
}
|
||||
|
||||
initPartResizerWidget( existingNewPartition.p );
|
||||
|
||||
FileSystem::Type fsType = existingNewPartition.p->fileSystem().type();
|
||||
m_ui->fsComboBox->setCurrentText( FileSystem::nameForType( fsType ) );
|
||||
|
||||
setSelectedMountPoint( m_ui->mountPointComboBox, PartitionInfo::mountPoint( existingNewPartition.p ) );
|
||||
updateMountPointUi();
|
||||
}
|
||||
|
||||
CreatePartitionDialog::~CreatePartitionDialog() {}
|
||||
@ -188,7 +218,7 @@ CreatePartitionDialog::initGptPartitionTypeUi()
|
||||
}
|
||||
|
||||
Partition*
|
||||
CreatePartitionDialog::createPartition()
|
||||
CreatePartitionDialog::getNewlyCreatedPartition()
|
||||
{
|
||||
if ( m_role.roles() == PartitionRole::None )
|
||||
{
|
||||
@ -204,17 +234,21 @@ CreatePartitionDialog::createPartition()
|
||||
: FileSystem::typeForName( m_ui->fsComboBox->currentText() );
|
||||
const QString fsLabel = m_ui->filesystemLabelEdit->text();
|
||||
|
||||
// The newly-created partitions have no flags set (no **active** flags),
|
||||
// because they're new. The desired flags can be retrieved from
|
||||
// newFlags() and the consumer (see PartitionPage::onCreateClicked)
|
||||
// does so, to set up the partition for create-and-then-set-flags.
|
||||
Partition* partition = nullptr;
|
||||
QString luksPassphrase = m_ui->encryptWidget->passphrase();
|
||||
if ( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty() )
|
||||
{
|
||||
partition = KPMHelpers::createNewEncryptedPartition(
|
||||
m_parent, *m_device, m_role, fsType, fsLabel, first, last, luksPassphrase, newFlags() );
|
||||
m_parent, *m_device, m_role, fsType, fsLabel, first, last, luksPassphrase, PartitionTable::Flags() );
|
||||
}
|
||||
else
|
||||
{
|
||||
partition
|
||||
= KPMHelpers::createNewPartition( m_parent, *m_device, m_role, fsType, fsLabel, first, last, newFlags() );
|
||||
partition = KPMHelpers::createNewPartition(
|
||||
m_parent, *m_device, m_role, fsType, fsLabel, first, last, PartitionTable::Flags() );
|
||||
}
|
||||
|
||||
if ( m_device->type() == Device::Type::LVM_Device )
|
||||
@ -284,34 +318,3 @@ CreatePartitionDialog::initPartResizerWidget( Partition* partition )
|
||||
m_partitionSizeController->setPartResizerWidget( m_ui->partResizerWidget );
|
||||
m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox );
|
||||
}
|
||||
|
||||
void
|
||||
CreatePartitionDialog::initFromFreeSpace( Partition* freeSpacePartition )
|
||||
{
|
||||
initPartResizerWidget( freeSpacePartition );
|
||||
}
|
||||
|
||||
void
|
||||
CreatePartitionDialog::initFromPartitionToCreate( Partition* partition )
|
||||
{
|
||||
Q_ASSERT( partition );
|
||||
|
||||
bool isExtended = partition->roles().has( PartitionRole::Extended );
|
||||
Q_ASSERT( !isExtended );
|
||||
if ( isExtended )
|
||||
{
|
||||
cDebug() << "Editing extended partitions is not supported for now";
|
||||
return;
|
||||
}
|
||||
|
||||
initPartResizerWidget( partition );
|
||||
|
||||
// File System
|
||||
FileSystem::Type fsType = partition->fileSystem().type();
|
||||
m_ui->fsComboBox->setCurrentText( FileSystem::nameForType( fsType ) );
|
||||
|
||||
// Mount point
|
||||
setSelectedMountPoint( m_ui->mountPointComboBox, PartitionInfo::mountPoint( partition ) );
|
||||
|
||||
updateMountPointUi();
|
||||
}
|
||||
|
@ -33,31 +33,48 @@ class Ui_CreatePartitionDialog;
|
||||
class CreatePartitionDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Dialog for editing a new partition.
|
||||
|
||||
private:
|
||||
/** @brief Delegated constructor
|
||||
*
|
||||
* For the (unlikely) case that a newly created partition is being re-edited,
|
||||
* pass a pointer to that @p partition, otherwise pass nullptr.
|
||||
* This does all the shared UI setup.
|
||||
*/
|
||||
CreatePartitionDialog( Device* device,
|
||||
PartitionNode* parentPartition,
|
||||
Partition* partition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget );
|
||||
|
||||
public:
|
||||
struct FreeSpace
|
||||
{
|
||||
Partition* p;
|
||||
};
|
||||
struct FreshPartition
|
||||
{
|
||||
Partition* p;
|
||||
};
|
||||
|
||||
/** @brief Dialog for editing a new partition based on free space.
|
||||
*
|
||||
* Creating from free space makes a wholly new partition with
|
||||
* no flags set at all.
|
||||
*/
|
||||
CreatePartitionDialog( Device* device,
|
||||
const FreeSpace& freeSpacePartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget = nullptr );
|
||||
/** @brief Dialog for editing a newly-created partition.
|
||||
*
|
||||
* A partition previously newly created (e.g. via this dialog
|
||||
* and the constructor above) can be re-edited.
|
||||
*/
|
||||
CreatePartitionDialog( Device* device,
|
||||
const FreshPartition& existingNewPartition,
|
||||
const QStringList& usedMountPoints,
|
||||
QWidget* parentWidget = nullptr );
|
||||
~CreatePartitionDialog() override;
|
||||
|
||||
/**
|
||||
* Must be called when user wants to create a partition in
|
||||
* freeSpacePartition.
|
||||
*/
|
||||
void initFromFreeSpace( Partition* freeSpacePartition );
|
||||
|
||||
/**
|
||||
* Must be called when user wants to edit a to-be-created partition.
|
||||
*/
|
||||
void initFromPartitionToCreate( Partition* partition );
|
||||
Partition* createPartition();
|
||||
Partition* getNewlyCreatedPartition();
|
||||
|
||||
PartitionTable::Flags newFlags() const;
|
||||
|
||||
|
@ -97,7 +97,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device,
|
||||
m_ui->fileSystemComboBox->addItems( fsNames );
|
||||
|
||||
FileSystem::Type defaultFSType;
|
||||
QString untranslatedFSName = PartUtils::findFS(
|
||||
QString untranslatedFSName = PartUtils::canonicalFilesystemName(
|
||||
Calamares::JobQueue::instance()->globalStorage()->value( "defaultFileSystemType" ).toString(), &defaultFSType );
|
||||
if ( defaultFSType == FileSystem::Type::Unknown )
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ EncryptWidget::updateState()
|
||||
if ( newState != m_state )
|
||||
{
|
||||
m_state = newState;
|
||||
emit stateChanged( m_state );
|
||||
Q_EMIT stateChanged( m_state );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,15 @@
|
||||
QStringList
|
||||
standardMountPoints()
|
||||
{
|
||||
QStringList mountPoints { "/", "/boot", "/home", "/opt", "/srv", "/usr", "/var" };
|
||||
QStringList mountPoints { "/", "/home", "/opt", "/srv", "/usr", "/var" };
|
||||
if ( PartUtils::isEfiSystem() )
|
||||
{
|
||||
mountPoints << Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
mountPoints << QStringLiteral( "/boot" );
|
||||
}
|
||||
mountPoints.removeDuplicates();
|
||||
mountPoints.sort();
|
||||
return mountPoints;
|
||||
@ -68,11 +72,13 @@ setSelectedMountPoint( QComboBox& combo, const QString& selected )
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < combo.count(); ++i )
|
||||
{
|
||||
if ( selected == combo.itemText( i ) )
|
||||
{
|
||||
combo.setCurrentIndex( i );
|
||||
return;
|
||||
}
|
||||
}
|
||||
combo.addItem( selected );
|
||||
combo.setCurrentIndex( combo.count() - 1 );
|
||||
}
|
||||
@ -85,10 +91,12 @@ flagsFromList( const QListWidget& list )
|
||||
PartitionTable::Flags flags;
|
||||
|
||||
for ( int i = 0; i < list.count(); i++ )
|
||||
{
|
||||
if ( list.item( i )->checkState() == Qt::Checked )
|
||||
{
|
||||
flags |= static_cast< PartitionTable::Flag >( list.item( i )->data( Qt::UserRole ).toInt() );
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
@ -391,13 +391,14 @@ PartitionPage::onCreateClicked()
|
||||
return;
|
||||
}
|
||||
|
||||
CreatePartitionDialog dlg( model->device(), partition->parent(), nullptr, getCurrentUsedMountpoints(), this );
|
||||
dlg.initFromFreeSpace( partition );
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog(
|
||||
model->device(), CreatePartitionDialog::FreeSpace { partition }, getCurrentUsedMountpoints(), this );
|
||||
if ( dlg->exec() == QDialog::Accepted )
|
||||
{
|
||||
Partition* newPart = dlg.createPartition();
|
||||
m_core->createPartition( model->device(), newPart, dlg.newFlags() );
|
||||
Partition* newPart = dlg->getNewlyCreatedPartition();
|
||||
m_core->createPartition( model->device(), newPart, dlg->newFlags() );
|
||||
}
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
void
|
||||
@ -492,11 +493,10 @@ PartitionPage::updatePartitionToCreate( Device* device, Partition* partition )
|
||||
mountPoints.removeOne( PartitionInfo::mountPoint( partition ) );
|
||||
|
||||
QPointer< CreatePartitionDialog > dlg
|
||||
= new CreatePartitionDialog( device, partition->parent(), partition, mountPoints, this );
|
||||
dlg->initFromPartitionToCreate( partition );
|
||||
= new CreatePartitionDialog( device, CreatePartitionDialog::FreshPartition { partition }, mountPoints, this );
|
||||
if ( dlg->exec() == QDialog::Accepted )
|
||||
{
|
||||
Partition* newPartition = dlg->createPartition();
|
||||
Partition* newPartition = dlg->getNewlyCreatedPartition();
|
||||
m_core->deletePartition( device, partition );
|
||||
m_core->createPartition( device, newPartition, dlg->newFlags() );
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ PartitionSplitterWidget::setSplitPartition( const QString& path, qint64 minSize,
|
||||
}
|
||||
}
|
||||
|
||||
emit partitionResized( m_itemToResize.itemPath, m_itemToResize.size, m_itemToResizeNext.size );
|
||||
Q_EMIT partitionResized( m_itemToResize.itemPath, m_itemToResize.size, m_itemToResizeNext.size );
|
||||
|
||||
cDebug() << "Items updated. Status:";
|
||||
foreach ( const PartitionSplitterItem& item, m_items )
|
||||
@ -374,7 +374,7 @@ PartitionSplitterWidget::mouseMoveEvent( QMouseEvent* event )
|
||||
|
||||
repaint();
|
||||
|
||||
emit partitionResized( itemPath, m_itemToResize.size, m_itemToResizeNext.size );
|
||||
Q_EMIT partitionResized( itemPath, m_itemToResize.size, m_itemToResizeNext.size );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -311,7 +311,7 @@ ReplaceWidget::setNextEnabled( bool enabled )
|
||||
}
|
||||
|
||||
m_nextEnabled = enabled;
|
||||
emit nextStatusChanged( enabled );
|
||||
Q_EMIT nextStatusChanged( enabled );
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,5 +68,5 @@ void
|
||||
ScanningDialog::setVisible( bool visible )
|
||||
{
|
||||
QDialog::setVisible( visible );
|
||||
emit visibilityChanged();
|
||||
Q_EMIT visibilityChanged();
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ AutoMountManagementJob::prettyName() const
|
||||
Calamares::JobResult
|
||||
AutoMountManagementJob::exec()
|
||||
{
|
||||
Logger::CDebug( Logger::LOGVERBOSE ) << "this" << Logger::Pointer( this ) << "value" << Logger::Pointer( m_stored )
|
||||
cVerbose() << "this" << Logger::Pointer( this ) << "value" << Logger::Pointer( m_stored )
|
||||
<< ( m_stored ? "restore" : m_disable ? "disable" : "enable" );
|
||||
if ( m_stored )
|
||||
{
|
||||
|
@ -43,6 +43,7 @@ ClearTempMountsJob::prettyStatusMessage() const
|
||||
Calamares::JobResult
|
||||
ClearTempMountsJob::exec()
|
||||
{
|
||||
Logger::Once o;
|
||||
// Fetch a list of current mounts to Calamares temporary directories.
|
||||
QList< QPair< QString, QString > > lst;
|
||||
QFile mtab( "/etc/mtab" );
|
||||
@ -51,23 +52,27 @@ ClearTempMountsJob::exec()
|
||||
return Calamares::JobResult::error( tr( "Cannot get list of temporary mounts." ) );
|
||||
}
|
||||
|
||||
cDebug() << "Opened mtab. Lines:";
|
||||
cVerbose() << o << "Opened mtab. Lines:";
|
||||
QTextStream in( &mtab );
|
||||
QString lineIn = in.readLine();
|
||||
while ( !lineIn.isNull() )
|
||||
{
|
||||
QStringList line = lineIn.split( ' ', SplitSkipEmptyParts );
|
||||
cDebug() << line.join( ' ' );
|
||||
cVerbose() << o << line.join( ' ' );
|
||||
QString device = line.at( 0 );
|
||||
QString mountPoint = line.at( 1 );
|
||||
if ( mountPoint.startsWith( "/tmp/calamares-" ) )
|
||||
{
|
||||
cDebug() << "INSERTING pair (device, mountPoint)" << device << mountPoint;
|
||||
lst.append( qMakePair( device, mountPoint ) );
|
||||
}
|
||||
lineIn = in.readLine();
|
||||
}
|
||||
|
||||
if ( lst.empty() )
|
||||
{
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
||||
|
||||
std::sort(
|
||||
lst.begin(), lst.end(), []( const QPair< QString, QString >& a, const QPair< QString, QString >& b ) -> bool {
|
||||
return a.first > b.first;
|
||||
@ -76,10 +81,10 @@ ClearTempMountsJob::exec()
|
||||
QStringList goodNews;
|
||||
QProcess process;
|
||||
|
||||
foreach ( auto line, lst )
|
||||
for ( const auto& line : qAsConst( lst ) )
|
||||
{
|
||||
QString partPath = line.second;
|
||||
cDebug() << "Will try to umount path" << partPath;
|
||||
cDebug() << o << "Will try to umount path" << partPath;
|
||||
process.start( "umount", { "-lv", partPath } );
|
||||
process.waitForFinished();
|
||||
if ( process.exitCode() == 0 )
|
||||
@ -92,7 +97,7 @@ ClearTempMountsJob::exec()
|
||||
ok.setMessage( tr( "Cleared all temporary mounts." ) );
|
||||
ok.setDetails( goodNews.join( "\n" ) );
|
||||
|
||||
cDebug() << "ClearTempMountsJob finished. Here's what was done:\n" << goodNews.join( "\n" );
|
||||
cDebug() << o << "ClearTempMountsJob finished. Here's what was done:\n" << Logger::DebugList( goodNews );
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
@ -60,14 +60,6 @@ CreatePartitionTableJob::prettyStatusMessage() const
|
||||
}
|
||||
|
||||
|
||||
static inline QDebug&
|
||||
operator<<( QDebug&& s, PartitionIterator& it )
|
||||
{
|
||||
s << ( ( *it ) ? ( *it )->deviceNode() : QString( "<null device>" ) );
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Calamares::JobResult
|
||||
CreatePartitionTableJob::exec()
|
||||
{
|
||||
@ -75,13 +67,13 @@ CreatePartitionTableJob::exec()
|
||||
QString message = tr( "The installer failed to create a partition table on %1." ).arg( m_device->name() );
|
||||
|
||||
PartitionTable* table = m_device->partitionTable();
|
||||
cDebug() << "Creating new partition table of type" << table->typeName() << ", uncommitted yet:";
|
||||
|
||||
if ( Logger::logLevelEnabled( Logger::LOGDEBUG ) )
|
||||
{
|
||||
cDebug() << "Creating new partition table of type" << table->typeName() << ", uncommitted partitions:";
|
||||
for ( auto it = PartitionIterator::begin( table ); it != PartitionIterator::end( table ); ++it )
|
||||
{
|
||||
cDebug() << it;
|
||||
cDebug() << Logger::SubEntry << ( ( *it ) ? ( *it )->deviceNode() : QString( "<null device>" ) );
|
||||
}
|
||||
|
||||
QProcess lsblk;
|
||||
@ -89,14 +81,14 @@ CreatePartitionTableJob::exec()
|
||||
lsblk.setProcessChannelMode( QProcess::MergedChannels );
|
||||
lsblk.start();
|
||||
lsblk.waitForFinished();
|
||||
cDebug() << "lsblk:\n" << lsblk.readAllStandardOutput();
|
||||
cDebug() << Logger::SubEntry << "lsblk output:\n" << Logger::NoQuote << lsblk.readAllStandardOutput();
|
||||
|
||||
QProcess mount;
|
||||
mount.setProgram( "mount" ); // Debug output only, not mounting something
|
||||
mount.setProcessChannelMode( QProcess::MergedChannels );
|
||||
mount.start();
|
||||
mount.waitForFinished();
|
||||
cDebug() << "mount:\n" << mount.readAllStandardOutput();
|
||||
cDebug() << Logger::SubEntry << "mount output:\n" << Logger::NoQuote << mount.readAllStandardOutput();
|
||||
}
|
||||
|
||||
CreatePartitionTableOperation op( *m_device, table );
|
||||
|
@ -25,5 +25,5 @@ PartitionJob::iprogress( int percent )
|
||||
{
|
||||
percent = 100;
|
||||
}
|
||||
emit progress( qreal( percent / 100.0 ) );
|
||||
Q_EMIT progress( qreal( percent / 100.0 ) );
|
||||
}
|
||||
|
@ -144,8 +144,9 @@ SetPartFlagsJob::prettyStatusMessage() const
|
||||
Calamares::JobResult
|
||||
SetPartFlagsJob::exec()
|
||||
{
|
||||
cDebug() << "Setting flags on" << m_device->deviceNode() << "partition" << partition()->deviceNode() << "to"
|
||||
<< m_flags;
|
||||
QStringList flagsList = PartitionTable::flagNames( m_flags );
|
||||
cDebug() << "Setting flags on" << m_device->deviceNode() << "partition" << partition()->deviceNode()
|
||||
<< Logger::DebugList( flagsList );
|
||||
|
||||
Report report( nullptr );
|
||||
SetPartFlagsOperation op( *m_device, *partition(), m_flags );
|
||||
|
@ -113,12 +113,11 @@ initialSwapChoice: none
|
||||
# Restrict the installation on disks that match the type of partition
|
||||
# tables that are specified.
|
||||
#
|
||||
# Suggested values: msdos, gpt
|
||||
# If nothing is specified, Calamares defaults to both "msdos" and "mbr".
|
||||
# Possible values: msdos, gpt. Names are case-sensitive and defined by KPMCore.
|
||||
#
|
||||
# If nothing is specified, Calamares defaults to both "msdos" and "gpt".
|
||||
#
|
||||
# Names are case-sensitive and defined by KPMCore.
|
||||
# requiredPartitionTableType: gpt
|
||||
# or,
|
||||
# requiredPartitionTableType:
|
||||
# - msdos
|
||||
# - gpt
|
||||
@ -139,6 +138,17 @@ initialSwapChoice: none
|
||||
# Names are case-sensitive and defined by KPMCore.
|
||||
defaultFileSystemType: "ext4"
|
||||
|
||||
# Selectable filesystem type, used when "erase" is done.
|
||||
#
|
||||
# When erasing the disk, the *defaultFileSystemType* is used (see
|
||||
# above), but it is also possible to give users a choice:
|
||||
# list suitable filesystems here. A drop-down is provided
|
||||
# to pick which is the filesystems will be used.
|
||||
#
|
||||
# The value *defaultFileSystemType* is added to this list (with a warning)
|
||||
# if not present; the default pick is the *defaultFileSystemType*.
|
||||
availableFileSystemTypes: ["ext4", "btrfs", "f2fs"]
|
||||
|
||||
# Show/hide LUKS related functionality in automated partitioning modes.
|
||||
# Disable this if you choose not to deploy early unlocking support in GRUB2
|
||||
# and/or your distribution's initramfs solution.
|
||||
@ -205,7 +215,12 @@ defaultFileSystemType: "ext4"
|
||||
# - uuid: partition uuid (optional parameter; gpt only; requires KPMCore >= 4.2.0)
|
||||
# - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0)
|
||||
# - attributes: partition attributes (optional parameter; gpt only; requires KPMCore >= 4.2.0)
|
||||
# - filesystem: filesystem type (optional parameter; fs not created if "unformatted" or unset)
|
||||
# - filesystem: filesystem type (optional parameter)
|
||||
# - if not set at all, treat as "unformatted"
|
||||
# - if "unformatted", no filesystem will be created
|
||||
# - if "unknown" (or an unknown FS name, like "elephant") then the
|
||||
# default filesystem type, or the user's choice, will be applied instead
|
||||
# of "unknown" (e.g. the user might pick ext4, or xfs).
|
||||
# - mountPoint: partition mount point (optional parameter; not mounted if unset)
|
||||
# - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB)
|
||||
# or
|
||||
|
@ -18,6 +18,8 @@ properties:
|
||||
alwaysShowPartitionLabels: { type: boolean, default: true }
|
||||
|
||||
defaultFileSystemType: { type: string }
|
||||
availableFileSystemTypes: { type: array, items: { type: string } }
|
||||
|
||||
enableLuksAutomatedPartitioning: { type: boolean, default: false }
|
||||
allowManualPartitioning: { type: boolean, default: true }
|
||||
partitionLayout: { type: array } # TODO: specify items
|
||||
|
@ -545,7 +545,7 @@ Config::passwordStatus( const QString& pw1, const QString& pw2 ) const
|
||||
}
|
||||
}
|
||||
|
||||
return qMakePair( PasswordValidity::Valid, QString() );
|
||||
return qMakePair( PasswordValidity::Valid, tr( "OK!" ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020 Anke Boersma <demm@kaosx.us>
|
||||
* SPDX-FileCopyrightText: 2020 - 2021 Anke Boersma <demm@kaosx.us>
|
||||
* 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.
|
||||
@ -10,7 +11,7 @@
|
||||
import io.calamares.core 1.0
|
||||
import io.calamares.ui 1.0
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.10
|
||||
import QtQuick.Layouts 1.3
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
@ -26,7 +27,6 @@ Kirigami.ScrollablePage {
|
||||
Kirigami.Theme.textColor: "#1F1F1F"
|
||||
|
||||
header: Kirigami.Heading {
|
||||
|
||||
Layout.fillWidth: true
|
||||
height: 50
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
@ -37,71 +37,63 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
id: _formLayout
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Column {
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("What is your name?")
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
||||
id: _userNameField
|
||||
width: parent.width
|
||||
enabled: config.isEditable("fullName")
|
||||
placeholderText: qsTr("Your Full Name")
|
||||
text: config.fullName
|
||||
onTextChanged: config.setFullName(text);
|
||||
onTextChanged: config.setFullName(text)
|
||||
|
||||
background: Rectangle {
|
||||
color: "#FBFBFB" // Kirigami.Theme.backgroundColor
|
||||
radius: 2
|
||||
opacity: 0.9
|
||||
//border.color: _userNameField.text === "" ? Kirigami.Theme.backgroundColor : ( config.fullNameReady ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _userNameField.text === "" ? "#FBFBFB" : ( config.fullNameChanged ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
palette.base: _userNameField.text.length ? "#f0fff0" : "#FBFBFB"
|
||||
palette.highlight : _userNameField.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("What name do you want to use to log in?")
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
||||
id: _userLoginField
|
||||
width: parent.width
|
||||
enabled: config.isEditable("loginName")
|
||||
placeholderText: qsTr("Login Name")
|
||||
text: config.loginName
|
||||
onTextChanged: config.setLoginName(text)
|
||||
validator: RegularExpressionValidator { regularExpression: /[a-z_][a-z0-9_-]*[$]?$/ }
|
||||
|
||||
background: Rectangle {
|
||||
onTextChanged: acceptableInput
|
||||
? ( _userLoginField.text === "root"
|
||||
? forbiddenMessage.visible=true
|
||||
: ( config.setLoginName(text),
|
||||
userMessage.visible = false,forbiddenMessage.visible=false ) )
|
||||
: ( userMessage.visible = true,console.log("Invalid") )
|
||||
|
||||
color: "#FBFBFB" // Kirigami.Theme.backgroundColor
|
||||
opacity: 0.9
|
||||
//border.color: _userLoginField.text === "" ? Kirigami.Theme.backgroundColor : ( config.userNameReady ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _userLoginField.text === "" ? "#FBFBFB" : ( config.loginNameStatusChanged ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
palette.base: _userLoginField.text.length
|
||||
? ( acceptableInput
|
||||
? ( _userLoginField.text === "root"
|
||||
? "#ffdae0" : "#f0fff0" ) : "#ffdae0" ) : "#FBFBFB"
|
||||
palette.highlight : _userLoginField.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
}
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("If more than one person will use this computer, you can create multiple accounts after installation.")
|
||||
font.weight: Font.Thin
|
||||
@ -110,36 +102,54 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Kirigami.InlineMessage {
|
||||
id: userMessage
|
||||
Layout.fillWidth: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: qsTr("Only lowercase letters, numbers, underscore and hyphen are allowed.")
|
||||
}
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
id: forbiddenMessage
|
||||
Layout.fillWidth: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: qsTr("root is not allowed as username.")
|
||||
}
|
||||
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("What is the name of this computer?")
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
||||
id: _hostName
|
||||
width: parent.width
|
||||
placeholderText: qsTr("Computer Name")
|
||||
text: config.hostName
|
||||
onTextChanged: config.setHostName(text)
|
||||
validator: RegularExpressionValidator { regularExpression: /[a-zA-Z0-9][-a-zA-Z0-9_]+/ }
|
||||
|
||||
background: Rectangle {
|
||||
onTextChanged: acceptableInput
|
||||
? ( _hostName.text === "localhost"
|
||||
? forbiddenHost.visible=true
|
||||
: ( config.setHostName(text),
|
||||
hostMessage.visible = false,forbiddenHost.visible = false ) )
|
||||
: hostMessage.visible = true
|
||||
|
||||
color: "#FBFBFB" // Kirigami.Theme.backgroundColor
|
||||
opacity: 0.9
|
||||
//border.color: _hostName.text === "" ? Kirigami.Theme.backgroundColor : ( config.hostNameStatusChanged ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _hostName.text === "" ? "#FBFBFB" : ( config.hostNameStatusChanged ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
palette.base: _hostName.text.length
|
||||
? ( acceptableInput
|
||||
? ( _hostName.text === "localhost" ? "#ffdae0" : "#f0fff0" )
|
||||
: "#ffdae0")
|
||||
: "#FBFBFB"
|
||||
palette.highlight : _hostName.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
}
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("This name will be used if you make the computer visible to others on a network.")
|
||||
font.weight: Font.Thin
|
||||
@ -148,13 +158,27 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Kirigami.InlineMessage {
|
||||
id: hostMessage
|
||||
Layout.fillWidth: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: qsTr("Only letter, numbers, underscore and hyphen are allowed, minimal of two characters.")
|
||||
}
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
id: forbiddenHost
|
||||
Layout.fillWidth: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: qsTr("localhost is not allowed as hostname.")
|
||||
}
|
||||
|
||||
Column {
|
||||
Layout.fillWidth: true
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("Choose a password to keep your account safe.")
|
||||
}
|
||||
@ -164,50 +188,46 @@ Kirigami.ScrollablePage {
|
||||
spacing: 20
|
||||
|
||||
TextField {
|
||||
|
||||
id: _passwordField
|
||||
width: parent.width / 2 - 10
|
||||
placeholderText: qsTr("Password")
|
||||
text: config.userPassword
|
||||
onTextChanged: config.setUserPassword(text)
|
||||
|
||||
palette.base: _passwordField.text.length ? "#f0fff0" : "#FBFBFB"
|
||||
palette.highlight : _passwordField.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
|
||||
echoMode: TextInput.Password
|
||||
passwordMaskDelay: 300
|
||||
inputMethodHints: Qt.ImhNoAutoUppercase
|
||||
|
||||
background: Rectangle {
|
||||
|
||||
color: "#FBFBFB" // Kirigami.Theme.backgroundColor
|
||||
opacity: 0.9
|
||||
//border.color: _passwordField.text === "" ? Kirigami.Theme.backgroundColor : ( config.passwordReady ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _passwordField.text === "" ? "#FBFBFB" : ( config.userPasswordStatusChanged ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
||||
id: _verificationPasswordField
|
||||
width: parent.width / 2 - 10
|
||||
placeholderText: qsTr("Repeat Password")
|
||||
text: config.userPasswordSecondary
|
||||
onTextChanged: config.setUserPasswordSecondary(text)
|
||||
|
||||
onTextChanged: _passwordField.text === _verificationPasswordField.text
|
||||
? ( config.setUserPasswordSecondary(text),
|
||||
passMessage.visible = false,
|
||||
validityMessage.visible = true )
|
||||
: ( passMessage.visible = true,
|
||||
validityMessage.visible = false )
|
||||
|
||||
palette.base: _verificationPasswordField.text.length
|
||||
? ( _passwordField.text === _verificationPasswordField.text
|
||||
? "#f0fff0" : "#ffdae0" )
|
||||
: "#FBFBFB"
|
||||
palette.highlight : _verificationPasswordField.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
|
||||
echoMode: TextInput.Password
|
||||
passwordMaskDelay: 300
|
||||
inputMethodHints: Qt.ImhNoAutoUppercase
|
||||
|
||||
background: Rectangle {
|
||||
|
||||
color: "#FBFBFB" //Kirigami.Theme.backgroundColor
|
||||
opacity: 0.9
|
||||
//border.color: _verificationpasswordField.text === "" ? Kirigami.Theme.backgroundColor : ( config.passwordReady ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _verificationPasswordField.text === "" ? "#FBFBFB" : ( config.userPasswordSecondaryChanged ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.")
|
||||
font.weight: Font.Thin
|
||||
@ -217,27 +237,25 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
|
||||
visible: config.permitWeakPasswords
|
||||
text: qsTr("Validate passwords quality")
|
||||
checked: config.requireStrongPasswords
|
||||
onCheckedChanged: config.setRequireStrongPasswords(checked)
|
||||
Kirigami.InlineMessage {
|
||||
id: passMessage
|
||||
Layout.fillWidth: true
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: config.userPasswordMessage
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: config.permitWeakPasswords
|
||||
width: parent.width
|
||||
text: qsTr("When this box is checked, password-strength checking is done and you will not be able to use a weak password.")
|
||||
font.weight: Font.Thin
|
||||
font.pointSize: 8
|
||||
color: "#6D6D6D"
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: qsTr("Log in automatically without asking for the password")
|
||||
checked: config.doAutoLogin
|
||||
onCheckedChanged: config.setAutoLogin(checked)
|
||||
Kirigami.InlineMessage {
|
||||
id: validityMessage
|
||||
Layout.fillWidth: true
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
type: config.userPasswordValidity
|
||||
? ( config.requireStrongPasswords
|
||||
? Kirigami.MessageType.Error : Kirigami.MessageType.Warning )
|
||||
: Kirigami.MessageType.Positive
|
||||
text: config.userPasswordMessage
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
@ -258,13 +276,11 @@ Kirigami.ScrollablePage {
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
visible: ! root.checked
|
||||
Layout.fillWidth: true
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
Label {
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("Choose a root password to keep your account safe.")
|
||||
}
|
||||
@ -274,50 +290,46 @@ Kirigami.ScrollablePage {
|
||||
spacing: 20
|
||||
|
||||
TextField {
|
||||
|
||||
id: _rootPasswordField
|
||||
width: parent.width / 2 -10
|
||||
placeholderText: qsTr("Root Password")
|
||||
text: config.rootPassword
|
||||
|
||||
onTextChanged: config.setRootPassword(text)
|
||||
|
||||
palette.base: _rootPasswordField.text.length ? "#f0fff0" : "#FBFBFB"
|
||||
palette.highlight : _rootPasswordField.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
|
||||
echoMode: TextInput.Password
|
||||
passwordMaskDelay: 300
|
||||
inputMethodHints: Qt.ImhNoAutoUppercase
|
||||
|
||||
background: Rectangle {
|
||||
|
||||
color: "#FBFBFB" // Kirigami.Theme.backgroundColor
|
||||
opacity: 0.9
|
||||
//border.color: _rootPasswordField.text === "" ? Kirigami.Theme.backgroundColor : ( config.rootPasswordReady ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _rootPasswordField.text === "" ? "#FBFBFB" : ( config.rootPasswordReady ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
TextField {
|
||||
|
||||
id: _verificationRootPasswordField
|
||||
width: parent.width / 2 -10
|
||||
placeholderText: qsTr("Repeat Root Password")
|
||||
text: config.rootPasswordSecondary
|
||||
onTextChanged: config.setRootPasswordSecondary(text)
|
||||
|
||||
onTextChanged: _rootPasswordField.text === _verificationRootPasswordField.text
|
||||
? ( config.setRootPasswordSecondary(text),
|
||||
rootPassMessage.visible = false,
|
||||
rootValidityMessage.visible = true )
|
||||
: ( rootPassMessage.visible = true,
|
||||
rootValidityMessage.visible = false )
|
||||
|
||||
palette.base: _verificationRootPasswordField.text.length
|
||||
? ( _rootPasswordField.text === _verificationRootPasswordField.text
|
||||
? "#f0fff0" : "#ffdae0") : "#FBFBFB"
|
||||
palette.highlight : _verificationRootPasswordField.text.length ? "#dcffdc" : "#FBFBFB"
|
||||
|
||||
echoMode: TextInput.Password
|
||||
passwordMaskDelay: 300
|
||||
inputMethodHints: Qt.ImhNoAutoUppercase
|
||||
|
||||
background: Rectangle {
|
||||
|
||||
color: "#FBFBFB" // Kirigami.Theme.backgroundColor
|
||||
opacity: 0.9
|
||||
//border.color: _verificationRootPasswordField.text === "" ? Kirigami.Theme.backgroundColor : ( config.rootPasswordReady ? Kirigami.Theme.backgroundColor : Kirigami.Theme.negativeTextColor)
|
||||
border.color: _verificationRootPasswordField.text === "" ? "#FBFBFB" : ( config.rootPasswordReady ? "#FBFBFB" : Kirigami.Theme.negativeTextColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
|
||||
visible: ! root.checked
|
||||
width: parent.width
|
||||
text: qsTr("Enter the same password twice, so that it can be checked for typing errors.")
|
||||
@ -326,5 +338,52 @@ Kirigami.ScrollablePage {
|
||||
color: "#6D6D6D"
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
id: rootPassMessage
|
||||
Layout.fillWidth: true
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
type: Kirigami.MessageType.Error
|
||||
text: config.rootPasswordMessage
|
||||
}
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
id: rootValidityMessage
|
||||
Layout.fillWidth: true
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
type: config.rootPasswordValidity
|
||||
? ( config.requireStrongPasswords
|
||||
? Kirigami.MessageType.Error : Kirigami.MessageType.Warning )
|
||||
: Kirigami.MessageType.Positive
|
||||
text: config.rootPasswordMessage
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: qsTr("Log in automatically without asking for the password")
|
||||
checked: config.doAutoLogin
|
||||
onCheckedChanged: config.setAutoLogin(checked)
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
visible: config.permitWeakPasswords
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: qsTr("Validate passwords quality")
|
||||
checked: config.requireStrongPasswords
|
||||
onCheckedChanged: config.setRequireStrongPasswords(checked),
|
||||
rootPassMessage.visible = false
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: config.permitWeakPasswords
|
||||
width: parent.width
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: qsTr("When this box is checked, password-strength checking is done and you will not be able to use a weak password.")
|
||||
font.weight: Font.Thin
|
||||
font.pointSize: 8
|
||||
color: "#6D6D6D"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user