From 6d744374db5ac64fc538f89412eb91f4798187b0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 May 2020 11:22:25 +0200 Subject: [PATCH 001/105] [tracking] Use enum-conveniences --- src/modules/tracking/TrackingType.h | 12 +++++++++--- src/modules/tracking/TrackingViewStep.cpp | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/modules/tracking/TrackingType.h b/src/modules/tracking/TrackingType.h index 02dbd934e..04e8d2ebe 100644 --- a/src/modules/tracking/TrackingType.h +++ b/src/modules/tracking/TrackingType.h @@ -19,11 +19,17 @@ #ifndef TRACKINGTYPE_H #define TRACKINGTYPE_H +#include "utils/NamedEnum.h" + enum class TrackingType { - InstallTracking, - MachineTracking, - UserTracking + NoTracking, // Do not enable tracking at all + InstallTracking, // Track that *this* install has happened + MachineTracking, // Track the machine, ongoing + UserTracking // Track the user, ongoing }; +// Implemented in TrackingViewStep.cpp +const NamedEnumTable< TrackingType >& trackingNames(); + #endif //TRACKINGTYPE_H diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index a51864ea9..2cb97f079 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -189,3 +189,20 @@ TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) m_widget->setGeneralPolicy( CalamaresUtils::getString( configurationMap, "policy" ) ); m_widget->setTrackingLevel( CalamaresUtils::getString( configurationMap, "default" ) ); } + +const NamedEnumTable< TrackingType >& +trackingNames() +{ + // *INDENT-OFF* + // clang-format off + static const NamedEnumTable< TrackingType > names { + { QStringLiteral( "none" ), TrackingType::NoTracking }, + { QStringLiteral( "install" ), TrackingType::InstallTracking }, + { QStringLiteral( "machine" ), TrackingType::MachineTracking }, + { QStringLiteral( "user" ), TrackingType::UserTracking } + }; + // clang-format on + // *INDENT-ON* + + return names; +} From fd2853b2cfa49d6af5add66ceaa75c60b0f97391 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 May 2020 11:41:02 +0200 Subject: [PATCH 002/105] [tracking] Switch setTrackingLevel() to use enum --- src/modules/tracking/TrackingPage.cpp | 34 ++++++++++------------- src/modules/tracking/TrackingPage.h | 14 ++++++---- src/modules/tracking/TrackingViewStep.cpp | 7 ++++- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index ba1d5efd0..359fac4b4 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -172,34 +172,28 @@ TrackingPage::setGeneralPolicy( QString url ) } void -TrackingPage::setTrackingLevel( const QString& l ) +TrackingPage::setTrackingLevel( TrackingType t ) { - QString level = l.toLower(); QRadioButton* button = nullptr; - if ( level.isEmpty() || level == "none" ) + switch( t ) { - button = ui->noneRadio; - } - else if ( level == "install" ) - { - button = ui->installRadio; - } - else if ( level == "machine" ) - { - button = ui->machineRadio; - } - else if ( level == "user" ) - { - button = ui->userRadio; + case TrackingType::NoTracking: + button = ui->noneRadio; + break; + case TrackingType::InstallTracking: + button = ui->installRadio; + break; + case TrackingType::MachineTracking: + button = ui->machineRadio; + break; + case TrackingType::UserTracking: + button = ui->userRadio; + break; } if ( button != nullptr ) { button->setChecked( true ); } - else - { - cWarning() << "unknown default tracking level" << l; - } } diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index 560115b92..52cfca493 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -35,7 +35,8 @@ class TrackingPage : public QWidget public: explicit TrackingPage( QWidget* parent = nullptr ); - /** + /** @brief Set initial state for each option + * * Enables or disables the tracking-option block for the given * tracking option @p t, and sets the initial state of the * checkbox to the @p user default. @@ -43,19 +44,20 @@ public: * Call this in ascending order of tracking type. */ void enableTrackingOption( TrackingType t, bool enabled ); - /** + /** @brief Is the given tracking type enabled? + * * Returns whether tracking type @p is selected by the user * (i.e. is the radio button for that level, or for a higher * tracking level, enabled). */ bool getTrackingOption( TrackingType t ); - /* URL for given level @p t */ + ///@brief Set URL for given level @p t void setTrackingPolicy( TrackingType t, QString url ); - /* URL for the global link */ + ///@brief Set URL for the global link void setGeneralPolicy( QString url ); - /* Select one of the four levels by name */ - void setTrackingLevel( const QString& level ); + ///@brief Select one of the four levels by name + void setTrackingLevel( TrackingType t ); private: Ui::TrackingPage* ui; diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 2cb97f079..f934301bd 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -187,7 +187,12 @@ TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) setTrackingOption( configurationMap, "user", TrackingType::UserTracking ); m_widget->setGeneralPolicy( CalamaresUtils::getString( configurationMap, "policy" ) ); - m_widget->setTrackingLevel( CalamaresUtils::getString( configurationMap, "default" ) ); + bool ok; + m_widget->setTrackingLevel( trackingNames().find(CalamaresUtils::getString( configurationMap, "default" ), ok ) ); + if ( !ok ) + { + cWarning() << "Default tracking level unknown:" << CalamaresUtils::getString( configurationMap, "default" ); + } } const NamedEnumTable< TrackingType >& From 8ed8b5dfa3e00274eb98dd4fa40274a1bbbfb82e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 May 2020 12:11:11 +0200 Subject: [PATCH 003/105] [tracking] Reduce compiler warnings - Newly added enum value NoTracking needs explicit handling in some switch()es, although it will never be passed in. --- src/modules/tracking/TrackingPage.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 359fac4b4..0ac466673 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -70,6 +70,9 @@ TrackingPage::enableTrackingOption( TrackingType t, bool enabled ) switch ( t ) { + case TrackingType::NoTracking: + // Nothing to do, this **has** no widget + return; case TrackingType::InstallTracking: group = ui->installGroup; break; @@ -108,6 +111,8 @@ TrackingPage::getTrackingOption( TrackingType t ) #define ch( x ) ui->x->isChecked() switch ( t ) { + case TrackingType::NoTracking: + return false; case TrackingType::InstallTracking: enabled = ch( installRadio ) || ch( machineRadio ) || ch( userRadio ); break; @@ -128,6 +133,9 @@ TrackingPage::setTrackingPolicy( TrackingType t, QString url ) QToolButton* button = nullptr; switch ( t ) { + case TrackingType::NoTracking: + cWarning() << "Cannot configure NoTracking widget"; + return; case TrackingType::InstallTracking: button = ui->installPolicyButton; break; From a69d47c115bcd32e9d4b8628b9ac939efb26d3fa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 May 2020 14:24:33 +0200 Subject: [PATCH 004/105] [tracking] Add a Config object --- src/modules/tracking/CMakeLists.txt | 1 + src/modules/tracking/Config.cpp | 40 +++++++++++++++++++++++++ src/modules/tracking/Config.h | 45 +++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 src/modules/tracking/Config.cpp create mode 100644 src/modules/tracking/Config.h diff --git a/src/modules/tracking/CMakeLists.txt b/src/modules/tracking/CMakeLists.txt index 24e020af4..11ccdb00b 100644 --- a/src/modules/tracking/CMakeLists.txt +++ b/src/modules/tracking/CMakeLists.txt @@ -2,6 +2,7 @@ calamares_add_plugin( tracking TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES + Config.cpp TrackingJobs.cpp TrackingPage.cpp TrackingViewStep.cpp diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp new file mode 100644 index 000000000..d920074fa --- /dev/null +++ b/src/modules/tracking/Config.cpp @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2020, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "Config.h" + +#include "utils/Logger.h" +#include "utils/Variant.h" + +Config::Config( QObject* parent ) + : QObject( parent ) +{ +} + +void +Config::setConfigurationMap( const QVariantMap& m ) +{ + m_generalPolicy = CalamaresUtils::getString( m, "policy" ); + emit generalPolicyChanged( m_generalPolicy ); +} + +QString +Config::generalPolicy() const +{ + return m_generalPolicy; +} diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h new file mode 100644 index 000000000..d0d6f6e0c --- /dev/null +++ b/src/modules/tracking/Config.h @@ -0,0 +1,45 @@ +/* === This file is part of Calamares - === + * + * Copyright 2020, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef TRACKING_CONFIG_H +#define TRACKING_CONFIG_H + +#include +#include +#include + +class Config : public QObject +{ + Q_OBJECT + Q_PROPERTY( QString generalPolicy READ generalPolicy NOTIFY generalPolicyChanged FINAL ) + +public: + Config( QObject* parent = nullptr ); + void setConfigurationMap( const QVariantMap& ); + +public Q_SLOTS: + QString generalPolicy() const; + +signals: + void generalPolicyChanged( QString ); + +private: + QString m_generalPolicy; +}; + +#endif From 044f5ce2b56f97600d604353f4eef94bfdf7ac78 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 May 2020 14:39:42 +0200 Subject: [PATCH 005/105] [tracking] Use the config object - right now only holds the global policy URL (as a string) --- src/modules/tracking/TrackingPage.cpp | 75 +++++++++++++---------- src/modules/tracking/TrackingPage.h | 12 +++- src/modules/tracking/TrackingViewStep.cpp | 9 ++- src/modules/tracking/TrackingViewStep.h | 2 + 4 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 0ac466673..ae9a04843 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -18,6 +18,7 @@ #include "TrackingPage.h" +#include "Config.h" #include "ui_page_trackingstep.h" #include "Branding.h" @@ -32,27 +33,12 @@ #include #include -TrackingPage::TrackingPage( QWidget* parent ) +TrackingPage::TrackingPage( Config* config, QWidget* parent ) : QWidget( parent ) , ui( new Ui::TrackingPage ) { ui->setupUi( this ); - CALAMARES_RETRANSLATE( - QString product = Calamares::Branding::instance()->shortProductName(); ui->retranslateUi( this ); - ui->generalExplanation->setText( - tr( "Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with " - "the last two options below), get continuous information about preferred applications. To see what " - "will be sent, please click the help icon next to each area." ) - .arg( product ) ); - ui->installExplanation->setText( - tr( "By selecting this you will send information about your installation and hardware. This information " - "will only be sent once after the installation finishes." ) ); - ui->machineExplanation->setText( tr( "By selecting this you will periodically send information about " - "your installation, hardware and applications, to %1." ) - .arg( product ) ); - ui->userExplanation->setText( tr( "By selecting this you will regularly send information about your " - "installation, hardware, applications and usage patterns, to %1." ) - .arg( product ) ); ) + CALAMARES_RETRANSLATE_SLOT( &TrackingPage::retranslate ); QButtonGroup* group = new QButtonGroup( this ); group->setExclusive( true ); @@ -61,8 +47,33 @@ TrackingPage::TrackingPage( QWidget* parent ) group->addButton( ui->machineRadio ); group->addButton( ui->userRadio ); ui->noneRadio->setChecked( true ); + + connect( config, &Config::generalPolicyChanged, this, &TrackingPage::setGeneralPolicy ); + retranslate(); } +void +TrackingPage::retranslate() +{ + QString product = Calamares::Branding::instance()->shortProductName(); + ui->retranslateUi( this ); + ui->generalExplanation->setText( + tr( "Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with " + "the last two options below), get continuous information about preferred applications. To see what " + "will be sent, please click the help icon next to each area." ) + .arg( product ) ); + ui->installExplanation->setText( + tr( "By selecting this you will send information about your installation and hardware. This information " + "will only be sent once after the installation finishes." ) ); + ui->machineExplanation->setText( tr( "By selecting this you will periodically send information about " + "your installation, hardware and applications, to %1." ) + .arg( product ) ); + ui->userExplanation->setText( tr( "By selecting this you will regularly send information about your " + "installation, hardware, applications and usage patterns, to %1." ) + .arg( product ) ); +} + + void TrackingPage::enableTrackingOption( TrackingType t, bool enabled ) { @@ -154,7 +165,7 @@ TrackingPage::setTrackingPolicy( TrackingType t, QString url ) } else { - connect( button, &QToolButton::clicked, [ url ] { QDesktopServices::openUrl( url ); } ); + connect( button, &QToolButton::clicked, [url] { QDesktopServices::openUrl( url ); } ); cDebug() << "Tracking policy" << int( t ) << "set to" << url; } else @@ -175,7 +186,7 @@ TrackingPage::setGeneralPolicy( QString url ) ui->generalPolicyLabel->show(); ui->generalPolicyLabel->setTextInteractionFlags( Qt::TextBrowserInteraction ); ui->generalPolicyLabel->show(); - connect( ui->generalPolicyLabel, &QLabel::linkActivated, [ url ] { QDesktopServices::openUrl( url ); } ); + connect( ui->generalPolicyLabel, &QLabel::linkActivated, [url] { QDesktopServices::openUrl( url ); } ); } } @@ -184,20 +195,20 @@ TrackingPage::setTrackingLevel( TrackingType t ) { QRadioButton* button = nullptr; - switch( t ) + switch ( t ) { - case TrackingType::NoTracking: - button = ui->noneRadio; - break; - case TrackingType::InstallTracking: - button = ui->installRadio; - break; - case TrackingType::MachineTracking: - button = ui->machineRadio; - break; - case TrackingType::UserTracking: - button = ui->userRadio; - break; + case TrackingType::NoTracking: + button = ui->noneRadio; + break; + case TrackingType::InstallTracking: + button = ui->installRadio; + break; + case TrackingType::MachineTracking: + button = ui->machineRadio; + break; + case TrackingType::UserTracking: + button = ui->userRadio; + break; } if ( button != nullptr ) diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index 52cfca493..dbc9cc20c 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -29,11 +29,13 @@ namespace Ui class TrackingPage; } +class Config; + class TrackingPage : public QWidget { Q_OBJECT public: - explicit TrackingPage( QWidget* parent = nullptr ); + explicit TrackingPage( Config* config, QWidget* parent = nullptr ); /** @brief Set initial state for each option * @@ -54,11 +56,15 @@ public: ///@brief Set URL for given level @p t void setTrackingPolicy( TrackingType t, QString url ); - ///@brief Set URL for the global link - void setGeneralPolicy( QString url ); ///@brief Select one of the four levels by name void setTrackingLevel( TrackingType t ); +public Q_SLOTS: + ///@brief Set URL for the global link + void setGeneralPolicy( QString url ); + + void retranslate(); + private: Ui::TrackingPage* ui; }; diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index f934301bd..6da292242 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -18,6 +18,7 @@ #include "TrackingViewStep.h" +#include "Config.h" #include "TrackingJobs.h" #include "TrackingPage.h" @@ -43,7 +44,8 @@ isValidStyle( const QString& s ) TrackingViewStep::TrackingViewStep( QObject* parent ) : Calamares::ViewStep( parent ) - , m_widget( new TrackingPage ) + , m_config( new Config( this ) ) + , m_widget( new TrackingPage( m_config ) ) { emit nextStatusChanged( false ); } @@ -186,9 +188,10 @@ TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) setTrackingOption( configurationMap, "user", TrackingType::UserTracking ); - m_widget->setGeneralPolicy( CalamaresUtils::getString( configurationMap, "policy" ) ); + m_config->setConfigurationMap( configurationMap ); + bool ok; - m_widget->setTrackingLevel( trackingNames().find(CalamaresUtils::getString( configurationMap, "default" ), ok ) ); + m_widget->setTrackingLevel( trackingNames().find( CalamaresUtils::getString( configurationMap, "default" ), ok ) ); if ( !ok ) { cWarning() << "Default tracking level unknown:" << CalamaresUtils::getString( configurationMap, "default" ); diff --git a/src/modules/tracking/TrackingViewStep.h b/src/modules/tracking/TrackingViewStep.h index bb40d292a..a342dc498 100644 --- a/src/modules/tracking/TrackingViewStep.h +++ b/src/modules/tracking/TrackingViewStep.h @@ -29,6 +29,7 @@ #include #include +class Config; class TrackingPage; class PLUGINDLLEXPORT TrackingViewStep : public Calamares::ViewStep @@ -58,6 +59,7 @@ public: private: QVariantMap setTrackingOption( const QVariantMap& configurationMap, const QString& key, TrackingType t ); + Config* m_config; TrackingPage* m_widget; QString m_installTrackingUrl; QString m_machineTrackingStyle; From ed71b2fbf530af59dff51782dc7e37e6d25e0954 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 May 2020 14:42:04 +0200 Subject: [PATCH 006/105] [tracking] Only accept valid policy URLs --- src/modules/tracking/Config.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index d920074fa..67da7025d 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -21,6 +21,8 @@ #include "utils/Logger.h" #include "utils/Variant.h" +#include + Config::Config( QObject* parent ) : QObject( parent ) { @@ -30,6 +32,12 @@ void Config::setConfigurationMap( const QVariantMap& m ) { m_generalPolicy = CalamaresUtils::getString( m, "policy" ); + + if ( !QUrl( m_generalPolicy ).isValid() ) + { + m_generalPolicy = QString(); + } + emit generalPolicyChanged( m_generalPolicy ); } From da6f728cd45a17d759f3f3ef104b77182516c9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 14 May 2020 12:30:58 -0400 Subject: [PATCH 007/105] [partition] Add support for partition uuid --- src/modules/partition/core/PartitionCoreModule.cpp | 1 + src/modules/partition/core/PartitionLayout.cpp | 6 ++++++ src/modules/partition/core/PartitionLayout.h | 2 ++ src/modules/partition/partition.conf | 1 + 4 files changed, 10 insertions(+) diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index aee1ab10f..b3c3409f4 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -883,6 +883,7 @@ PartitionCoreModule::initLayout( const QVariantList& config ) } if ( !m_partLayout->addEntry( CalamaresUtils::getString( pentry, "name" ), + CalamaresUtils::getString( pentry, "uuid" ), CalamaresUtils::getString( pentry, "type" ), CalamaresUtils::getString( pentry, "mountPoint" ), CalamaresUtils::getString( pentry, "filesystem" ), diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 33d2a7679..451604273 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -118,6 +118,7 @@ PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const bool PartitionLayout::addEntry( const QString& label, + const QString& uuid, const QString& type, const QString& mountPoint, const QString& fs, @@ -140,6 +141,7 @@ PartitionLayout::addEntry( const QString& label, } entry.partLabel = label; + entry.partUUID = uuid; entry.partType = type; entry.partMountPoint = mountPoint; PartUtils::findFS( fs, &entry.partFileSystem ); @@ -244,6 +246,10 @@ PartitionLayout::execute( Device* dev, currentPartition->setLabel( part.partLabel ); currentPartition->fileSystem().setLabel( part.partLabel ); } + if ( !part.partUUID.isEmpty() ) + { + currentPartition->setUUID( part.partUUID ); + } if ( !part.partType.isEmpty() ) { #if defined( WITH_KPMCORE42API ) diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 5651ae995..a7bfcc4b9 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -41,6 +41,7 @@ public: struct PartitionEntry { QString partLabel; + QString partUUID; QString partType; QString partMountPoint; FileSystem::Type partFileSystem = FileSystem::Unknown; @@ -76,6 +77,7 @@ public: const QString& min = QString(), const QString& max = QString() ); bool addEntry( const QString& label, + const QString& uuid, const QString& type, const QString& mountPoint, const QString& fs, diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index f6cc34ee4..158258fc9 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -127,6 +127,7 @@ defaultFileSystemType: "ext4" # - name: filesystem label # and # partition name (gpt only; since KPMCore 4.2.0) +# - uuid: partition uuid (optional parameter; gpt only; requires KPMCore >= 4.2.0) # - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0) # - filesystem: filesystem type # - mountPoint: partition mount point From 3d2b9053b08b41ee9dab70c61a9542324442b35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Thu, 12 Mar 2020 15:27:35 -0400 Subject: [PATCH 008/105] [partition] Add the GPT label and UUID to global storage --- src/modules/partition/jobs/FillGlobalStorageJob.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp index 07c856d44..1242b7804 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ b/src/modules/partition/jobs/FillGlobalStorageJob.cpp @@ -91,6 +91,8 @@ mapForPartition( Partition* partition, const QString& uuid ) { QVariantMap map; map[ "device" ] = partition->partitionPath(); + map[ "partlabel" ] = partition->label(); + map[ "partuuid" ] = partition->uuid(); map[ "mountPoint" ] = PartitionInfo::mountPoint( partition ); map[ "fsName" ] = userVisibleFS( partition->fileSystem() ); map[ "fs" ] = untranslatedFS( partition->fileSystem() ); @@ -107,6 +109,7 @@ mapForPartition( Partition* partition, const QString& uuid ) Logger::CDebug deb; using TR = Logger::DebugRow< const char* const, const QString& >; deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode() + << TR( "partlabel", map[ "partlabel" ].toString() ) << TR( "partuuid", map[ "partuuid" ].toString() ) << TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) << TR( "fs:", map[ "fs" ].toString() ) << TR( "fsName", map[ "fsName" ].toString() ) << TR( "uuid", uuid ) << TR( "claimed", map[ "claimed" ].toString() ); From d9fb9c19a80efd4f149b5952e868b2639a8e5034 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 May 2020 16:41:25 +0200 Subject: [PATCH 009/105] [tracking] Refactor the information for one tracking type - a single tracking type can be enabled for configuration in the config file; each must have a policy URL. Class TrackingStyleConfig is a base class for that kind of configuration. --- src/modules/tracking/Config.cpp | 58 +++++++++++++++++++++++++-- src/modules/tracking/Config.h | 70 +++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 67da7025d..217babba4 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -23,22 +23,72 @@ #include -Config::Config( QObject* parent ) +TrackingStyleConfig::TrackingStyleConfig( QObject* parent ) : QObject( parent ) { } +TrackingStyleConfig::~TrackingStyleConfig() { } + void -Config::setConfigurationMap( const QVariantMap& m ) +TrackingStyleConfig::setTracking( bool enabled ) { - m_generalPolicy = CalamaresUtils::getString( m, "policy" ); + setTracking( enabled ? EnabledByUser : DisabledByUser ); +} + +void +TrackingStyleConfig::setTracking( TrackingStyleConfig::TrackingState state ) +{ + if ( m_state != TrackingState::DisabledByConfig ) + { + m_state = state; + } + emit trackingChanged(); +} + +void +TrackingStyleConfig::setConfigurationMap( const QVariantMap& config ) +{ + m_state = CalamaresUtils::getBool( config, "enabled", false ) ? DisabledByUser : DisabledByConfig; + m_policy = CalamaresUtils::getString( config, "policy" ); + if ( !QUrl( m_policy ).isValid() ) + { + if ( m_state != DisabledByConfig ) + { + cError() << "Tracking policy URL" << m_policy << "is not valid; disabling this tracking type."; + } + m_policy = QString(); + m_state = DisabledByConfig; + } + + emit policyChanged( m_policy ); + emit trackingChanged(); +} + + +Config::Config( QObject* parent ) + : QObject( parent ) + , m_installTracking( new TrackingStyleConfig( this ) ) +{ +} + +void +Config::setConfigurationMap( const QVariantMap& configurationMap ) +{ + m_generalPolicy = CalamaresUtils::getString( configurationMap, "policy" ); if ( !QUrl( m_generalPolicy ).isValid() ) { m_generalPolicy = QString(); } - emit generalPolicyChanged( m_generalPolicy ); + + bool success = false; + auto subconfig = CalamaresUtils::getSubMap( configurationMap, "install", success ); + if ( success ) + { + m_installTracking->setConfigurationMap( subconfig ); + } } QString diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index d0d6f6e0c..80f6d74d1 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -23,10 +23,77 @@ #include #include +/** @brief Base class for configuring a specific kind of tracking. + * + * All tracking types have a policy URL, which is used to explain what + * kind of tracking is involved, what data is sent, etc. The content + * of that URL is the responsibility of the distro. + * + * A tracking type is disabled by default: if it isn't specifically + * enabled (for configuration) in the config file, it will always be disabled. + * If it is enabled (for configuration) in the config file, it still + * defaults to disabled, but the user can choose to enable it. + */ +class TrackingStyleConfig : public QObject +{ + Q_OBJECT + + Q_PROPERTY( TrackingState trackingStatus READ tracking WRITE setTracking NOTIFY trackingChanged FINAL ) + Q_PROPERTY( bool isEnabled READ isEnabled NOTIFY trackingChanged FINAL ) + Q_PROPERTY( bool isConfigurable READ isConfigurable NOTIFY trackingChanged FINAL ) + Q_PROPERTY( QString policy READ policy NOTIFY policyChanged FINAL ) + +public: + TrackingStyleConfig( QObject* parent ); + virtual ~TrackingStyleConfig(); + + void setConfigurationMap( const QVariantMap& ); + + enum TrackingState + { + DisabledByConfig, + DisabledByUser, + EnabledByUser + }; + Q_ENUM( TrackingState ); + +public Q_SLOTS: + TrackingState tracking() const { return m_state; } + /// @brief Has the user specifically enabled this kind of tracking? + bool isEnabled() const { return m_state == EnabledByUser; } + /// @brief Is this tracking enabled for configuration? + bool isConfigurable() const { return m_state != DisabledByConfig; } + /** @brief Sets the tracking state + * + * Unless the tracking is enabled for configuration, it always + * remains disabled. + */ + void setTracking( TrackingState ); + /** @brief Sets the tracking state + * + * Use @c true for @c EnabledByUser, @c false for DisabledByUser, + * but keep in mind that if the tracking is not enabled for + * configuration, it will always remain disabled. + */ + void setTracking( bool ); + + /// @brief URL for the policy explaining this tracking + QString policy() const { return m_policy; } + +signals: + void trackingChanged(); + void policyChanged( QString ); + +private: + TrackingState m_state = DisabledByConfig; + QString m_policy; // URL +}; + class Config : public QObject { Q_OBJECT Q_PROPERTY( QString generalPolicy READ generalPolicy NOTIFY generalPolicyChanged FINAL ) + Q_PROPERTY( TrackingStyleConfig* installTracking READ installTracking FINAL ) public: Config( QObject* parent = nullptr ); @@ -34,12 +101,15 @@ public: public Q_SLOTS: QString generalPolicy() const; + TrackingStyleConfig* installTracking() const { return m_installTracking; } signals: void generalPolicyChanged( QString ); private: QString m_generalPolicy; + + TrackingStyleConfig* m_installTracking; }; #endif From f97a0756a9af62ce544475d6631e93de2c9f012a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 May 2020 17:09:01 +0200 Subject: [PATCH 010/105] [tracking] Introduce configuration for install-tracking - subclass of TrackingStyleConfig holds the URL that is pinged with information when the installation is done. --- src/modules/tracking/Config.cpp | 43 ++++++++++++++++++++++++--------- src/modules/tracking/Config.h | 18 +++++++++++++- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 217babba4..7997556bf 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -46,29 +46,50 @@ TrackingStyleConfig::setTracking( TrackingStyleConfig::TrackingState state ) emit trackingChanged(); } +void +TrackingStyleConfig::validateUrl( QString& urlString ) +{ + if ( !QUrl( urlString ).isValid() ) + { + if ( m_state != DisabledByConfig ) + { + cError() << "URL" << urlString << "is not valid; disabling this tracking type."; + m_state = DisabledByConfig; + emit trackingChanged(); + } + urlString = QString(); + } +} + + void TrackingStyleConfig::setConfigurationMap( const QVariantMap& config ) { m_state = CalamaresUtils::getBool( config, "enabled", false ) ? DisabledByUser : DisabledByConfig; m_policy = CalamaresUtils::getString( config, "policy" ); - if ( !QUrl( m_policy ).isValid() ) - { - if ( m_state != DisabledByConfig ) - { - cError() << "Tracking policy URL" << m_policy << "is not valid; disabling this tracking type."; - } - m_policy = QString(); - m_state = DisabledByConfig; - } - + validateUrl( m_policy ); emit policyChanged( m_policy ); emit trackingChanged(); } +InstallTrackingConfig::InstallTrackingConfig( QObject* parent ) + : TrackingStyleConfig( parent ) +{ +} + +void +InstallTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) +{ + TrackingStyleConfig::setConfigurationMap( configurationMap ); + + m_installTrackingUrl = CalamaresUtils::getString( configurationMap, "url" ); + validateUrl( m_installTrackingUrl ); +} + Config::Config( QObject* parent ) : QObject( parent ) - , m_installTracking( new TrackingStyleConfig( this ) ) + , m_installTracking( new InstallTrackingConfig( this ) ) { } diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index 80f6d74d1..0fbf8495b 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -84,11 +84,27 @@ signals: void trackingChanged(); void policyChanged( QString ); +protected: + /// @brief Validates the @p urlString, disables tracking if invalid + void validateUrl( QString& urlString ); + private: TrackingState m_state = DisabledByConfig; QString m_policy; // URL }; +class InstallTrackingConfig : public TrackingStyleConfig +{ +public: + InstallTrackingConfig( QObject* parent ); + void setConfigurationMap( const QVariantMap& configurationMap ); + + QString installTrackingUrl() { return m_installTrackingUrl; } + +private: + QString m_installTrackingUrl; +}; + class Config : public QObject { Q_OBJECT @@ -109,7 +125,7 @@ signals: private: QString m_generalPolicy; - TrackingStyleConfig* m_installTracking; + InstallTrackingConfig* m_installTracking; }; #endif From 528b98c1c4410423958c776945ec012b7876a55a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 May 2020 17:42:51 +0200 Subject: [PATCH 011/105] [tracking] Configurations for machine and user tracking --- src/modules/tracking/Config.cpp | 59 +++++++++++++++++++++++++++++++++ src/modules/tracking/Config.h | 49 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 7997556bf..2c62447b1 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -46,6 +46,21 @@ TrackingStyleConfig::setTracking( TrackingStyleConfig::TrackingState state ) emit trackingChanged(); } +void +TrackingStyleConfig::validate( QString& s, std::function< bool( const QString& ) >&& pred ) +{ + if ( !pred( s ) ) + { + if ( m_state != DisabledByConfig ) + { + cError() << "Configuration string" << s << "is not valid; disabling this tracking type."; + m_state = DisabledByConfig; + emit trackingChanged(); + } + s = QString(); + } +} + void TrackingStyleConfig::validateUrl( QString& urlString ) { @@ -86,6 +101,50 @@ InstallTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap validateUrl( m_installTrackingUrl ); } +MachineTrackingConfig::MachineTrackingConfig( QObject* parent ) + : TrackingStyleConfig( parent ) +{ +} + +/** @brief Is @p s a valid machine-tracking style. */ +static bool +isValidMachineTrackingStyle( const QString& s ) +{ + static QStringList knownStyles { "neon" }; + return knownStyles.contains( s ); +} + +void +MachineTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) +{ + TrackingStyleConfig::setConfigurationMap( configurationMap ); + + m_machineTrackingStyle = CalamaresUtils::getString( configurationMap, "style" ); + validate( m_machineTrackingStyle, isValidMachineTrackingStyle ); +} + + +UserTrackingConfig::UserTrackingConfig( QObject* parent ) + : TrackingStyleConfig( parent ) +{ +} + +static bool +isValidUserTrackingStyle( const QString& s ) +{ + static QStringList knownStyles { "kde" }; + return knownStyles.contains( s ); +} + +void +UserTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) +{ + TrackingStyleConfig::setConfigurationMap( configurationMap ); + + m_userTrackingStyle = CalamaresUtils::getString( configurationMap, "style" ); + validate( m_userTrackingStyle, isValidUserTrackingStyle ); +} + Config::Config( QObject* parent ) : QObject( parent ) diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index 0fbf8495b..d9210b7ff 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -87,12 +87,21 @@ signals: protected: /// @brief Validates the @p urlString, disables tracking if invalid void validateUrl( QString& urlString ); + /// @brief Validates the @p string, disables tracking if invalid + void validate( QString& s, std::function< bool( const QString& s ) >&& pred ); private: TrackingState m_state = DisabledByConfig; QString m_policy; // URL }; +/** @brief Install tracking pings a URL at the end of installation + * + * Install tracking will do a single GET on the given URL at + * the end of installation. The information included in the GET + * request depends on the URL configuration, see also the tracking + * jobs. + */ class InstallTrackingConfig : public TrackingStyleConfig { public: @@ -105,6 +114,46 @@ private: QString m_installTrackingUrl; }; +/** @brief Machine tracking reports from the installed system + * + * When machine tracking is on, the installed system will report + * back ("call home") at some point. This can mean Debian pop-con, + * or KDE neon maching tracking, or something else. The kind + * of configuration depends on the style of tracking that is enabled. + */ +class MachineTrackingConfig : public TrackingStyleConfig +{ +public: + MachineTrackingConfig( QObject* parent ); + void setConfigurationMap( const QVariantMap& configurationMap ); + + QString machineTrackingStyle() { return m_machineTrackingStyle; } + +private: + QString m_machineTrackingStyle; +}; + +/** @brief User tracking reports user actions + * + * When user tracking is on, it is enabled for the user configured + * in Calamares -- not for users created afterwards in the target + * system, unless the target system defaults to tracking them. + * The kind of user tracking depends on the target system and + * environment; KDE user tracking is one example, which can be + * configured in a fine-grained way and defaults to off. + */ +class UserTrackingConfig : public TrackingStyleConfig +{ +public: + UserTrackingConfig( QObject* parent ); + void setConfigurationMap( const QVariantMap& configurationMap ); + + QString userTrackingStyle() { return m_userTrackingStyle; } + +private: + QString m_userTrackingStyle; +}; + class Config : public QObject { Q_OBJECT From 5763799ba9b6394a509c26a23831dda63c9a7700 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 May 2020 17:48:51 +0200 Subject: [PATCH 012/105] [tracking] Load all the tracking bits into the configuration --- src/modules/tracking/Config.cpp | 14 ++++++++++++++ src/modules/tracking/Config.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 2c62447b1..8b5decd76 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -149,6 +149,8 @@ UserTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) Config::Config( QObject* parent ) : QObject( parent ) , m_installTracking( new InstallTrackingConfig( this ) ) + , m_machineTracking( new MachineTrackingConfig( this ) ) + , m_userTracking( new UserTrackingConfig( this ) ) { } @@ -169,6 +171,18 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) { m_installTracking->setConfigurationMap( subconfig ); } + + subconfig = CalamaresUtils::getSubMap( configurationMap, "machine", success ); + if ( success ) + { + m_machineTracking->setConfigurationMap( subconfig ); + } + + subconfig = CalamaresUtils::getSubMap( configurationMap, "user", success ); + if ( success ) + { + m_userTracking->setConfigurationMap( subconfig ); + } } QString diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index d9210b7ff..1a451e5ce 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -175,6 +175,8 @@ private: QString m_generalPolicy; InstallTrackingConfig* m_installTracking; + MachineTrackingConfig* m_machineTracking; + UserTrackingConfig* m_userTracking; }; #endif From 309b2f872de99fb8d93ed54d531e71f798bf9157 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 May 2020 20:18:34 +0200 Subject: [PATCH 013/105] [tracking] Drop configuration fields from ViewStep - All the configuration lives in the Config object (or the tracking objects that it exposes). - Get data from the config object for the jobs; TODO: give the jobs a less-clunky interface. The UI isn't hooked up to the Config object yet, though. --- src/modules/tracking/Config.h | 7 ++- src/modules/tracking/TrackingViewStep.cpp | 62 +++++------------------ src/modules/tracking/TrackingViewStep.h | 35 ------------- 3 files changed, 19 insertions(+), 85 deletions(-) diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index 1a451e5ce..bd9ba520e 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -159,6 +159,8 @@ class Config : public QObject Q_OBJECT Q_PROPERTY( QString generalPolicy READ generalPolicy NOTIFY generalPolicyChanged FINAL ) Q_PROPERTY( TrackingStyleConfig* installTracking READ installTracking FINAL ) + Q_PROPERTY( TrackingStyleConfig* machineTracking READ machineTracking FINAL ) + Q_PROPERTY( TrackingStyleConfig* userTracking READ userTracking FINAL ) public: Config( QObject* parent = nullptr ); @@ -166,7 +168,10 @@ public: public Q_SLOTS: QString generalPolicy() const; - TrackingStyleConfig* installTracking() const { return m_installTracking; } + + InstallTrackingConfig* installTracking() const { return m_installTracking; } + MachineTrackingConfig* machineTracking() const { return m_machineTracking; } + UserTrackingConfig* userTracking() const { return m_userTracking; } signals: void generalPolicyChanged( QString ); diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 6da292242..98685bfc8 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -105,12 +105,9 @@ TrackingViewStep::isAtEnd() const void TrackingViewStep::onLeave() { - m_installTracking.userEnabled = m_widget->getTrackingOption( TrackingType::InstallTracking ); - m_machineTracking.userEnabled = m_widget->getTrackingOption( TrackingType::MachineTracking ); - m_userTracking.userEnabled = m_widget->getTrackingOption( TrackingType::UserTracking ); - cDebug() << "Install tracking:" << m_installTracking.enabled(); - cDebug() << "Machine tracking:" << m_machineTracking.enabled(); - cDebug() << " User tracking:" << m_userTracking.enabled(); + cDebug() << "Install tracking:" << m_config->installTracking()->isEnabled(); + cDebug() << "Machine tracking:" << m_config->machineTracking()->isEnabled(); + cDebug() << " User tracking:" << m_config->userTracking()->isEnabled(); } @@ -120,10 +117,10 @@ TrackingViewStep::jobs() const Calamares::JobList l; cDebug() << "Creating tracking jobs .."; - if ( m_installTracking.enabled() && !m_installTrackingUrl.isEmpty() ) + if ( m_config->installTracking()->isEnabled() ) { - QString installUrl = m_installTrackingUrl; - const auto s = CalamaresUtils::System::instance(); + QString installUrl = m_config->installTracking()->installTrackingUrl(); + const auto* s = CalamaresUtils::System::instance(); QString memory, disk; memory.setNum( s->getTotalMemoryB().first ); @@ -136,58 +133,25 @@ TrackingViewStep::jobs() const l.append( Calamares::job_ptr( new TrackingInstallJob( installUrl ) ) ); } - if ( m_machineTracking.enabled() && !m_machineTrackingStyle.isEmpty() ) + if ( m_config->machineTracking()->isEnabled() ) { - Q_ASSERT( isValidStyle( m_machineTrackingStyle ) ); - if ( m_machineTrackingStyle == "neon" ) + const auto style = m_config->machineTracking()->machineTrackingStyle(); + if ( style == "neon" ) { l.append( Calamares::job_ptr( new TrackingMachineNeonJob() ) ); } + else + { + cWarning() << "Unsupported machine tracking style" << style; + } } return l; } -QVariantMap -TrackingViewStep::setTrackingOption( const QVariantMap& configurationMap, const QString& key, TrackingType t ) -{ - bool settingEnabled = false; - - bool success = false; - auto config = CalamaresUtils::getSubMap( configurationMap, key, success ); - - if ( success ) - { - settingEnabled = CalamaresUtils::getBool( config, "enabled", false ); - } - - TrackingEnabled& trackingConfiguration = tracking( t ); - trackingConfiguration.settingEnabled = settingEnabled; - trackingConfiguration.userEnabled = false; - - m_widget->enableTrackingOption( t, settingEnabled ); - m_widget->setTrackingPolicy( t, CalamaresUtils::getString( config, "policy" ) ); - - return config; -} - void TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - QVariantMap config; - - config = setTrackingOption( configurationMap, "install", TrackingType::InstallTracking ); - m_installTrackingUrl = CalamaresUtils::getString( config, "url" ); - - config = setTrackingOption( configurationMap, "machine", TrackingType::MachineTracking ); - auto s = CalamaresUtils::getString( config, "style" ); - if ( isValidStyle( s ) ) - { - m_machineTrackingStyle = s; - } - - setTrackingOption( configurationMap, "user", TrackingType::UserTracking ); - m_config->setConfigurationMap( configurationMap ); bool ok; diff --git a/src/modules/tracking/TrackingViewStep.h b/src/modules/tracking/TrackingViewStep.h index a342dc498..b05f1b053 100644 --- a/src/modules/tracking/TrackingViewStep.h +++ b/src/modules/tracking/TrackingViewStep.h @@ -57,43 +57,8 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: - QVariantMap setTrackingOption( const QVariantMap& configurationMap, const QString& key, TrackingType t ); - Config* m_config; TrackingPage* m_widget; - QString m_installTrackingUrl; - QString m_machineTrackingStyle; - - struct TrackingEnabled - { - bool settingEnabled; // Enabled in config file - bool userEnabled; // User checked "yes" - - TrackingEnabled() - : settingEnabled( false ) - , userEnabled( false ) - { - } - - bool enabled() const { return settingEnabled && userEnabled; } - }; - TrackingEnabled m_installTracking, m_machineTracking, m_userTracking; - - inline TrackingEnabled& tracking( TrackingType t ) - { - if ( t == TrackingType::UserTracking ) - { - return m_userTracking; - } - else if ( t == TrackingType::MachineTracking ) - { - return m_machineTracking; - } - else - { - return m_installTracking; - } - } }; CALAMARES_PLUGIN_FACTORY_DECLARATION( TrackingViewStepFactory ) From 49e66b11a2938b92cd9647728de38058de921cd7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 May 2020 10:42:25 +0200 Subject: [PATCH 014/105] [tracking] Refactor creation of jobs - Let the jobs handle their own styling and handling, simplify the ViewStep code. --- src/modules/tracking/TrackingJobs.cpp | 40 +++++++++++++++++++++ src/modules/tracking/TrackingJobs.h | 42 +++++++++++++++++++++-- src/modules/tracking/TrackingPage.cpp | 4 +-- src/modules/tracking/TrackingViewStep.cpp | 36 +++---------------- 4 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 1f284e6dd..40af355bd 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -18,6 +18,8 @@ #include "TrackingJobs.h" +#include "Config.h" + #include "network/Manager.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" @@ -72,6 +74,44 @@ TrackingInstallJob::exec() return Calamares::JobResult::ok(); } +void +TrackingInstallJob::addJob( Calamares::JobList& list, InstallTrackingConfig* config ) +{ + if ( config->isEnabled() ) + { + QString installUrl = config->installTrackingUrl(); + const auto* s = CalamaresUtils::System::instance(); + + QString memory, disk; + memory.setNum( s->getTotalMemoryB().first ); + disk.setNum( s->getTotalDiskB() ); + + installUrl.replace( "$CPU", s->getCpuDescription() ).replace( "$MEMORY", memory ).replace( "$DISK", disk ); + + cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl; + + list.append( Calamares::job_ptr( new TrackingInstallJob( installUrl ) ) ); + } +} + +void +TrackingMachineJob::addJob( Calamares::JobList& list, MachineTrackingConfig* config ) +{ + if ( config->isEnabled() ) + { + const auto style = config->machineTrackingStyle(); + if ( style == "neon" ) + { + list.append( Calamares::job_ptr( new TrackingMachineNeonJob() ) ); + } + else + { + cWarning() << "Unsupported machine tracking style" << style; + } + } +} + + QString TrackingMachineNeonJob::prettyName() const { diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h index 813355591..c7c2450cb 100644 --- a/src/modules/tracking/TrackingJobs.h +++ b/src/modules/tracking/TrackingJobs.h @@ -16,13 +16,35 @@ * along with Calamares. If not, see . */ -#ifndef TRACKINGJOBS -#define TRACKINGJOBS +#ifndef TRACKING_TRACKINGJOBS_H +#define TRACKING_TRACKINGJOBS_H #include "Job.h" +class InstallTrackingConfig; +class MachineTrackingConfig; + class QSemaphore; +/** @section Tracking Jobs + * + * The tracking jobs do the actual work of configuring tracking on the + * target machine. Tracking jobs may have *styles*, variations depending + * on the distro or environment of the target system. At the root of + * each family of tracking jobs (installation, machine, user) there is + * a class with static method `addJob()` that takes the configuration + * information from the relevant Config sub-object and optionally + * adds the right job (subclass!) to the list of jobs. + */ + +/** @brief Install-tracking job (gets a URL) + * + * The install-tracking job (there is only one kind) does a GET + * on a configured URL with some additional information about + * the machine (if configured into the URL). + * + * No persistent tracking is done. + */ class TrackingInstallJob : public Calamares::Job { Q_OBJECT @@ -35,11 +57,25 @@ public: QString prettyStatusMessage() const override; Calamares::JobResult exec() override; + static void addJob( Calamares::JobList& list, InstallTrackingConfig* config ); + private: const QString m_url; }; -class TrackingMachineNeonJob : public Calamares::Job +/** @brief Base class for machine-tracking jobs + * + * Machine-tracking configuraiton depends on the distro / style of machine + * being tracked, so it has subclasses to switch on the relevant kind + * of tracking. A machine is tracked persistently. + */ +class TrackingMachineJob : public Calamares::Job +{ +public: + static void addJob( Calamares::JobList& list, MachineTrackingConfig* config ); +}; + +class TrackingMachineNeonJob : public TrackingMachineJob { Q_OBJECT public: diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index ae9a04843..7572ecb68 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -165,7 +165,7 @@ TrackingPage::setTrackingPolicy( TrackingType t, QString url ) } else { - connect( button, &QToolButton::clicked, [url] { QDesktopServices::openUrl( url ); } ); + connect( button, &QToolButton::clicked, [ url ] { QDesktopServices::openUrl( url ); } ); cDebug() << "Tracking policy" << int( t ) << "set to" << url; } else @@ -186,7 +186,7 @@ TrackingPage::setGeneralPolicy( QString url ) ui->generalPolicyLabel->show(); ui->generalPolicyLabel->setTextInteractionFlags( Qt::TextBrowserInteraction ); ui->generalPolicyLabel->show(); - connect( ui->generalPolicyLabel, &QLabel::linkActivated, [url] { QDesktopServices::openUrl( url ); } ); + connect( ui->generalPolicyLabel, &QLabel::linkActivated, [ url ] { QDesktopServices::openUrl( url ); } ); } } diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 98685bfc8..9942c2981 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -106,45 +106,19 @@ void TrackingViewStep::onLeave() { cDebug() << "Install tracking:" << m_config->installTracking()->isEnabled(); - cDebug() << "Machine tracking:" << m_config->machineTracking()->isEnabled(); - cDebug() << " User tracking:" << m_config->userTracking()->isEnabled(); + cDebug() << Logger::SubEntry << "Machine tracking:" << m_config->machineTracking()->isEnabled(); + cDebug() << Logger::SubEntry << " User tracking:" << m_config->userTracking()->isEnabled(); } Calamares::JobList TrackingViewStep::jobs() const { - Calamares::JobList l; - cDebug() << "Creating tracking jobs .."; - if ( m_config->installTracking()->isEnabled() ) - { - QString installUrl = m_config->installTracking()->installTrackingUrl(); - const auto* s = CalamaresUtils::System::instance(); - QString memory, disk; - memory.setNum( s->getTotalMemoryB().first ); - disk.setNum( s->getTotalDiskB() ); - - installUrl.replace( "$CPU", s->getCpuDescription() ).replace( "$MEMORY", memory ).replace( "$DISK", disk ); - - cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl; - - l.append( Calamares::job_ptr( new TrackingInstallJob( installUrl ) ) ); - } - - if ( m_config->machineTracking()->isEnabled() ) - { - const auto style = m_config->machineTracking()->machineTrackingStyle(); - if ( style == "neon" ) - { - l.append( Calamares::job_ptr( new TrackingMachineNeonJob() ) ); - } - else - { - cWarning() << "Unsupported machine tracking style" << style; - } - } + Calamares::JobList l; + TrackingInstallJob::addJob( l, m_config->installTracking() ); + TrackingMachineJob::addJob( l, m_config->machineTracking() ); return l; } From dfd6bb6a8bf08dc8c83a228f43177917f8253972 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 May 2020 11:05:32 +0200 Subject: [PATCH 015/105] [tracking] Massage the displayed explanation --- src/modules/tracking/TrackingPage.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 7572ecb68..1e30a8a3a 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -58,19 +58,21 @@ TrackingPage::retranslate() QString product = Calamares::Branding::instance()->shortProductName(); ui->retranslateUi( this ); ui->generalExplanation->setText( - tr( "Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with " - "the last two options below), get continuous information about preferred applications. To see what " + tr( "Tracking helps %1 to see how often it is installed, what hardware it is installed on and " + "which applications are used. To see what " "will be sent, please click the help icon next to each area." ) .arg( product ) ); ui->installExplanation->setText( tr( "By selecting this you will send information about your installation and hardware. This information " "will only be sent once after the installation finishes." ) ); - ui->machineExplanation->setText( tr( "By selecting this you will periodically send information about " - "your installation, hardware and applications, to %1." ) - .arg( product ) ); - ui->userExplanation->setText( tr( "By selecting this you will regularly send information about your " - "installation, hardware, applications and usage patterns, to %1." ) - .arg( product ) ); + ui->machineExplanation->setText( + tr( "By selecting this you will periodically send information about your machine installation, " + "hardware and applications, to %1." ) + .arg( product ) ); + ui->userExplanation->setText( + tr( "By selecting this you will regularly send information about your " + "user installation, hardware, applications and application usage patterns, to %1." ) + .arg( product ) ); } From a7c4e2d203a05ef94b84f1451e4f4cc3a5728272 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 19 May 2020 11:12:16 +0200 Subject: [PATCH 016/105] [tracking] Remove widget-setting stuff not needed with Config --- src/modules/tracking/TrackingPage.cpp | 100 -------------------------- src/modules/tracking/TrackingPage.h | 19 ----- 2 files changed, 119 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 1e30a8a3a..82e0d99c5 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -76,106 +76,6 @@ TrackingPage::retranslate() } -void -TrackingPage::enableTrackingOption( TrackingType t, bool enabled ) -{ - QWidget* group = nullptr; - - switch ( t ) - { - case TrackingType::NoTracking: - // Nothing to do, this **has** no widget - return; - case TrackingType::InstallTracking: - group = ui->installGroup; - break; - case TrackingType::MachineTracking: - group = ui->machineGroup; - break; - case TrackingType::UserTracking: - group = ui->userGroup; - break; - } - - if ( group != nullptr ) - { - if ( enabled ) - { - group->show(); - } - else - { - group->hide(); - } - } - else - { - cWarning() << "unknown tracking option" << int( t ); - } -} - -bool -TrackingPage::getTrackingOption( TrackingType t ) -{ - bool enabled = false; - - // A tracking type is enabled if it is checked, or - // any higher level is checked. -#define ch( x ) ui->x->isChecked() - switch ( t ) - { - case TrackingType::NoTracking: - return false; - case TrackingType::InstallTracking: - enabled = ch( installRadio ) || ch( machineRadio ) || ch( userRadio ); - break; - case TrackingType::MachineTracking: - enabled = ch( machineRadio ) || ch( userRadio ); - break; - case TrackingType::UserTracking: - enabled = ch( userRadio ); - break; - } -#undef ch - return enabled; -} - -void -TrackingPage::setTrackingPolicy( TrackingType t, QString url ) -{ - QToolButton* button = nullptr; - switch ( t ) - { - case TrackingType::NoTracking: - cWarning() << "Cannot configure NoTracking widget"; - return; - case TrackingType::InstallTracking: - button = ui->installPolicyButton; - break; - case TrackingType::MachineTracking: - button = ui->machinePolicyButton; - break; - case TrackingType::UserTracking: - button = ui->userPolicyButton; - break; - } - - if ( button != nullptr ) - if ( url.isEmpty() ) - { - button->hide(); - } - else - { - connect( button, &QToolButton::clicked, [ url ] { QDesktopServices::openUrl( url ); } ); - cDebug() << "Tracking policy" << int( t ) << "set to" << url; - } - else - { - cWarning() << "unknown tracking option" << int( t ); - } -} - void TrackingPage::setGeneralPolicy( QString url ) { diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index dbc9cc20c..ce8b87729 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -37,25 +37,6 @@ class TrackingPage : public QWidget public: explicit TrackingPage( Config* config, QWidget* parent = nullptr ); - /** @brief Set initial state for each option - * - * Enables or disables the tracking-option block for the given - * tracking option @p t, and sets the initial state of the - * checkbox to the @p user default. - * - * Call this in ascending order of tracking type. - */ - void enableTrackingOption( TrackingType t, bool enabled ); - /** @brief Is the given tracking type enabled? - * - * Returns whether tracking type @p is selected by the user - * (i.e. is the radio button for that level, or for a higher - * tracking level, enabled). - */ - bool getTrackingOption( TrackingType t ); - - ///@brief Set URL for given level @p t - void setTrackingPolicy( TrackingType t, QString url ); ///@brief Select one of the four levels by name void setTrackingLevel( TrackingType t ); From 935f443a4db7085e27c44c2c061d4a5cf5881ca5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 May 2020 05:24:20 -0400 Subject: [PATCH 017/105] [tracking] Simplify policy display - Don't need an own slot for this, just connect to signals from Config and the label, neither of which need any state. --- src/modules/tracking/TrackingPage.cpp | 31 ++++++++++++--------------- src/modules/tracking/TrackingPage.h | 3 --- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 82e0d99c5..000ea2002 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -48,7 +48,20 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) group->addButton( ui->userRadio ); ui->noneRadio->setChecked( true ); - connect( config, &Config::generalPolicyChanged, this, &TrackingPage::setGeneralPolicy ); + // TODO: move to .ui file + ui->generalPolicyLabel->setTextInteractionFlags( Qt::TextBrowserInteraction ); + + connect( config, &Config::generalPolicyChanged, [ this ]( const QString& url ) { + this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); + } ); + connect( ui->generalPolicyLabel, &QLabel::linkActivated, [ config ] { + QString url( config->generalPolicy() ); + if ( !url.isEmpty() ) + { + QDesktopServices::openUrl( url ); + } + } ); + retranslate(); } @@ -76,22 +89,6 @@ TrackingPage::retranslate() } -void -TrackingPage::setGeneralPolicy( QString url ) -{ - if ( url.isEmpty() ) - { - ui->generalPolicyLabel->hide(); - } - else - { - ui->generalPolicyLabel->show(); - ui->generalPolicyLabel->setTextInteractionFlags( Qt::TextBrowserInteraction ); - ui->generalPolicyLabel->show(); - connect( ui->generalPolicyLabel, &QLabel::linkActivated, [ url ] { QDesktopServices::openUrl( url ); } ); - } -} - void TrackingPage::setTrackingLevel( TrackingType t ) { diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index ce8b87729..f63f7375c 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -41,9 +41,6 @@ public: void setTrackingLevel( TrackingType t ); public Q_SLOTS: - ///@brief Set URL for the global link - void setGeneralPolicy( QString url ); - void retranslate(); private: From 1d143d95a0ba544ff80c3738398ed29ed09bc8aa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 May 2020 08:30:37 -0400 Subject: [PATCH 018/105] [tracking] Setup UI in the .ui file --- src/modules/tracking/TrackingPage.cpp | 3 --- src/modules/tracking/page_trackingstep.ui | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 000ea2002..02bc94195 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -48,9 +48,6 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) group->addButton( ui->userRadio ); ui->noneRadio->setChecked( true ); - // TODO: move to .ui file - ui->generalPolicyLabel->setTextInteractionFlags( Qt::TextBrowserInteraction ); - connect( config, &Config::generalPolicyChanged, [ this ]( const QString& url ) { this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); } ); diff --git a/src/modules/tracking/page_trackingstep.ui b/src/modules/tracking/page_trackingstep.ui index ae2ed11b8..9612ef2b4 100644 --- a/src/modules/tracking/page_trackingstep.ui +++ b/src/modules/tracking/page_trackingstep.ui @@ -279,6 +279,9 @@ margin-left: 2em; false + + Qt::TextBrowserInteraction + From bed884c9718a4a75bce1356cc33d4bee40c7892e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 May 2020 09:21:47 -0400 Subject: [PATCH 019/105] [tracking] Move setup of initial-tracking states to Config - the *default* level from the config, can be handled inside the Config object as well; remove TrackingPage method that does the same. --- src/modules/tracking/Config.cpp | 59 +++++++++++++++++++++++ src/modules/tracking/Config.h | 3 ++ src/modules/tracking/TrackingType.h | 2 +- src/modules/tracking/TrackingViewStep.cpp | 23 --------- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 8b5decd76..2dc91c2a9 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -18,11 +18,30 @@ #include "Config.h" +#include "TrackingType.h" + #include "utils/Logger.h" #include "utils/Variant.h" #include +const NamedEnumTable< TrackingType >& +trackingNames() +{ + // *INDENT-OFF* + // clang-format off + static const NamedEnumTable< TrackingType > names { + { QStringLiteral( "none" ), TrackingType::NoTracking }, + { QStringLiteral( "install" ), TrackingType::InstallTracking }, + { QStringLiteral( "machine" ), TrackingType::MachineTracking }, + { QStringLiteral( "user" ), TrackingType::UserTracking } + }; + // clang-format on + // *INDENT-ON* + + return names; +} + TrackingStyleConfig::TrackingStyleConfig( QObject* parent ) : QObject( parent ) { @@ -154,6 +173,26 @@ Config::Config( QObject* parent ) { } +static void +enableLevelsBelow( Config* config, TrackingType level ) +{ + switch( level ) + { + case TrackingType::UserTracking: + config->userTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); + FALLTHRU; + case TrackingType::MachineTracking: + config->machineTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); + FALLTHRU; + case TrackingType::InstallTracking: + config->installTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); + break; + case TrackingType::NoTracking: + config->noTracking( true ); + break; + } +} + void Config::setConfigurationMap( const QVariantMap& configurationMap ) { @@ -183,6 +222,14 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) { m_userTracking->setConfigurationMap( subconfig ); } + + auto level = trackingNames().find( CalamaresUtils::getString( configurationMap, "default" ), success ); + if ( !success ) + { + cWarning() << "Default tracking level unknown:" << CalamaresUtils::getString( configurationMap, "default" ); + level = TrackingType::NoTracking; + } + enableLevelsBelow( this, level ); } QString @@ -190,3 +237,15 @@ Config::generalPolicy() const { return m_generalPolicy; } + +void +Config::noTracking( bool switchOffAllTracking ) +{ + if ( !switchOffAllTracking ) + { + return; + } + m_installTracking->setTracking( TrackingStyleConfig::TrackingState::DisabledByUser ); + m_machineTracking->setTracking( TrackingStyleConfig::TrackingState::DisabledByUser ); + m_userTracking->setTracking( TrackingStyleConfig::TrackingState::DisabledByUser ); +} diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index bd9ba520e..26dcf2f4f 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -173,6 +173,9 @@ public Q_SLOTS: MachineTrackingConfig* machineTracking() const { return m_machineTracking; } UserTrackingConfig* userTracking() const { return m_userTracking; } + /// @brief Call with @c true to turn off all the trackings + void noTracking( bool ); + signals: void generalPolicyChanged( QString ); diff --git a/src/modules/tracking/TrackingType.h b/src/modules/tracking/TrackingType.h index 04e8d2ebe..22e3157d6 100644 --- a/src/modules/tracking/TrackingType.h +++ b/src/modules/tracking/TrackingType.h @@ -29,7 +29,7 @@ enum class TrackingType UserTracking // Track the user, ongoing }; -// Implemented in TrackingViewStep.cpp +// Implemented in Config.cpp const NamedEnumTable< TrackingType >& trackingNames(); #endif //TRACKINGTYPE_H diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 9942c2981..491fef12a 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -127,28 +127,5 @@ void TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_config->setConfigurationMap( configurationMap ); - - bool ok; - m_widget->setTrackingLevel( trackingNames().find( CalamaresUtils::getString( configurationMap, "default" ), ok ) ); - if ( !ok ) - { - cWarning() << "Default tracking level unknown:" << CalamaresUtils::getString( configurationMap, "default" ); - } } -const NamedEnumTable< TrackingType >& -trackingNames() -{ - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< TrackingType > names { - { QStringLiteral( "none" ), TrackingType::NoTracking }, - { QStringLiteral( "install" ), TrackingType::InstallTracking }, - { QStringLiteral( "machine" ), TrackingType::MachineTracking }, - { QStringLiteral( "user" ), TrackingType::UserTracking } - }; - // clang-format on - // *INDENT-ON* - - return names; -} From fab3ff2c41dbec28a0ee307c0c35d06738aff3fb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 May 2020 09:56:32 -0400 Subject: [PATCH 020/105] [tracking] Implement KUserFeedback configuration - write config files to turn on KUserFeedback (for known areas) - TODO: get the right home directory to write in --- src/modules/tracking/TrackingJobs.cpp | 69 +++++++++++++++++++++++++++ src/modules/tracking/TrackingJobs.h | 34 +++++++++++++ 2 files changed, 103 insertions(+) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 40af355bd..18d01c7ca 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -162,3 +162,72 @@ true tr( "Could not configure machine feedback correctly, Calamares error %1." ).arg( r ) ); } } + +void +TrackingUserJob::addJob( Calamares::JobList& list, UserTrackingConfig* config ) +{ + if ( config->isEnabled() ) + { + const auto style = config->userTrackingStyle(); + if ( style == "kuserfeedback" ) + { + list.append( Calamares::job_ptr( new TrackingKUserFeedbackJob() ) ); + } + else + { + cWarning() << "Unsupported user tracking style" << style; + } + } +} + +QString +TrackingKUserFeedbackJob::prettyName() const +{ + return tr( "KDE user feedback" ); +} + +QString +TrackingKUserFeedbackJob::prettyDescription() const +{ + return prettyName(); +} + +QString +TrackingKUserFeedbackJob::prettyStatusMessage() const +{ + return tr( "Configuring KDE user feedback." ); +} + +Calamares::JobResult +TrackingKUserFeedbackJob::exec() +{ + // This is the contents of a config file to turn on some kind + // of KUserFeedback tracking; the level (16) is chosen for minimal + // but not zero tracking. + static const char config[] = R"x([Global] +FeedbackLevel=16 +)x"; + + for ( const QString& area : QStringList { "PlasmaUserFeedback" } ) + { + // TODO: get the configured user name + QString path = QStringLiteral( "/home/%1/.config/%2" ).arg( QString(), area ); + cDebug() << "Configuring KUserFeedback" << path; + + int r = CalamaresUtils::System::instance()->createTargetFile( path, config ); + if ( r > 0 ) + { + return Calamares::JobResult::error( + tr( "Error in KDE user feedback configuration." ), + tr( "Could not configure KDE user feedback correctly, script error %1." ).arg( r ) ); + } + else if ( r < 0 ) + { + return Calamares::JobResult::error( + tr( "Error in KDE user feedback configuration." ), + tr( "Could not configure KDE user feedback correctly, Calamares error %1." ).arg( r ) ); + } + } + + return Calamares::JobResult::ok(); +} diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h index c7c2450cb..76e7dbed9 100644 --- a/src/modules/tracking/TrackingJobs.h +++ b/src/modules/tracking/TrackingJobs.h @@ -23,6 +23,7 @@ class InstallTrackingConfig; class MachineTrackingConfig; +class UserTrackingConfig; class QSemaphore; @@ -75,6 +76,12 @@ public: static void addJob( Calamares::JobList& list, MachineTrackingConfig* config ); }; +/** @brief Tracking machines, KDE neon style + * + * The machine has a machine-id, and this is sed(1)'ed into the + * update-manager configuration, to report the machine-id back + * to KDE neon servers. + */ class TrackingMachineNeonJob : public TrackingMachineJob { Q_OBJECT @@ -85,5 +92,32 @@ public: Calamares::JobResult exec() override; }; +/** @brief Base class for user-tracking jobs + * + * User-tracking configuration depends on the distro / style of user + * tracking being implemented, so there are subclasses to switch on the + * relevant kind of tracking. Users are tracked persistently (the user + * can of course configure the tracking again once the system is restarted). + */ +class TrackingUserJob : public Calamares::Job +{ +public: + static void addJob( Calamares::JobList& list, UserTrackingConfig* config ); +}; + +/** @brief Turn on KUserFeedback in target system + * + * This writes suitable files for turning on KUserFeedback for the + * normal user configured in Calamares. The feedback can be reconfigured + * by the user through Plasma's user-feedback dialog. + */ +class TrackingKUserFeedbackJob : public Calamares::Job +{ +public: + QString prettyName() const override; + QString prettyDescription() const override; + QString prettyStatusMessage() const override; + Calamares::JobResult exec() override; +}; #endif From 60e12174fd117e78d6984f28aafe6aa2a7a69fd9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 May 2020 10:32:56 -0400 Subject: [PATCH 021/105] [tracking] Switch out Radio for CheckBox - The Radio's are replaced by CheckBoxes and some logic, so that different tracking styles can be enabled independently. None of the settings end up in the Config yet, though. --- src/modules/tracking/TrackingPage.cpp | 67 +++++++++++++---------- src/modules/tracking/TrackingPage.h | 17 +++++- src/modules/tracking/page_trackingstep.ui | 8 +-- 3 files changed, 55 insertions(+), 37 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 02bc94195..e42ae2312 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -40,13 +40,15 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) ui->setupUi( this ); CALAMARES_RETRANSLATE_SLOT( &TrackingPage::retranslate ); - QButtonGroup* group = new QButtonGroup( this ); - group->setExclusive( true ); - group->addButton( ui->noneRadio ); - group->addButton( ui->installRadio ); - group->addButton( ui->machineRadio ); - group->addButton( ui->userRadio ); - ui->noneRadio->setChecked( true ); + ui->noneCheckBox->setChecked( true ); + connect( ui->noneCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::noneChecked ); + connect( ui->installCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::otherChecked ); + connect( ui->machineCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::otherChecked ); + connect( ui->userCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::otherChecked ); + + connect( ui->installCheckBox, &QCheckBox::stateChanged, [ this ]( int s ) { cDebug() << "Checkbox install changed" << s; } ); + connect( config->installTracking(), &TrackingStyleConfig::trackingChanged, [ config ]() { cDebug() << + "Install tracking changed" << config->installTracking()->isEnabled(); } ) ; connect( config, &Config::generalPolicyChanged, [ this ]( const QString& url ) { this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); @@ -85,30 +87,35 @@ TrackingPage::retranslate() .arg( product ) ); } - -void -TrackingPage::setTrackingLevel( TrackingType t ) +void TrackingPage::noneChecked(int state) { - QRadioButton* button = nullptr; - - switch ( t ) + if ( state ) { - case TrackingType::NoTracking: - button = ui->noneRadio; - break; - case TrackingType::InstallTracking: - button = ui->installRadio; - break; - case TrackingType::MachineTracking: - button = ui->machineRadio; - break; - case TrackingType::UserTracking: - button = ui->userRadio; - break; - } - - if ( button != nullptr ) - { - button->setChecked( true ); + cDebug() << "Unchecking all due to none box"; + ui->installCheckBox->setChecked( false ); + ui->machineCheckBox->setChecked( false ); + ui->userCheckBox->setChecked( false ); + } +} + +void TrackingPage::otherChecked(int state) +{ + cDebug() << "Other checked" << state; + if ( state ) + { + // Can't have none checked, if another one is + ui->noneCheckBox->setChecked( false ); + } + else + { + if ( ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked() ) + { + // One of them is still checked, leave *none* alone + ; + } + else + { + ui->noneCheckBox->setChecked( true ); + } } } diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index f63f7375c..e4c465fbc 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -37,12 +37,23 @@ class TrackingPage : public QWidget public: explicit TrackingPage( Config* config, QWidget* parent = nullptr ); - ///@brief Select one of the four levels by name - void setTrackingLevel( TrackingType t ); - public Q_SLOTS: void retranslate(); + /** @brief When the *no tracking* checkbox is changed + * + * @p state will be non-zero when the box is checked; this + * **unchecks** all the other boxes. + */ + void noneChecked( int state ); + + /** @brief Some other checkbox changed + * + * This may check the *none* button if all the others are + * now unchecked. + */ + void otherChecked( int state ); + private: Ui::TrackingPage* ui; }; diff --git a/src/modules/tracking/page_trackingstep.ui b/src/modules/tracking/page_trackingstep.ui index 9612ef2b4..4383d312d 100644 --- a/src/modules/tracking/page_trackingstep.ui +++ b/src/modules/tracking/page_trackingstep.ui @@ -32,7 +32,7 @@ margin-left: 2em; - + @@ -83,7 +83,7 @@ margin-left: 2em; - + @@ -145,7 +145,7 @@ margin-left: 2em; - + @@ -207,7 +207,7 @@ margin-left: 2em; - + From c6174b027ca1c9e11336bdee61885d1ab338830a Mon Sep 17 00:00:00 2001 From: AI Lion Date: Sun, 31 May 2020 00:31:05 +0800 Subject: [PATCH 022/105] remove unnecessary period mark since it's a title --- src/modules/welcome/Config.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index 71d6de9bb..c842e2451 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -229,14 +229,14 @@ Config::genericWelcomeMessage() const if ( Calamares::Settings::instance()->isSetupMode() ) { message = Calamares::Branding::instance()->welcomeStyleCalamares() - ? tr( "

Welcome to the Calamares setup program for %1.

" ) - : tr( "

Welcome to %1 setup.

" ); + ? tr( "

Welcome to the Calamares setup program for %1

" ) + : tr( "

Welcome to %1 setup

" ); } else { message = Calamares::Branding::instance()->welcomeStyleCalamares() - ? tr( "

Welcome to the Calamares installer for %1.

" ) - : tr( "

Welcome to the %1 installer.

" ); + ? tr( "

Welcome to the Calamares installer for %1

" ) + : tr( "

Welcome to the %1 installer

" ); } return message; From fb3bc12aac5a3702f5d3669905b4cd7bd9057eb5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 6 Jun 2020 17:21:14 +0200 Subject: [PATCH 023/105] Post-release housekeeping --- CHANGES | 13 +++++++++++++ CMakeLists.txt | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 34c61c40c..64102fae8 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,18 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. +# 3.2.26 (unreleased) # + +This release contains contributions from (alphabetically by first name): + - No external contributors yet + +## Core ## + - No core changes yet + +## Modules ## + - No module changes yet + + # 3.2.25 (2020-06-06) # This release contains contributions from (alphabetically by first name): @@ -37,6 +49,7 @@ This release contains contributions from (alphabetically by first name): - The *keyboard* module no longer uses *ca_eng* keyboards in Canada by default, but sticks to the *us* keyboard. #1419 + # 3.2.24 (2020-05-11) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index d01cdf7f3..020b83e80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,10 +40,10 @@ cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) project( CALAMARES - VERSION 3.2.25 + VERSION 3.2.26 LANGUAGES C CXX ) -set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development +set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development ### OPTIONS # From 73eb718c08395cdac05ecfeabcbf01e441ded6da Mon Sep 17 00:00:00 2001 From: demmm Date: Mon, 8 Jun 2020 13:25:47 +0200 Subject: [PATCH 024/105] adding needed geoip section to welcomeq.conf see https://github.com/calamares/calamares/issues/1427#issuecomment-640531710 --- src/modules/welcomeq/welcomeq.conf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/modules/welcomeq/welcomeq.conf b/src/modules/welcomeq/welcomeq.conf index 2553e157a..6c2cf9557 100644 --- a/src/modules/welcomeq/welcomeq.conf +++ b/src/modules/welcomeq/welcomeq.conf @@ -62,3 +62,21 @@ requirements: # - storage - ram # - root + +# GeoIP checking +# +# This can be used to pre-select a language based on the country +# the user is currently in. It *assumes* that there's internet +# connectivity, though. Configuration is like in the locale module, +# but remember to use a URL that returns full data **and** to +# use a selector that will pick the country, not the timezone. +# +# To disable GeoIP checking, either comment-out the entire geoip section, +# or set the *style* key to an unsupported format (e.g. `none`). +# Also, note the analogous feature in `src/modules/locale/locale.conf`, +# which is where you will find complete documentation. +# +geoip: + style: "none" + url: "https://geoip.kde.org/v1/ubiquity" # extended XML format + selector: "CountryCode" # blank uses default, which is wrong From 8255bc3fc129b46fec577b3501d061b6056fa2ce Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jun 2020 07:06:03 -0400 Subject: [PATCH 025/105] [welcome] Sanitize example configurations - remove all duplicated documentation from ; it's the same as `welcome.conf` in all respects except for *qmlSearch*. --- src/modules/welcome/welcome.conf | 8 ++++ src/modules/welcomeq/welcomeq.conf | 66 ++++-------------------------- 2 files changed, 17 insertions(+), 57 deletions(-) diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index d8da60d19..45cb654a2 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -67,6 +67,14 @@ requirements: # Also, note the analogous feature in `src/modules/locale/locale.conf`, # which is where you will find complete documentation. # +# For testing, the *style* may be set to `fixed`, any URL that +# returns data (e.g. `http://example.com`) and then *selector* +# sets the data that is actually returned (e.g. "DE" to simulate +# the machine being in Germany). +# +# NOTE: the *selector* must pick the country code from the GeoIP +# data. Timezone, city, or other data will not be recognized. +# geoip: style: "none" url: "https://geoip.kde.org/v1/ubiquity" # extended XML format diff --git a/src/modules/welcomeq/welcomeq.conf b/src/modules/welcomeq/welcomeq.conf index 6c2cf9557..6c131742e 100644 --- a/src/modules/welcomeq/welcomeq.conf +++ b/src/modules/welcomeq/welcomeq.conf @@ -1,52 +1,23 @@ -# Configuration for the welcome module. The welcome page -# displays some information from the branding file. -# Which parts it displays can be configured through -# the show* variables. +# Configuration for the welcomeq module. # -# In addition to displaying the welcome page, this module -# can check requirements for installation. +# The configuration for welcomeq is exactly the same +# as the welcome module, with the one exception of +# *qmlSearch* which governs QML loading. +# +# No documentation is given here: look in the welcome module. --- -# Setting for QML loading +# Setting for QML loading: use QRC, branding, or both sources of files qmlSearch: both -# Display settings for various buttons on the welcome page. -# The URLs themselves come from branding.desc is the setting -# here is "true". If the setting is false, the button is hidden. -# The setting can also be a full URL which will then be used -# instead of the one from the branding file, or empty or not-set -# which will hide the button. + +# Everythin below here is documented in `welcome.conf` showSupportUrl: true showKnownIssuesUrl: true showReleaseNotesUrl: true -# If this Url is set to something non-empty, a "donate" -# button is added to the welcome page alongside the -# others (see settings, above). Clicking the button opens -# the corresponding link. (This button has no corresponding -# branding.desc string) -# -# showDonateUrl: https://kde.org/community/donations/ - -# Requirements checking. These are general, generic, things -# that are checked. They may not match with the actual requirements -# imposed by other modules in the system. requirements: - # Amount of available disk, in GiB. Floating-point is allowed here. - # Note that this does not account for *usable* disk, so it is possible - # to pass this requirement, yet have no space to install to. requiredStorage: 5.5 - - # Amount of available RAM, in GiB. Floating-point is allowed here. requiredRam: 1.0 - - # To check for internet connectivity, Calamares does a HTTP GET - # on this URL; on success (e.g. HTTP code 200) internet is OK. internetCheckUrl: http://google.com - - # List conditions to check. Each listed condition will be - # probed in some way, and yields true or false according to - # the host system satisfying the condition. - # - # This sample file lists all the conditions that are known. check: - storage - ram @@ -54,28 +25,9 @@ requirements: - internet - root - screen - # List conditions that **must** be satisfied (from the list - # of conditions, above) for installation to proceed. - # If any of these conditions are not met, the user cannot - # continue past the welcome page. required: - # - storage - ram - # - root -# GeoIP checking -# -# This can be used to pre-select a language based on the country -# the user is currently in. It *assumes* that there's internet -# connectivity, though. Configuration is like in the locale module, -# but remember to use a URL that returns full data **and** to -# use a selector that will pick the country, not the timezone. -# -# To disable GeoIP checking, either comment-out the entire geoip section, -# or set the *style* key to an unsupported format (e.g. `none`). -# Also, note the analogous feature in `src/modules/locale/locale.conf`, -# which is where you will find complete documentation. -# geoip: style: "none" url: "https://geoip.kde.org/v1/ubiquity" # extended XML format From f35fab24ac310cec92d79e837e826bbf5f40259a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jun 2020 08:05:46 -0400 Subject: [PATCH 026/105] [welcome] Remove name-tangle - use useful, not-single-letter, variable names - don't rename inconsistently in the lambda capture --- src/modules/welcome/Config.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index c842e2451..20e049186 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -336,7 +336,7 @@ setCountry( Config* config, const QString& countryCode, CalamaresUtils::GeoIP::H } static inline void -setGeoIP( Config* c, const QVariantMap& configurationMap ) +setGeoIP( Config* config, const QVariantMap& configurationMap ) { bool ok = false; QVariantMap geoip = CalamaresUtils::getSubMap( configurationMap, "geoip", ok ); @@ -350,12 +350,12 @@ setGeoIP( Config* c, const QVariantMap& configurationMap ) if ( handler->type() != CalamaresUtils::GeoIP::Handler::Type::None ) { auto* future = new FWString(); - QObject::connect( future, &FWString::finished, [config = c, f = future, h = handler]() { - QString countryResult = f->future().result(); + QObject::connect( future, &FWString::finished, [config, future, handler]() { + QString countryResult = future->future().result(); cDebug() << "GeoIP result for welcome=" << countryResult; - ::setCountry( config, countryResult, h ); - f->deleteLater(); - delete h; + ::setCountry( config, countryResult, handler ); + future->deleteLater(); + delete handler; } ); future->setFuture( handler->queryRaw() ); } From abe558f12707fdc84c72644105cd68e16572cdce Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jun 2020 08:27:06 -0400 Subject: [PATCH 027/105] [libcalamares] Be more verbose when the requirements check is done --- src/libcalamares/modulesystem/RequirementsModel.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/modulesystem/RequirementsModel.cpp b/src/libcalamares/modulesystem/RequirementsModel.cpp index 6f9fc1e7b..41a5616c1 100644 --- a/src/libcalamares/modulesystem/RequirementsModel.cpp +++ b/src/libcalamares/modulesystem/RequirementsModel.cpp @@ -1,5 +1,5 @@ /* === This file is part of Calamares - === - * + * * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify @@ -96,13 +96,16 @@ RequirementsModel::roleNames() const void RequirementsModel::describe() const { + cDebug() << "Requirements model has" << m_requirements.count() << "items"; bool acceptable = true; int count = 0; for ( const auto& r : m_requirements ) { + cDebug() << Logger::SubEntry << "requirement" << count << r.name + << "satisfied?" << r.satisfied + << "mandatory?" << r.mandatory; if ( r.mandatory && !r.satisfied ) { - cDebug() << Logger::SubEntry << "requirement" << count << r.name << "is not satisfied."; acceptable = false; } ++count; From 5b1e5a9e037f11de4d964486f9e98704584cd78e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jun 2020 09:45:19 -0400 Subject: [PATCH 028/105] [welcome] Some API docs --- src/modules/welcome/Config.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/modules/welcome/Config.h b/src/modules/welcome/Config.h index 7fe6fa04e..4ce3999c0 100644 --- a/src/modules/welcome/Config.h +++ b/src/modules/welcome/Config.h @@ -28,7 +28,20 @@ class Config : public QObject { Q_OBJECT + /** @brief The languages available in Calamares. + * + * This is a list-model, with names and descriptions for the translations + * available to Calamares. + */ Q_PROPERTY( CalamaresUtils::Locale::LabelModel* languagesModel READ languagesModel CONSTANT FINAL ) + /** @brief The requirements (from modules) and their checked-status + * + * The model grows rows over time as each module is checked and its + * requirements are taken into account. The model **as a whole** + * has properties *satisfiedRequirements* and *satisfiedMandatory* + * to say if all of the requirements held in the model have been + * satisfied. See the model documentation for details. + */ Q_PROPERTY( Calamares::RequirementsModel* requirementsModel READ requirementsModel CONSTANT FINAL ) Q_PROPERTY( QString languageIcon READ languageIcon CONSTANT FINAL ) From d1165bea56c33ddc375099215b3fef706c0d7663 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Jun 2020 10:22:03 -0400 Subject: [PATCH 029/105] [welcomeq] Use just one component to display requirements - Do all the status indication in one component, but vary the top-level message based on whether the mandatory requirements are satisfied. - Vary color and icon based on each requirement's *mandatory* setting. --- src/modules/welcomeq/Recommended.qml | 2 ++ src/modules/welcomeq/Requirements.qml | 27 ++++++++++++++++++++------- src/modules/welcomeq/welcomeq.qml | 6 +----- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/modules/welcomeq/Recommended.qml b/src/modules/welcomeq/Recommended.qml index 636311b11..5a6c1316d 100644 --- a/src/modules/welcomeq/Recommended.qml +++ b/src/modules/welcomeq/Recommended.qml @@ -17,6 +17,8 @@ * along with Calamares. If not, see . */ +/* THIS COMPONENT IS UNUSED -- from the default welcomeq.qml at least */ + import io.calamares.core 1.0 import io.calamares.ui 1.0 diff --git a/src/modules/welcomeq/Requirements.qml b/src/modules/welcomeq/Requirements.qml index e81d0a2e6..a376c6010 100644 --- a/src/modules/welcomeq/Requirements.qml +++ b/src/modules/welcomeq/Requirements.qml @@ -44,8 +44,12 @@ Rectangle { activeFocusOnPress: false wrapMode: Text.WordWrap - text: qsTr("

This computer does not satisfy the minimum requirements for installing %1.
+ property var requirementsText: qsTr("

This computer does not satisfy the minimum requirements for installing %1.
Installation cannot continue.

").arg(Branding.string(Branding.VersionedName)) + property var recommendationsText: qsTr("

This computer does not satisfy some of the recommended requirements for setting up %1.
+ Setup can continue, but some features might be disabled.

").arg(Branding.string(Branding.VersionedName)) + + text: config.requirementsModel.satisfiedMandatory ? recommendationsText : requirementsText } Rectangle { @@ -60,26 +64,34 @@ Rectangle { Item { width: 640 - height: 35 + // Hide the satisfied requirements; we could do that with + // a filtering model, but here we'll just hide it, but also + // need to compensate for the spacing between items. + height: !satisfied ? 35 : -requirementsList.spacing + visible: !satisfied Column { anchors.centerIn: parent Rectangle { implicitWidth: 640 - implicitHeight: 35 - border.color: mandatory ? "#228b22" : "#ff0000" - color: mandatory ? "#f0fff0" : "#ffc0cb" + implicitHeight: !satisfied ? 35 : 0 + // Colors and images based on the two satisfied-bools: + // - if satisfied, then green / ok + // - otherwise if mandatory, then red / stop + // - otherwise, then yellow / warning + border.color: satisfied ? "#228b22" : (mandatory ? "#ff0000" : "#ffa411") + color: satisfied ? "#f0fff0" : (mandatory ? "#ffc0cb" : "#ffefd5") Image { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.margins: 20 - source: mandatory ? "qrc:/data/images/yes.svgz" : "qrc:/data/images/no.svgz" + source: satisfied ? "qrc:/data/images/yes.svgz" : (mandatory ? "qrc:/data/images/no.svgz" : "qrc:/data/images/information.svgz") } Text { - text: mandatory ? details : negatedText + text: satisfied ? details : negatedText anchors.centerIn: parent font.pointSize: 11 } @@ -89,6 +101,7 @@ Rectangle { } ListView { + id: requirementsList anchors.fill: parent spacing: 5 model: config.requirementsModel diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml index b92ff9628..ffa480f4a 100644 --- a/src/modules/welcomeq/welcomeq.qml +++ b/src/modules/welcomeq/welcomeq.qml @@ -56,12 +56,8 @@ Page fillMode: Image.PreserveAspectFit } - Recommended { - visible: !config.requirementsModel.satisfiedRequirements - } - Requirements { - visible: !config.requirementsModel.satisfiedMandatory + visible: !config.requirementsModel.satisfiedRequirements } RowLayout { From f68d0f0628c6343d87fae8364b165bb8472f0588 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 12:05:40 +0200 Subject: [PATCH 030/105] [welcome] Add a filtered model for unsatisfied requirements --- src/modules/welcome/Config.cpp | 13 +++++++++++++ src/modules/welcome/Config.h | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index 20e049186..2bf418ff1 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -32,6 +32,7 @@ Config::Config( QObject* parent ) : QObject( parent ) , m_languages( CalamaresUtils::Locale::availableTranslations() ) + , m_filtermodel( std::make_unique< QSortFilterProxyModel >() ) { initLanguages(); @@ -97,6 +98,18 @@ Config::requirementsModel() const return Calamares::ModuleManager::instance()->requirementsModel(); } +QAbstractItemModel* +Config::unsatisfiedRequirements() const +{ + if ( !m_filtermodel->sourceModel() ) + { + m_filtermodel->setFilterRole( Calamares::RequirementsModel::Roles::Satisfied ); + m_filtermodel->setFilterFixedString( QStringLiteral( "false" ) ); + m_filtermodel->setSourceModel( requirementsModel() ); + } + return m_filtermodel.get(); +} + QString Config::languageIcon() const diff --git a/src/modules/welcome/Config.h b/src/modules/welcome/Config.h index 4ce3999c0..6d14097c5 100644 --- a/src/modules/welcome/Config.h +++ b/src/modules/welcome/Config.h @@ -23,8 +23,11 @@ #include "modulesystem/RequirementsModel.h" #include +#include #include +#include + class Config : public QObject { Q_OBJECT @@ -43,6 +46,14 @@ class Config : public QObject * satisfied. See the model documentation for details. */ Q_PROPERTY( Calamares::RequirementsModel* requirementsModel READ requirementsModel CONSTANT FINAL ) + /** @brief The requirements (from modules) that are **unsatisfied** + * + * This is the same as requirementsModel(), except filtered so + * that only those requirements that are not satisfied are exposed. + * Note that the type is different, so you should still use the + * requirementsModel() for overall status like *satisfiedMandatory*. + */ + Q_PROPERTY( QAbstractItemModel* unsatisfiedRequirements READ unsatisfiedRequirements CONSTANT FINAL ) Q_PROPERTY( QString languageIcon READ languageIcon CONSTANT FINAL ) @@ -96,6 +107,8 @@ public slots: ///@brief The **global** requirements model, from ModuleManager Calamares::RequirementsModel* requirementsModel() const; + QAbstractItemModel* unsatisfiedRequirements() const; + signals: void countryCodeChanged( QString countryCode ); void localeIndexChanged( int localeIndex ); @@ -112,7 +125,8 @@ signals: private: void initLanguages(); - CalamaresUtils::Locale::LabelModel* m_languages; + CalamaresUtils::Locale::LabelModel* m_languages = nullptr; + std::unique_ptr< QSortFilterProxyModel > m_filtermodel; QString m_languageIcon; QString m_countryCode; From d22178ca5e91bfdbf74bd92e6cc1baceebdcdc23 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 12:13:44 +0200 Subject: [PATCH 031/105] [welcomeq] Show filtered list of requirements - only the unsatisfied ones are shown; no need to filter and fiddle about in QML --- src/modules/welcomeq/Requirements.qml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/welcomeq/Requirements.qml b/src/modules/welcomeq/Requirements.qml index a376c6010..e7835d868 100644 --- a/src/modules/welcomeq/Requirements.qml +++ b/src/modules/welcomeq/Requirements.qml @@ -64,18 +64,15 @@ Rectangle { Item { width: 640 - // Hide the satisfied requirements; we could do that with - // a filtering model, but here we'll just hide it, but also - // need to compensate for the spacing between items. - height: !satisfied ? 35 : -requirementsList.spacing - visible: !satisfied + height: 35 + visible: true Column { anchors.centerIn: parent Rectangle { implicitWidth: 640 - implicitHeight: !satisfied ? 35 : 0 + implicitHeight: 35 // Colors and images based on the two satisfied-bools: // - if satisfied, then green / ok // - otherwise if mandatory, then red / stop @@ -104,7 +101,10 @@ Rectangle { id: requirementsList anchors.fill: parent spacing: 5 - model: config.requirementsModel + // This uses the filtered model, so that only unsatisfied + // requirements are ever shown. You could use *requirementsModel* + // to get all of them. + model: config.unsatisfiedRequirements delegate: requirementsDelegate } } From 35fb8dcc27bc9ed823808cea0191c19f2aca8333 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 13:24:12 +0200 Subject: [PATCH 032/105] [mount] Warn if chcon is missing, rather than fail FIXES #1429 --- src/modules/mount/main.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index b10c5c0bf..4e16b43c3 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -52,8 +52,13 @@ def mount_partition(root_mount_point, partition, partitions): # Ensure that the created directory has the correct SELinux context on # SELinux-enabled systems. os.makedirs(mount_point, exist_ok=True) - subprocess.call(['chcon', '--reference=' + raw_mount_point, - mount_point]) + try: + subprocess.call(['chcon', '--reference=' + raw_mount_point, mount_point]) + except FileNotFoundError as e: + libcalamares.utils.warning(str(e)) + except OSError: + libcalamares.utils.error("Cannot run 'chcon' normally.") + raise fstype = partition.get("fs", "").lower() From a617dba85ee15513e8cb960d4b7b9e5d370a93bb Mon Sep 17 00:00:00 2001 From: demmm Date: Tue, 9 Jun 2020 13:34:16 +0200 Subject: [PATCH 033/105] [welcomeq]re-add the donate button example to welcomeq.conf --- src/modules/welcomeq/welcomeq.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/welcomeq/welcomeq.conf b/src/modules/welcomeq/welcomeq.conf index 6c131742e..32be7fcb5 100644 --- a/src/modules/welcomeq/welcomeq.conf +++ b/src/modules/welcomeq/welcomeq.conf @@ -13,6 +13,7 @@ qmlSearch: both showSupportUrl: true showKnownIssuesUrl: true showReleaseNotesUrl: true +# showDonateUrl: https://kde.org/community/donations/ requirements: requiredStorage: 5.5 From d511cc2f7a74576338f9bdad1fc9241e5847a541 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 14:21:11 +0200 Subject: [PATCH 034/105] [locale] Norfolk Island gave up +11.5 in 2015 --- src/modules/locale/images/timezone_11.5.png | Bin 867 -> 0 bytes src/modules/locale/locale.qrc | 1 - .../locale/timezonewidget/TimeZoneImage.cpp | 4 ++-- src/modules/locale/timezonewidget/TimeZoneImage.h | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) delete mode 100644 src/modules/locale/images/timezone_11.5.png diff --git a/src/modules/locale/images/timezone_11.5.png b/src/modules/locale/images/timezone_11.5.png deleted file mode 100644 index 442cabfebf69ac0452942abbd78e57c452b960be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 867 zcmeAS@N?(olHy`uVBq!ia0y~yVCG?9U<~1428!%^?EMQ!v7|ftIx;Y9?C1WI$O_~$ z76-XIF|0c$^AgBWNcITwWnidMV_;}#VPF8MZ+OALP-?)y@G60U!D~oA+A800munwU*Y5T$-|EqN zG!V!JqPF8f72Cb?*Spm0_HNkc3q-YheDl}2^qdXtJ{t;D&~rYt=Uiy#>EQqW|4%3u zF$OwJyCldj8010(U}9lqWi*|(b@O&3uPd%zS6w~N|N8OUMcgScAV{qJwwnV`DPxki zyNlt?+pr{4!35MgOhChYt*cQdnR(h2TP{Yh_$=G3GE?8>K+)GTpRY%;NXS&x%nxXX_XKS29~-; zh9L$9R;I>Q2FBV3MnDY>kIMCd8YDqB1m~xflqVLYGL)B>>t*I;7bhncr0V4trO$q6 RBL!5%;OXk;vd$@?2>@z!)F1!= diff --git a/src/modules/locale/locale.qrc b/src/modules/locale/locale.qrc index b6b0d0cf7..713943ae7 100644 --- a/src/modules/locale/locale.qrc +++ b/src/modules/locale/locale.qrc @@ -21,7 +21,6 @@ images/timezone_10.0.png images/timezone_10.5.png images/timezone_11.0.png - images/timezone_11.5.png images/timezone_12.0.png images/timezone_12.75.png images/timezone_13.0.png diff --git a/src/modules/locale/timezonewidget/TimeZoneImage.cpp b/src/modules/locale/timezonewidget/TimeZoneImage.cpp index 52ddc24b1..eec939905 100644 --- a/src/modules/locale/timezonewidget/TimeZoneImage.cpp +++ b/src/modules/locale/timezonewidget/TimeZoneImage.cpp @@ -26,7 +26,7 @@ static const char* zoneNames[] = { "0.0", "1.0", "2.0", "3.0", "3.5", "4.0", "4.5", "5.0", "5.5", "5.75", "6.0", "6.5", "7.0", - "8.0", "9.0", "9.5", "10.0", "10.5", "11.0", "11.5", "12.0", "12.75", "13.0", "-1.0", "-2.0", "-3.0", + "8.0", "9.0", "9.5", "10.0", "10.5", "11.0", "12.0", "12.75", "13.0", "-1.0", "-2.0", "-3.0", "-3.5", "-4.0", "-4.5", "-5.0", "-5.5", "-6.0", "-7.0", "-8.0", "-9.0", "-9.5", "-10.0", "-11.0" }; static_assert( TimeZoneImageList::zoneCount == ( sizeof( zoneNames ) / sizeof( zoneNames[ 0 ] ) ), "Incorrect number of zones" ); @@ -36,7 +36,7 @@ static_assert( TimeZoneImageList::zoneCount == ( sizeof( zoneNames ) / sizeof( z /* static constexpr */ const int TimeZoneImageList::zoneCount; /* static constexpr */ const QSize TimeZoneImageList::imageSize; -static_assert( TimeZoneImageList::zoneCount == 38 ); +static_assert( TimeZoneImageList::zoneCount == 37 ); TimeZoneImageList::TimeZoneImageList() {} diff --git a/src/modules/locale/timezonewidget/TimeZoneImage.h b/src/modules/locale/timezonewidget/TimeZoneImage.h index 0a3aea145..ee02bfbfd 100644 --- a/src/modules/locale/timezonewidget/TimeZoneImage.h +++ b/src/modules/locale/timezonewidget/TimeZoneImage.h @@ -77,7 +77,7 @@ public: QImage find( QPoint p ) const; /// @brief The **expected** number of zones in the list. - static constexpr const int zoneCount = 38; + static constexpr const int zoneCount = 37; /// @brief The expected size of each zone image. static constexpr const QSize imageSize = QSize( 780, 340 ); }; From 38b4f45b92d72fed916f9b0d3a5d3112534028ac Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 14:40:13 +0200 Subject: [PATCH 035/105] [locale] Repair timezone graphics -- west-Africa and Pacific --- src/modules/locale/images/timezone_-1.0.png | Bin 15641 -> 12010 bytes src/modules/locale/images/timezone_-10.0.png | Bin 10561 -> 10414 bytes src/modules/locale/images/timezone_-7.0.png | Bin 15090 -> 15126 bytes src/modules/locale/images/timezone_0.0.png | Bin 19182 -> 16289 bytes src/modules/locale/images/timezone_10.0.png | Bin 22594 -> 18305 bytes src/modules/locale/images/timezone_11.0.png | Bin 13472 -> 13590 bytes src/modules/locale/images/timezone_12.0.png | Bin 7704 -> 8116 bytes src/modules/locale/images/timezone_2.0.png | Bin 21508 -> 18803 bytes 8 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/modules/locale/images/timezone_-1.0.png b/src/modules/locale/images/timezone_-1.0.png index 50ced39802ee3f7f75864c53b6f6c72bbc3cfb16..4fdbd0e3fef0ca2aa4834b053be3b8133f7f106c 100644 GIT binary patch literal 12010 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 GhyO2s3}qq! diff --git a/src/modules/locale/images/timezone_-7.0.png b/src/modules/locale/images/timezone_-7.0.png index a4a12b9aef605aafe6354235d2dfc15d458287f9..c3f98ecbc11c6435070130e0f72025421d34f5b8 100644 GIT binary patch literal 15126 zcmeIZXHc6@3#s-3m9>;SiHA>Z)_T5CGb}#+)Aa6l1%e7S>CXebf7)`r zn51~(7oh&)-aiOJTP~W%?Ln4;4T$KYTRORI?sfZ(!(*A(Nv3*#QXGy! z?YY&SYTVHj4gd2Qf84vJF)t#bc{L)Ur3WM=<|B`wZ~p)b3w>25;R4w5niT)=jYYKz zVD_Genu#|70Z~5w?+@iUVc-h^osY7ykAb_R57frXfdC4H3OGZ+-gY(~4g&68PMLeM z^Z*bC9?0It$3fc8%K>NzM1+Jz_<@g*$ZO$e(xQ^m&&2qIgr$Xqf@mCS{>uP2cY9~Y zfd3dEB*iZx{8~szT1-@0NR&@V1Q_sk87fFX@Pt5J>BVdRterXMf3h(lpD%8u_Px#! zXApw9$rpd#`NNZ3Sv{?&t9n(hB$i6L^oYH}fLXUYqb}>$_-om|$DhQKHI}2{<^t(G zX$Cw!Iu1L-Q5?$g)S4n3nva#qXQPmRJbMc{2|dGE3}%oKC`T`I{832bvvOhhjywNy z{%rO^aGh@MS=P5ZGZQzuSKmHF8?eyJ9F2Xd2DylK55tFoyoatwa?Jylj*nSwCG3E8 zL{R4&SVau91dFH2Lilzg#v0!Y)3oE8uY&LY0Gj7kcL;&zZOgx_jv#~_Ka}7%D=oe` z`QI5>-tz3W6Bt}00<9u`i{KG|7eAvd%o*6T|6rO5?d(4M6?j;_ewS!g76GgBLW}d! z>9Eqqzn$pbpAuRX%0ASN%9 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 literal 15090 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 XW|oEtd;G)z5sHMU%!k7F+8+NG*3hM& diff --git a/src/modules/locale/images/timezone_0.0.png b/src/modules/locale/images/timezone_0.0.png index 02a4c8f8b112254df490d33a5d2d0e19f8cdb8d0..f098b9c67e3701d81751523d2be9ec79911c9099 100644 GIT binary patch literal 16289 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 diff --git a/src/modules/locale/images/timezone_10.0.png b/src/modules/locale/images/timezone_10.0.png index fab3dadac909dfd9ecdbbc8a8c9ee90e04c808af..9304fa4ad9e1fab49575e0c98223e0e843c67551 100644 GIT binary patch literal 18305 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

I26Eaj2^v?D2FgzTr|?1RLII?GdICB>m2Mp8;| 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 TUP%P-nV6hGgq-5|$KLoCl*Tv~ diff --git a/src/modules/locale/images/timezone_11.0.png b/src/modules/locale/images/timezone_11.0.png index 71e62ee0c631050f6e6e9be7c148c109c8aeaf58..b5395bad1869cb8d8466da11e6c83e89f1bbed2b 100644 GIT binary patch literal 13590 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 literal 13472 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 diff --git a/src/modules/locale/images/timezone_12.0.png b/src/modules/locale/images/timezone_12.0.png index 9d4b458e77a0f2cc5c2a971c09ddc468ad0ccf76..04902676030220b0be436197b54b2115ea89127e 100644 GIT binary patch literal 8116 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

^IhAs89p<&oE zqZh4!W(+;;67oD#YcX=$QEmB1xEubrz%H1$@|zhSS&vt8%<`qfQDZC__>p?3&IG3^5jU^wA!O!m8i8;q!k{e zYRKN0A^j@&<djZ_?L~Qx&RCWx(d}stRl-}_nUhMY+K6fTo&gsRq zf9(&AUQVFxwwVX|)D2MEEU3o>8pfb=f6#S7`Rw+*-e$@K`x!lvU~H{@IBjy7*|?ou zj4~^CEGcoO?#*$FK6bwF@wczGa@G;RTG>qy2=-Ld+BrDw>uoa8>`Pa1H%2Qa$s50| z#pgEHP0YnhHLP1pmLN!2QqU9)<6JMQQ-j{AWw4&aPf7*u*jpz_@Cu6p zaw5_G`bFTqKx zJfjz~iv%)x#UW|xCdyI|O0Sw;hgwaAkx-U_UuRHVY<<|kE;g7xjLn#NCKhGfpj(0k@<^7*}YsZ3~7 z!)N2w7|wnlzefv2c_QqQLX=GR{H$oHMSX8Kmef8hYA-&D1IL16Q>y3h%UC>ww5G7> zsat&|xGfb`yhf~C(out1oe)>4iV?}YI%4;MQgkXWB+0p={|J?jyFvcH`peXPl?aFrVL$n z-ro$u6nEBV)mFA#E@{QkzFev25bo^nvAD4=M z=!V7n9s6r=o|MZsm=$yK7V*z$b$JKJ<_|lDYTJw*CX~B2-8;opDBQZ-ab@_8{cz6i z9)B|sjt`d(-4oR4an&=K;r%AJvHS$F=CL`Ks@QqKfu~c^QKH=X&Il{UTWx7fZ|4d*9XZGg z7)49E-%-zPT-kcw)_k7rqDG3rV!p55eAGFS4_t ziXK;e3}EYf<%nnHpBsYNolNflmB!TN=Fvc*p0v?KCBd~UsuW!CyNlsbo1-euhUZ1& z%b}n9$!~RN_8|e)GaurB{g+fE5vW&z6F3G>n~xRh9~;D@3a3R>V+4_(?IqjH>JR*M zyv%HaoIgx&?Ba(AzMSWtD1>>jvaEoL#Ibtn0y<%E^w#g3cN#nYp${d#3gK4*Jdj>|`}T8Hs3apt_pj8t-CAfF_G3=N`#lumv6rAu|r}(1=_WidCD?3sX-^!sK;E?Ok z+FJF)knWO9v(|%xhi&8RmvtzGz*6mAs*$Td|6!X%@|6gRN@i4)m^uB)99f0mN)R}K zve8$=pYC0;!f!Z;2LYk0@}8Q|awZT(awE=6o8S}f31?+AtMOMOxL1>ti<;^&TW()g pErBijsR>HwKc(dV?&HgE{LH%p5?aME9>7IF7c6bgmBHNp{U0|OhSdN7 literal 7704 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 diff --git a/src/modules/locale/images/timezone_2.0.png b/src/modules/locale/images/timezone_2.0.png index fa0bc4818f6f83bc88a2b3970a7df07168ec1c1f..1bae9510ee8a4f34528311f7ff7172165b7a0891 100644 GIT binary patch literal 18803 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 L`njxgN@xNAlYeAX literal 21508 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 Ib4q9e00j&<-v9sr From b9f802bbda998c0ba657231d17b6fa3fd95a2f2a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 23:25:17 +0200 Subject: [PATCH 036/105] CMake: shuffle includes together --- CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 020b83e80..30ba649ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,7 +162,13 @@ if(NOT CMAKE_VERSION VERSION_LESS "3.10.0") ) endif() +# CMake Modules +include( CMakePackageConfigHelpers ) include( CTest ) +include( FeatureSummary ) + +# Calamares Modules +include( CMakeColors ) ### C++ SETUP # @@ -248,9 +254,6 @@ if( CMAKE_COMPILER_IS_GNUCXX ) endif() endif() -include( FeatureSummary ) -include( CMakeColors ) - ### DEPENDENCIES # @@ -555,6 +558,8 @@ configure_file( CalamaresBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/Calam # Create the CalamaresConfig.cmake and CalamaresConfigVersion files file( RELATIVE_PATH CONF_REL_INCLUDE_DIR "${CMAKE_INSTALL_FULL_CMAKEDIR}" "${CMAKE_INSTALL_FULL_INCLUDEDIR}" ) + + configure_file( CalamaresConfig.cmake.in "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" @ONLY ) configure_file( CalamaresConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake" @ONLY ) configure_file( CalamaresUse.cmake.in "${PROJECT_BINARY_DIR}/CalamaresUse.cmake" @ONLY ) From 6507098d16f2d5a7623421643242ab578ca65fc4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 23:38:31 +0200 Subject: [PATCH 037/105] CMake: use standard function for creating a version file --- CMakeLists.txt | 7 ++++++- CalamaresConfigVersion.cmake.in | 12 ------------ 2 files changed, 6 insertions(+), 13 deletions(-) delete mode 100644 CalamaresConfigVersion.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 30ba649ee..107dc0b23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -556,12 +556,17 @@ export( PACKAGE Calamares ) configure_file( CalamaresBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/CalamaresBuildTreeSettings.cmake" @ONLY ) # Create the CalamaresConfig.cmake and CalamaresConfigVersion files +write_basic_package_version_file( + ${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + file( RELATIVE_PATH CONF_REL_INCLUDE_DIR "${CMAKE_INSTALL_FULL_CMAKEDIR}" "${CMAKE_INSTALL_FULL_INCLUDEDIR}" ) configure_file( CalamaresConfig.cmake.in "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" @ONLY ) -configure_file( CalamaresConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake" @ONLY ) configure_file( CalamaresUse.cmake.in "${PROJECT_BINARY_DIR}/CalamaresUse.cmake" @ONLY ) # Install the cmake files diff --git a/CalamaresConfigVersion.cmake.in b/CalamaresConfigVersion.cmake.in deleted file mode 100644 index 05b87c8d3..000000000 --- a/CalamaresConfigVersion.cmake.in +++ /dev/null @@ -1,12 +0,0 @@ -set(PACKAGE_VERSION "@CALAMARES_VERSION@") - -# Check whether the requested PACKAGE_FIND_VERSION is compatible -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif() -endif() - From f59b6da7995340df3f8896da2c771db72c81bde3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Jun 2020 23:58:58 +0200 Subject: [PATCH 038/105] CMake: produce a standard modern-CMake config file - Use modern CMake commands to produce the config file - Drop the CalamaresUse.cmake file, include its functionality in the config file. --- CMakeLists.txt | 17 +++++++++-------- CalamaresConfig.cmake.in | 40 ++++++++++++++-------------------------- CalamaresUse.cmake.in | 29 ----------------------------- 3 files changed, 23 insertions(+), 63 deletions(-) delete mode 100644 CalamaresUse.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 107dc0b23..3cf52e198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -556,25 +556,26 @@ export( PACKAGE Calamares ) configure_file( CalamaresBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/CalamaresBuildTreeSettings.cmake" @ONLY ) # Create the CalamaresConfig.cmake and CalamaresConfigVersion files +configure_package_config_file( + "CalamaresConfig.cmake.in" + "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" + PATH_VARS + CMAKE_INSTALL_INCLUDEDIR + CMAKE_INSTALL_LIBDIR + CMAKE_INSTALL_DATADIR +) write_basic_package_version_file( ${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) -file( RELATIVE_PATH CONF_REL_INCLUDE_DIR "${CMAKE_INSTALL_FULL_CMAKEDIR}" "${CMAKE_INSTALL_FULL_INCLUDEDIR}" ) - - - -configure_file( CalamaresConfig.cmake.in "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" @ONLY ) -configure_file( CalamaresUse.cmake.in "${PROJECT_BINARY_DIR}/CalamaresUse.cmake" @ONLY ) - # Install the cmake files install( FILES "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" "${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake" - "${PROJECT_BINARY_DIR}/CalamaresUse.cmake" "CMakeModules/CalamaresAddBrandingSubdirectory.cmake" "CMakeModules/CalamaresAddLibrary.cmake" "CMakeModules/CalamaresAddModuleSubdirectory.cmake" diff --git a/CalamaresConfig.cmake.in b/CalamaresConfig.cmake.in index 6d32410c6..9814bf8c1 100644 --- a/CalamaresConfig.cmake.in +++ b/CalamaresConfig.cmake.in @@ -1,32 +1,20 @@ # Config file for the Calamares package # -# It defines the following variables -# CALAMARES_INCLUDE_DIRS - include directories for Calamares -# CALAMARES_LIBRARIES - libraries to link against -# CALAMARES_USE_FILE - name of a convenience include -# CALAMARES_APPLICATION_NAME - human-readable application name -# -# Typical use is: -# -# find_package(Calamares REQUIRED) -# include("${CALAMARES_USE_FILE}") -# +# For legacy use it defines the following variables: +# - Calamares_INCLUDE_DIRS - include directories for Calamares +# - Calamares_LIB_DIRS - library directories +# - Calamares_LIBRARIES - libraries to link against (e.g. -lcalamares) -# Compute paths -get_filename_component(CALAMARES_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -if(EXISTS "${CALAMARES_CMAKE_DIR}/CMakeCache.txt") - # In build tree - include("${CALAMARES_CMAKE_DIR}/CalamaresBuildTreeSettings.cmake") -else() - set(CALAMARES_INCLUDE_DIRS "${CALAMARES_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@/libcalamares") -endif() +@PACKAGE_INIT@ -# Our library dependencies (contains definitions for IMPORTED targets) -include("${CALAMARES_CMAKE_DIR}/CalamaresLibraryDepends.cmake") +include(${CMAKE_CURRENT_LIST_DIR}/CalamaresConfigVersion.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/CalamaresTargets.cmake) -# These are IMPORTED targets created by CalamaresLibraryDepends.cmake -set(CALAMARES_LIBRARIES calamares) +set(Calamares_LIB_DIRS "@PACKAGE_CMAKE_INSTALL_LIBDIR@") +set(Calamares_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set(Calamares_LIBRARIES calamares) -# Convenience variables -set(CALAMARES_USE_FILE "${CALAMARES_CMAKE_DIR}/CalamaresUse.cmake") -set(CALAMARES_APPLICATION_NAME "Calamares") +include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddLibrary.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddModuleSubdirectory.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddPlugin.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddBrandingSubdirectory.cmake) diff --git a/CalamaresUse.cmake.in b/CalamaresUse.cmake.in deleted file mode 100644 index 00f3c968d..000000000 --- a/CalamaresUse.cmake.in +++ /dev/null @@ -1,29 +0,0 @@ -# A setup-cmake-things-for-Calamares module. -# -# This module handles looking for dependencies and including -# all of the Calamares macro modules, so that you can focus -# on just using the macros to build Calamares modules. -# Typical use looks like this: -# -# ``` -# find_package( Calamares REQUIRED ) -# include( "${CALAMARES_CMAKE_DIR}/CalamaresUse.cmake" ) -# ``` -# -# The first CMake command finds Calamares (which will contain -# this file), then adds the found location to the search path, -# and then includes this file. After that, you can use -# Calamares module and plugin macros. - -if( NOT CALAMARES_CMAKE_DIR ) - message( FATAL_ERROR "Use find_package(Calamares) first." ) -endif() -set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CALAMARES_CMAKE_DIR} ) - -find_package( Qt5 @QT_VERSION@ CONFIG REQUIRED Core Widgets LinguistTools ) - -include( CalamaresAddLibrary ) -include( CalamaresAddModuleSubdirectory ) -include( CalamaresAddPlugin ) -include( CalamaresAddBrandingSubdirectory ) - From dc16afac4a4e1cf3e2448cd291aaedc4aee0f352 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 00:31:13 +0200 Subject: [PATCH 039/105] CMake: massage IMPORTED targets and module path - Add the Calamares CMake-modules to the search path automatically - Export to CalamaresTargets.cmake and use namespace Calamares:: - Document imported targets - Find Qt, because the translations machinery will need macros from that - The installed lib links to IMPORTED libraries from KF5, so we need to find them (again) as well. --- CMakeLists.txt | 19 ++++---- CMakeModules/CalamaresAddLibrary.cmake | 2 +- CalamaresConfig.cmake.in | 60 +++++++++++++++++++++++--- src/libcalamares/CMakeLists.txt | 4 +- src/libcalamaresui/CMakeLists.txt | 2 +- 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cf52e198..8071f0870 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -532,7 +532,9 @@ configure_file( # Early configure these files as we need them later on set( CALAMARES_CMAKE_DIR "${CMAKE_SOURCE_DIR}/CMakeModules" ) -set( CALAMARES_LIBRARIES calamares ) +# This is used by CalamaresAddLibrary; once installed, this variable +# is set to the IMPORTED library for Calamares. +set( Calamares_LIBRARIES calamares ) add_subdirectory( src ) @@ -570,6 +572,13 @@ write_basic_package_version_file( VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) +export( PACKAGE Calamares ) +install( + EXPORT Calamares + DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" + FILE "CalamaresTargets.cmake" + NAMESPACE Calamares:: +) # Install the cmake files install( @@ -588,14 +597,6 @@ install( "${CMAKE_INSTALL_CMAKEDIR}" ) -# Install the export set for use with the install-tree -install( - EXPORT - CalamaresLibraryDepends - DESTINATION - "${CMAKE_INSTALL_CMAKEDIR}" -) - if( INSTALL_CONFIG ) install( FILES diff --git a/CMakeModules/CalamaresAddLibrary.cmake b/CMakeModules/CalamaresAddLibrary.cmake index 6155293d7..abfb3ac38 100644 --- a/CMakeModules/CalamaresAddLibrary.cmake +++ b/CMakeModules/CalamaresAddLibrary.cmake @@ -93,7 +93,7 @@ function(calamares_add_library) # add link targets target_link_libraries(${target} - LINK_PUBLIC ${CALAMARES_LIBRARIES} + LINK_PUBLIC ${Calamares_LIBRARIES} Qt5::Core Qt5::Gui Qt5::Widgets diff --git a/CalamaresConfig.cmake.in b/CalamaresConfig.cmake.in index 9814bf8c1..7fa67b310 100644 --- a/CalamaresConfig.cmake.in +++ b/CalamaresConfig.cmake.in @@ -1,20 +1,68 @@ # Config file for the Calamares package # +# The following IMPORTED targets are defined: +# - Calamares::calamares - the core library +# - Calamares::calamaresui - the UI (and QML) library +# # For legacy use it defines the following variables: # - Calamares_INCLUDE_DIRS - include directories for Calamares # - Calamares_LIB_DIRS - library directories -# - Calamares_LIBRARIES - libraries to link against (e.g. -lcalamares) +# - Calamares_LIBRARIES - libraries to link against @PACKAGE_INIT@ +### Versioning and IMPORTED targets +# +# include(${CMAKE_CURRENT_LIST_DIR}/CalamaresConfigVersion.cmake) include(${CMAKE_CURRENT_LIST_DIR}/CalamaresTargets.cmake) +### Dependencies +# +# The libraries can depend on a variety of Qt and KDE Frameworks +# components, so accumulate them and find (just once). +# +macro(accumulate_deps outvar target namespace) + string(LENGTH ${namespace} _nslen) + get_target_property(_libs ${target} INTERFACE_LINK_LIBRARIES) + foreach(_lib ${_libs}) + if (_lib MATCHES ^${namespace}) + string(SUBSTRING ${_lib} ${_nslen} -1 _component) + list(APPEND ${outvar} ${_component}) + endif() + endforeach() +endmacro() + +# Qt5 infrastructure for translations is required +set(qt5_required Core Widgets LinguistTools) +accumulate_deps(qt5_required Calamares::calamares Qt5::) +accumulate_deps(qt5_required Calamares::calamaresui Qt5::) +find_package(Qt5 CONFIG REQUIRED ${qt5_required}) + +set(kf5_required "") +accumulate_deps(kf5_required Calamares::calamares KF5::) +accumulate_deps(kf5_required Calamares::calamaresui KF5::) +if(kf5_required) + find_package(ECM ${ECM_VERSION} NO_MODULE) + if( ECM_FOUND ) + list(PREPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) + find_package(KF5 REQUIRED COMPONENTS ${kf5_required}) + endif() +endif() + +### Legacy support +# +# set(Calamares_LIB_DIRS "@PACKAGE_CMAKE_INSTALL_LIBDIR@") set(Calamares_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") -set(Calamares_LIBRARIES calamares) +set(Calamares_LIBRARIES Calamares::calamares) -include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddLibrary.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddModuleSubdirectory.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddPlugin.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/CalamaresAddBrandingSubdirectory.cmake) +### CMake support +# +# +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +include(CalamaresAddLibrary) +include(CalamaresAddModuleSubdirectory) +include(CalamaresAddPlugin) +include(CalamaresAddBrandingSubdirectory) diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index b43b89289..b4d369fe0 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -1,5 +1,5 @@ # === This file is part of Calamares - === -# +# # SPDX-FileCopyrightText: 2020 Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify @@ -177,7 +177,7 @@ target_link_libraries( calamares ) install( TARGETS calamares - EXPORT CalamaresLibraryDepends + EXPORT Calamares RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 32fec2cb1..b00f9682c 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -67,7 +67,7 @@ calamares_add_library( calamaresui LINK_LIBRARIES Qt5::Svg RESOURCES libcalamaresui.qrc - EXPORT CalamaresLibraryDepends + EXPORT Calamares VERSION ${CALAMARES_VERSION_SHORT} ) From e6fe19df20d1689ebb508f79e2f12dabd2dbf3c6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 01:25:36 +0200 Subject: [PATCH 040/105] CMake: remove unused link libraries - Nothing ever sets LIBRARY_QT5_MODULES (it would be a macro argument to calamares_add_library, if anything). --- CMakeModules/CalamaresAddLibrary.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeModules/CalamaresAddLibrary.cmake b/CMakeModules/CalamaresAddLibrary.cmake index abfb3ac38..88978e751 100644 --- a/CMakeModules/CalamaresAddLibrary.cmake +++ b/CMakeModules/CalamaresAddLibrary.cmake @@ -97,7 +97,6 @@ function(calamares_add_library) Qt5::Core Qt5::Gui Qt5::Widgets - ${LIBRARY_QT5_MODULES} ) if(LIBRARY_LINK_LIBRARIES) target_link_libraries(${target} LINK_PUBLIC ${LIBRARY_LINK_LIBRARIES}) From a62d96f555fc42a0232182cf8688ebcf23ac07c2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 01:34:18 +0200 Subject: [PATCH 041/105] CMake: tidy up installation of CMake infrastructure - export() only once - document variables a bit better - drop the LibraryDepends file --- CMakeLists.txt | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8071f0870..23359490f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -530,10 +530,9 @@ configure_file( IMMEDIATE @ONLY ) -# Early configure these files as we need them later on -set( CALAMARES_CMAKE_DIR "${CMAKE_SOURCE_DIR}/CMakeModules" ) -# This is used by CalamaresAddLibrary; once installed, this variable -# is set to the IMPORTED library for Calamares. +# This is used by CalamaresAddLibrary; once Calamares is installed, +# the CalamaresConfig.cmake module sets this variable to the IMPORTED +# libraries for Calamares. set( Calamares_LIBRARIES calamares ) add_subdirectory( src ) @@ -544,20 +543,17 @@ add_feature_info(Config ${INSTALL_CONFIG} "Install Calamares configuration") add_feature_info(KCrash ${WITH_KF5Crash} "Crash dumps via KCrash") add_feature_info(KDBusAddons ${WITH_KF5DBus} "Unique-application via DBus") -# Add all targets to the build-tree export set +### CMake infrastructure installation +# +# set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" ) set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" ) -export( TARGETS calamares - FILE "${PROJECT_BINARY_DIR}/CalamaresLibraryDepends.cmake" ) -# Export the package for use from the build-tree -# (this registers the build-tree with a global CMake-registry) export( PACKAGE Calamares ) - -# Create a CalamaresBuildTreeSettings.cmake file for the use from the build tree -configure_file( CalamaresBuildTreeSettings.cmake.in "${PROJECT_BINARY_DIR}/CalamaresBuildTreeSettings.cmake" @ONLY ) - -# Create the CalamaresConfig.cmake and CalamaresConfigVersion files +configure_file( + CalamaresBuildTreeSettings.cmake.in + "${PROJECT_BINARY_DIR}/CalamaresBuildTreeSettings.cmake" @ONLY +) configure_package_config_file( "CalamaresConfig.cmake.in" "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" @@ -572,7 +568,6 @@ write_basic_package_version_file( VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) -export( PACKAGE Calamares ) install( EXPORT Calamares DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" From 9039e15bdf0dd45dea42deb88dfd3b3d9d09c7f2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 01:42:11 +0200 Subject: [PATCH 042/105] CMake: tidy misc. installation bits - don't generate uninstall file twice - tighten up vertical space --- CMakeLists.txt | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23359490f..52af262d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -523,13 +523,6 @@ endif() # make predefined install dirs available everywhere include( GNUInstallDirs ) -# make uninstall support -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY -) - # This is used by CalamaresAddLibrary; once Calamares is installed, # the CalamaresConfig.cmake module sets this variable to the IMPORTED # libraries for Calamares. @@ -592,36 +585,31 @@ install( "${CMAKE_INSTALL_CMAKEDIR}" ) +### Miscellaneous installs +# +# if( INSTALL_CONFIG ) install( - FILES - settings.conf - DESTINATION - share/calamares + FILES settings.conf + DESTINATIONshare/calamares ) endif() if( INSTALL_POLKIT ) install( - FILES - com.github.calamares.calamares.policy - DESTINATION - "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}" + FILES com.github.calamares.calamares.policy + DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}" ) endif() install( - FILES - calamares.desktop - DESTINATION - ${CMAKE_INSTALL_DATADIR}/applications + FILES calamares.desktop + DESTINATION ${CMAKE_INSTALL_DATADIR}/applications ) install( - FILES - man/calamares.8 - DESTINATION - ${CMAKE_INSTALL_MANDIR}/man8/ + FILES man/calamares.8 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/ ) # uninstall target From 14ff681106c4115625c0831b17f05423ae963cce Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 02:01:59 +0200 Subject: [PATCH 043/105] CMake: give libcalamares IMPORTED includes - Set the interface-include path for libcalamares, so that linking to it (as one would from an external repo) pulls in all the includes. --- src/libcalamares/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index b4d369fe0..a2c60efe5 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -163,6 +163,7 @@ set_target_properties( calamares PROPERTIES VERSION ${CALAMARES_VERSION_SHORT} SOVERSION ${CALAMARES_VERSION_SHORT} + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libcalamares ) calamares_automoc( calamares ) From 3c770b79b30c229f8f831599a41715a40da4f27f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 02:10:21 +0200 Subject: [PATCH 044/105] CMake: install all the libcalamares subdir-headers --- src/libcalamares/CMakeLists.txt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index a2c60efe5..deb291ba9 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -193,13 +193,18 @@ install( CODE " # Install header files file( GLOB rootHeaders "*.h" ) -file( GLOB kdsingleapplicationguardHeaders "kdsingleapplicationguard/*.h" ) file( GLOB utilsHeaders "utils/*.h" ) -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h DESTINATION include/libcalamares ) -install( FILES ${rootHeaders} DESTINATION include/libcalamares ) -install( FILES ${kdsingleapplicationguardHeaders} DESTINATION include/libcalamares/kdsingleapplicationguard ) -install( FILES ${utilsHeaders} DESTINATION include/libcalamares/utils ) +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h + ${rootHeaders} + DESTINATION include/libcalamares +) +foreach( subdir geoip locale modulesystem network partition utils ) + file( GLOB subdir_headers "${subdir}/*.h" ) + install( FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir} ) +endforeach() ### TESTING # From 6c272bc8bef08de019930c64dfa97135a557dfd5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 02:27:57 +0200 Subject: [PATCH 045/105] [libcalamares] Link yamlcpp privately - link the library privately -- the public API uses QVariantMap - install FindYAMLCPP just in case - add yamlcpp explicitly in the few places that really need it (e.g. netinstall testing the parsing of netinstall.yaml) --- CMakeLists.txt | 1 + src/libcalamares/CMakeLists.txt | 2 +- src/libcalamaresui/CMakeLists.txt | 1 + src/modules/netinstall/CMakeLists.txt | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52af262d0..7aabe437e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -581,6 +581,7 @@ install( "CMakeModules/CalamaresAddTranslations.cmake" "CMakeModules/CalamaresAutomoc.cmake" "CMakeModules/CMakeColors.cmake" + "CMakeModules/FindYAMLCPP.cmake" DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" ) diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index deb291ba9..a7b4472d5 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -170,8 +170,8 @@ calamares_automoc( calamares ) target_link_libraries( calamares LINK_PRIVATE ${OPTIONAL_PRIVATE_LIBRARIES} - LINK_PUBLIC yamlcpp + LINK_PUBLIC Qt5::Core KF5::CoreAddons ${OPTIONAL_PUBLIC_LIBRARIES} diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index b00f9682c..9d7b7a85c 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -66,6 +66,7 @@ calamares_add_library( calamaresui EXPORT_MACRO UIDLLEXPORT_PRO LINK_LIBRARIES Qt5::Svg + yamlcpp RESOURCES libcalamaresui.qrc EXPORT Calamares VERSION ${CALAMARES_VERSION_SHORT} diff --git a/src/modules/netinstall/CMakeLists.txt b/src/modules/netinstall/CMakeLists.txt index 3e6ac3cb5..762e92985 100644 --- a/src/modules/netinstall/CMakeLists.txt +++ b/src/modules/netinstall/CMakeLists.txt @@ -26,5 +26,6 @@ calamares_add_test( PackageModel.cpp LIBRARIES Qt5::Gui + yamlcpp ) From 23c93904dfd2d8b4116ad438a459abb94cc31d0b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 11:51:53 +0200 Subject: [PATCH 046/105] CMake: put CMake-level ABI settings in CalamaresConfig - drop the BuildTreeSettings, it was not usefully used - make CalamaresConfig repeat the WITH_* settings, so that consumers can know the ABI offered --- CMakeLists.txt | 4 ---- CalamaresBuildTreeSettings.cmake.in | 4 ---- CalamaresConfig.cmake.in | 12 +++++++++++- src/libcalamares/CalamaresConfig.h.in | 11 +++++++++-- 4 files changed, 20 insertions(+), 11 deletions(-) delete mode 100644 CalamaresBuildTreeSettings.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aabe437e..09e5c6d1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -543,10 +543,6 @@ set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" ) export( PACKAGE Calamares ) -configure_file( - CalamaresBuildTreeSettings.cmake.in - "${PROJECT_BINARY_DIR}/CalamaresBuildTreeSettings.cmake" @ONLY -) configure_package_config_file( "CalamaresConfig.cmake.in" "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" diff --git a/CalamaresBuildTreeSettings.cmake.in b/CalamaresBuildTreeSettings.cmake.in deleted file mode 100644 index 507fc3d64..000000000 --- a/CalamaresBuildTreeSettings.cmake.in +++ /dev/null @@ -1,4 +0,0 @@ -set(CALAMARES_INCLUDE_DIRS - "@PROJECT_SOURCE_DIR@/src/libcalamares" - "@PROJECT_BINARY_DIR@/src/libcalamares" -) diff --git a/CalamaresConfig.cmake.in b/CalamaresConfig.cmake.in index 7fa67b310..4c62fb477 100644 --- a/CalamaresConfig.cmake.in +++ b/CalamaresConfig.cmake.in @@ -62,7 +62,17 @@ set(Calamares_LIBRARIES Calamares::calamares) # list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +include(CalamaresAddBrandingSubdirectory) include(CalamaresAddLibrary) include(CalamaresAddModuleSubdirectory) include(CalamaresAddPlugin) -include(CalamaresAddBrandingSubdirectory) + +# These are feature-settings that affect consumers of Calamares +# libraries as well; without Python-support in the libs, for instance, +# there's no point in having a Python plugin. +# +# This list should match the one in libcalamares/CalamaresConfig.h, +# which is the C++-language side of the same configuration. +set(Calamares_WITH_PYTHON @WITH_PYTHON@) +set(Calamares_WITH_PYTHONQT @WITH_PYTHONQT@) +set(Calamares_WITH_QML @WITH_QML@) diff --git a/src/libcalamares/CalamaresConfig.h.in b/src/libcalamares/CalamaresConfig.h.in index 98efa8c26..c081b158f 100644 --- a/src/libcalamares/CalamaresConfig.h.in +++ b/src/libcalamares/CalamaresConfig.h.in @@ -1,5 +1,5 @@ /* === This file is part of Calamares - === - * + * * SPDX-FileCopyrightText: 2020 Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify @@ -29,7 +29,14 @@ #define CMAKE_INSTALL_FULL_DATADIR "${CMAKE_INSTALL_FULL_DATADIR}/calamares" #define CMAKE_INSTALL_FULL_SYSCONFDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}" -//cmakedefines for CMake variables (e.g. for optdepends) go here +/* + * These are feature-settings that affect consumers of Calamares + * libraries as well; without Python-support in the libs, for instance, + * there's no point in having a Python plugin. + * + * This list should match the one in CalamaresConfig.cmake + * which is the CMake-time side of the same configuration. + */ #cmakedefine WITH_PYTHON #cmakedefine WITH_PYTHONQT #cmakedefine WITH_QML From dc0ed24f1a05cac6b9fc47ddfeb2531497673c89 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 16:43:34 +0200 Subject: [PATCH 047/105] [libcalamaresui] Install libcalamaresui headers - All the headers go to relevant subdirs, but we don't keep libcalamares and libcalamaresui apart. - While here, remove unused variable from libcalamares CMake --- src/libcalamares/CMakeLists.txt | 7 +++++-- src/libcalamaresui/CMakeLists.txt | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index a7b4472d5..0516b5613 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -177,6 +177,9 @@ target_link_libraries( calamares ${OPTIONAL_PUBLIC_LIBRARIES} ) +### Installation +# +# install( TARGETS calamares EXPORT Calamares RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -193,19 +196,19 @@ install( CODE " # Install header files file( GLOB rootHeaders "*.h" ) -file( GLOB utilsHeaders "utils/*.h" ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h ${rootHeaders} DESTINATION include/libcalamares ) +# Install each subdir-worth of header files foreach( subdir geoip locale modulesystem network partition utils ) file( GLOB subdir_headers "${subdir}/*.h" ) install( FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir} ) endforeach() + ### TESTING # # diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 9d7b7a85c..773fdf617 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -83,3 +83,25 @@ endif() if( WITH_QML ) target_link_libraries( calamaresui PUBLIC Qt5::QuickWidgets ) endif() + + +### Installation +# +# +# The library is already installed through calamares_add_library(), +# so we only need to do headers. Unlike the Calamares source tree, +# where libcalamares and libcalamaresui live in different branches, +# we're going to glom it all together in the installed headers location. + +install( + FILES + Branding.h + ViewManager.h + DESTINATION include/libcalamares +) + +# Install each subdir-worth of header files +foreach( subdir modulesystem utils viewpages widgets ) + file( GLOB subdir_headers "${subdir}/*.h" ) + install( FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir} ) +endforeach() From 3ae519b8ed577fdd7025ed7f6719ad0a173b3323 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 10 Jun 2020 16:58:17 +0200 Subject: [PATCH 048/105] Documentation: uncomment oem-setup - Calamares complains if this isn't set, so the example should probably be 'safe' from that complaint. With 3.3 plans including 'fatal error instead of warning' this should be fixed on-time. --- settings.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.conf b/settings.conf index 982f4ebbe..8bff02373 100644 --- a/settings.conf +++ b/settings.conf @@ -166,7 +166,7 @@ dont-chroot: false # If this is set to true, Calamares refers to itself as a "setup program" # rather than an "installer". Defaults to the value of dont-chroot, but # Calamares will complain if this is not explicitly set. -# oem-setup: true +oem-setup: false # If this is set to true, the "Cancel" button will be disabled entirely. # The button is also hidden from view. From f034b55da23e4cdc4fc026a0ec3c93f2a2ba6955 Mon Sep 17 00:00:00 2001 From: Pablo Ovelleiro Corral Date: Thu, 11 Jun 2020 11:45:50 +0200 Subject: [PATCH 049/105] [packages] add xbps package manager --- src/modules/packages/main.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py index 8f58cd6fb..3e29d72e1 100644 --- a/src/modules/packages/main.py +++ b/src/modules/packages/main.py @@ -274,6 +274,20 @@ class PMApt(PackageManager): # Doesn't need to update the system explicitly pass +class PMXbps(PackageManager): + backend = "xbps" + + def install(self, pkgs, from_local=False): + check_target_env_call(["xbps-install", "-Sy"] + pkgs) + + def remove(self, pkgs): + check_target_env_call(["xbps-remove", "-Ry", "--noconfirm"] + pkgs) + + def update_db(self): + check_target_env_call(["xbps-install", "-S"]) + + def update_system(self): + check_target_env_call(["xbps", "-Suy"]) class PMPacman(PackageManager): backend = "pacman" From 2ad44f6805a97679a86f01815c5f4fb6ef14f286 Mon Sep 17 00:00:00 2001 From: Pablo Ovelleiro Corral Date: Thu, 11 Jun 2020 11:57:23 +0200 Subject: [PATCH 050/105] add tags file to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2f36a5de6..da0f082a6 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ CMakeLists.txt.user # Kate *.kate-swp +tags From 4c65b8cc637d87e00e740b0d7a99ffd5b016b337 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 11 Jun 2020 12:26:32 +0200 Subject: [PATCH 051/105] CI: remove outdated comment-crud --- ci/txpull.sh | 21 +++++++-------------- ci/txpush.sh | 19 +++++++------------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/ci/txpull.sh b/ci/txpull.sh index 734a689b5..619963687 100755 --- a/ci/txpull.sh +++ b/ci/txpull.sh @@ -23,20 +23,15 @@ # ### END USAGE -### INITIAL SETUP +### SANITY CHECKING # -# This stuff needs to be done once; in a real CI environment where it -# runs regularly in a container, the setup needs to be done when -# creating the container. +# The script needs a .tx/config to talk to the Transifex server; +# it also checks that it is run from the top-level of a Calamares +# checkout. In order to use the system overall, you'll also need: +# - ~/.gitconfig (For the git commits this does) +# - ~/.transifexrc (Password token for Transifex) +# - ~/.ssh (For git commits) # -# -# cp ~/jenkins-master/.transifexrc ~ # Transifex user settings -# cp ~/jenkins-master/.gitconfig ~ # Git config, user settings -# cp -R ~/jenkins-master/.ssh ~ # SSH, presumably for github -# -# cd "$WORKSPACE" -# git config --global http.sslVerify false - test -f "CMakeLists.txt" || { echo "! Not at Calamares top-level" ; exit 1 ; } test -f ".tx/config" || { echo "! Not at Calamares top-level" ; exit 1 ; } test -f "calamares.desktop" || { echo "! Not at Calamares top-level" ; exit 1 ; } @@ -145,5 +140,3 @@ for POFILE in $(find lang -name "python.po") ; do done git add --verbose lang/python* git commit "$AUTHOR" --message="i18n: [python] $BOILERPLATE" | true - -# git push --set-upstream origin master diff --git a/ci/txpush.sh b/ci/txpush.sh index 3195f42b4..dc8c8c413 100755 --- a/ci/txpush.sh +++ b/ci/txpush.sh @@ -29,20 +29,15 @@ # ### END USAGE -### INITIAL SETUP +### SANITY CHECKING # -# This stuff needs to be done once; in a real CI environment where it -# runs regularly in a container, the setup needs to be done when -# creating the container. +# The script needs a .tx/config to talk to the Transifex server; +# it also checks that it is run from the top-level of a Calamares +# checkout. In order to use the system overall, you'll also need: +# - ~/.gitconfig (For the git commits this does) +# - ~/.transifexrc (Password token for Transifex) +# - ~/.ssh (For git commits) # -# -# cp ~/jenkins-master/.transifexrc ~ # Transifex user settings -# cp ~/jenkins-master/.gitconfig ~ # Git config, user settings -# cp -R ~/jenkins-master/.ssh ~ # SSH, presumably for github -# -# cd "$WORKSPACE" -# git config --global http.sslVerify false - test -f "CMakeLists.txt" || { echo "! Not at Calamares top-level" ; exit 1 ; } test -f ".tx/config" || { echo "! Not at Calamares top-level" ; exit 1 ; } test -f "calamares.desktop" || { echo "! Not at Calamares top-level" ; exit 1 ; } From ac8de23c6e54d7b76fdedfe2f9fd273026d0a58b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 11 Jun 2020 12:42:51 +0200 Subject: [PATCH 052/105] Changes: mention recent features and contributors --- CHANGES | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 64102fae8..b1b74f4ee 100644 --- a/CHANGES +++ b/CHANGES @@ -6,14 +6,18 @@ website will have to do for older versions. # 3.2.26 (unreleased) # This release contains contributions from (alphabetically by first name): - - No external contributors yet + - Pablo Ovelleiro Corral ## Core ## - - No core changes yet + - External modules can now be built again, outside of the Calamares + source and build-tree. ## Modules ## - - No module changes yet - + - *locale* put some more places into the correct timezone **visually**; + for instance Norfolk Island gave up UTC+11.5 in 2015 and is now + UTC+11, but Calamares still showed it in a zone separate from UTC+11. + - *packages* gained support for the Void Linux package manager, + *xbps*. (thanks Pablo) # 3.2.25 (2020-06-06) # From 73f8c627bd20ffb2012600f1c5098589f4e602af Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 12 Jun 2020 11:35:23 +0200 Subject: [PATCH 053/105] CMake: support out-of-tree builds - The variables that are set for out-of-tree builds are prefixed with to avoid name clashes; make the module-infrastructure respect those instead of the in-tree variable names. - .. and then duplicate the in-tree variables to the out-of-tree variables, so we only need one set of module instructions. --- CMakeLists.txt | 7 +++++++ CMakeModules/CalamaresAddModuleSubdirectory.cmake | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09e5c6d1d..2a209e2d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,6 +359,13 @@ if( NOT PYTHONLIBS_FOUND OR NOT PYTHONQT_FOUND ) set( WITH_PYTHONQT OFF ) endif() +# Now we know the state of the ABI-options, copy them into "Calamares_" +# prefixed variables, to match how the variables would-be-named +# when building out-of-tree. +set(Calamares_WITH_PYTHON ${WITH_PYTHON}) +set(Calamares_WITH_PYTHONQT ${WITH_PYTHONQT}) +set(Calamares_WITH_QML ${WITH_QML}) + ### Transifex Translation status # # Construct language lists for use. If there are p_tx* variables, diff --git a/CMakeModules/CalamaresAddModuleSubdirectory.cmake b/CMakeModules/CalamaresAddModuleSubdirectory.cmake index fe4f34f94..02c1a577f 100644 --- a/CMakeModules/CalamaresAddModuleSubdirectory.cmake +++ b/CMakeModules/CalamaresAddModuleSubdirectory.cmake @@ -70,11 +70,11 @@ function( calamares_add_module_subdirectory ) # _mod_testing boolean if the module should be added to the loadmodule tests file(STRINGS "${_mod_dir}/module.desc" MODULE_INTERFACE REGEX "^interface") if ( MODULE_INTERFACE MATCHES "pythonqt" ) - set( _mod_enabled ${WITH_PYTHONQT} ) + set( _mod_enabled ${Calamares_WITH_PYTHONQT} ) set( _mod_reason "No PythonQt support" ) set( _mod_testing OFF ) elseif ( MODULE_INTERFACE MATCHES "python" ) - set( _mod_enabled ${WITH_PYTHON} ) + set( _mod_enabled ${Calamares_WITH_PYTHON} ) set( _mod_reason "No Python support" ) set( _mod_testing ON ) # Will check syntax and imports, at least elseif ( MODULE_INTERFACE MATCHES "qtplugin" ) From f218e2e9a617f176d4ed69904a81ab97c9597122 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 12 Jun 2020 12:05:35 +0200 Subject: [PATCH 054/105] CMake: handle Python modules built from subdirectory a/b --- CMakeModules/CalamaresAddModuleSubdirectory.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CMakeModules/CalamaresAddModuleSubdirectory.cmake b/CMakeModules/CalamaresAddModuleSubdirectory.cmake index 02c1a577f..86f0b8f4c 100644 --- a/CMakeModules/CalamaresAddModuleSubdirectory.cmake +++ b/CMakeModules/CalamaresAddModuleSubdirectory.cmake @@ -61,7 +61,17 @@ function( calamares_add_module_subdirectory ) # ...otherwise, we look for a module.desc. elseif( EXISTS "${_mod_dir}/module.desc" ) set( MODULES_DIR ${CMAKE_INSTALL_LIBDIR}/calamares/modules ) - set( MODULE_DESTINATION ${MODULES_DIR}/${SUBDIRECTORY} ) + # The module subdirectory may be given as a/b/c, but the module + # needs to be installed as "c", so we split off any intermediate + # directories. + get_filename_component(_dirname "${SUBDIRECTORY}" DIRECTORY) + if( _dirname ) + # Remove the dirname and any leftover leading /s + string( REGEX REPLACE "^${_dirname}/*" "" _modulename "${SUBDIRECTORY}" ) + set( MODULE_DESTINATION ${MODULES_DIR}/${_modulename} ) + else() + set( MODULE_DESTINATION ${MODULES_DIR}/${SUBDIRECTORY} ) + endif() # Read module.desc, check that the interface type is supported. # From 70f10798737e9b4c36267b95726dc8fb12cec1ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 12 Jun 2020 12:56:13 +0200 Subject: [PATCH 055/105] i18n: expand the translation-load-compare tool a little, more docs --- lang/txload.cpp | 76 +++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/lang/txload.cpp b/lang/txload.cpp index 36e0f71a2..68a157b81 100644 --- a/lang/txload.cpp +++ b/lang/txload.cpp @@ -1,6 +1,4 @@ /* === This file is part of Calamares - === - * - * Copyright 2018, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,23 +12,33 @@ * * You should have received a copy of the GNU General Public License * along with Calamares. If not, see . + * + * SPDX-FileCopyrightText: 2018 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * License-Filename: LICENSE */ /* * Tool to find differences between translations (can be used to help * merging them into one). See usage string, below, for details. + * + * The tool can be used when there are multiple translation files + * for a single language (e.g. Spanish) which need to be reconciled. + * Then running `txload file0.ts file1.ts ...` will produce a + * human-readable overview of what is translated and where the + * differences in translation are. */ #include #include #include -#include +// #include #include -static const char usage[] = "Usage: txload [ ...]\n" +static const char usage[] = "Usage: txload [ ...]\n" "\n" - "Reads a .ts source file and zero or more .ts \n" + "Reads a .ts source file and zero or more .ts \n" "files, and does a comparison between the translations. Source (English)\n" "strings that are untranslated are flagged in each of the translation\n" "files, while differences in the translations are themselves also shown.\n" @@ -95,34 +103,34 @@ QDomElement find_message(QDomElement& context, const QString& source) return QDomElement(); } -bool merge_into(QDomElement& master, QDomElement& sub) +bool merge_into(QDomElement& origin, QDomElement& alternate) { - QDomNode n = sub.firstChild(); + QDomNode n = alternate.firstChild(); while (!n.isNull()) { if (n.isElement()) { - QDomElement e = n.toElement(); - if ( e.tagName() == "message" ) + QDomElement alternateMessage = n.toElement(); + if ( alternateMessage.tagName() == "message" ) { - QString source = e.firstChildElement( "source" ).text(); - QString translation = e.firstChildElement( "translation" ).text(); - QDomElement masterTranslation = find_message( master, source ); - if ( masterTranslation.isNull() ) + QString alternateSourceText = alternateMessage.firstChildElement( "source" ).text(); + QString alternateTranslationText = alternateMessage.firstChildElement( "translation" ).text(); + QDomElement originMessage = find_message( origin, alternateSourceText ); + if ( originMessage.isNull() ) { - qDebug() << "No master translation for" << source; + qDebug() << "No origin translation for" << alternateSourceText; return false; } - QString msource = masterTranslation.firstChildElement( "source" ).text(); - QString mtranslation = masterTranslation.firstChildElement( "translation" ).text(); + QString originSourceText = originMessage.firstChildElement( "source" ).text(); + QString originTranslationText = originMessage.firstChildElement( "translation" ).text(); - if ( source != msource ) + if ( alternateSourceText != originSourceText ) { - qDebug() << "Mismatch for messages\n" << source << '\n' << msource; + qDebug() << "Mismatch for messages\n" << alternateSourceText << '\n' << originSourceText; return false; } - if ( !translation.isEmpty() && ( translation != mtranslation ) ) + if ( !alternateTranslationText.isEmpty() && ( alternateTranslationText != originTranslationText ) ) { - qDebug() << "\n\n\nSource:" << source << "\nTL1:" << mtranslation << "\nTL2:" << translation; + qDebug() << "\n\n\nSource:" << alternateSourceText << "\nTL1:" << originTranslationText << "\nTL2:" << alternateTranslationText; } } } @@ -134,32 +142,32 @@ bool merge_into(QDomElement& master, QDomElement& sub) -bool merge_into(QDomDocument& master, QDomElement& context) +bool merge_into(QDomDocument& originDocument, QDomElement& context) { QDomElement name = context.firstChildElement( "name" ); if ( name.isNull() ) return false; QString contextname = name.text(); - QDomElement masterContext = find_context( master, contextname ); - if ( masterContext.isNull() ) + QDomElement originContext = find_context( originDocument, contextname ); + if ( originContext.isNull() ) { - qDebug() << "Master document has no context" << contextname; + qDebug() << "Origin document has no context" << contextname; return false; } - return merge_into( masterContext, context ); + return merge_into( originContext, context ); } -bool merge_into(QDomDocument& master, QDomDocument& sub) +bool merge_into(QDomDocument& originDocument, QDomDocument& alternateDocument) { - QDomElement top = sub.documentElement(); + QDomElement top = alternateDocument.documentElement(); QDomNode n = top.firstChild(); while (!n.isNull()) { if (n.isElement()) { QDomElement e = n.toElement(); if ( e.tagName() == "context" ) - if ( !merge_into( master, e ) ) + if ( !merge_into( originDocument, e ) ) return false; } n = n.nextSibling(); @@ -178,16 +186,16 @@ int main(int argc, char** argv) return 1; } - QDomDocument doc("master"); - if ( !load_file(argv[1], doc) ) + QDomDocument originDocument("origin"); + if ( !load_file(argv[1], originDocument) ) return 1; for (int i = 2; i < argc; ++i) { - QDomDocument subdoc("sub"); - if ( !load_file(argv[i], subdoc) ) + QDomDocument alternateDocument("alternate"); + if ( !load_file(argv[i], alternateDocument) ) return 1; - if ( !merge_into( doc, subdoc ) ) + if ( !merge_into( originDocument, alternateDocument ) ) return 1; } @@ -200,7 +208,7 @@ int main(int argc, char** argv) return 1; } - outfile.write( doc.toString(4).toUtf8() ); + outfile.write( originDocument.toString(4).toUtf8() ); outfile.close(); return 0; From a9ec5921855f079c549d26d8273708390c06b630 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 12 Jun 2020 13:12:50 +0200 Subject: [PATCH 056/105] CI: change of default branch --- README.md | 15 ++++++++------- ci/travis-coverity.sh | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7b12532e5..2544ebb69 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ --------- [![GitHub release](https://img.shields.io/github/release/calamares/calamares.svg)](https://github.com/calamares/calamares/releases) -[![Travis Build Status](https://travis-ci.org/calamares/calamares.svg?branch=master)](https://travis-ci.org/calamares/calamares) +[![Travis Build Status](https://travis-ci.org/calamares/calamares.svg?branch=calamares)](https://travis-ci.org/calamares/calamares) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5389/badge.svg)](https://scan.coverity.com/projects/5389) -[![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/master/LICENSE) +[![GitHub license](https://img.shields.io/github/license/calamares/calamares.svg)](https://github.com/calamares/calamares/blob/calamares/LICENSE) | [Report a Bug](https://github.com/calamares/calamares/issues/new) | [Translate](https://www.transifex.com/projects/p/calamares/) | [Contribute](https://github.com/calamares/calamares/wiki/Develop-Guide) | Freenode (IRC): #calamares | [Wiki](https://github.com/calamares/calamares/wiki) | |:-----------------------------------------:|:----------------------:|:-----------------------:|:--------------------------:|:--------------------------:| @@ -23,11 +23,12 @@ Main: * KDE Frameworks KCoreAddons (>= 5.58 recommended) * PythonQt (optional, deprecated) -Modules: -* Individual modules may have their own requirements; - these are listed in CMake output. Particular requirements (not complete): -* *fsresizer* KPMCore >= 3.3 -* *partition* KPMCore >= 3.3 +Individual modules may have their own requirements; +these are listed in CMake output. +Particular requirements (not complete): + +* *fsresizer* KPMCore >= 3.3 (>= 4.1 recommended) +* *partition* KPMCore >= 3.3 (>= 4.1 recommended) * *users* LibPWQuality (optional) ### Building diff --git a/ci/travis-coverity.sh b/ci/travis-coverity.sh index 88b6a2ab5..78535df65 100755 --- a/ci/travis-coverity.sh +++ b/ci/travis-coverity.sh @@ -29,6 +29,6 @@ tar caf calamares-ci.tar.xz cov-int curl -k --form token=$COVERITY_SCAN_TOKEN \ --form email=groot@kde.org \ --form file=@calamares-ci.tar.xz \ - --form version="master-`date -u +%Y%m%d`" \ - --form description="master on `date -u`" \ + --form version="calamares-`date -u +%Y%m%d`" \ + --form description="calamares on `date -u`" \ https://scan.coverity.com/builds?project=calamares%2Fcalamares From 8ba9d394ec68df4e52e31540c18076d72031811f Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Fri, 12 Jun 2020 14:36:48 +0200 Subject: [PATCH 057/105] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_bn.ts | 3827 ++++++++++++++++++++++++++++++++++++++ lang/calamares_es.ts | 72 +- lang/calamares_eu.ts | 20 +- lang/calamares_it_IT.ts | 52 +- lang/calamares_lv.ts | 3829 +++++++++++++++++++++++++++++++++++++++ lang/calamares_sq.ts | 10 +- lang/calamares_sv.ts | 184 +- 7 files changed, 7851 insertions(+), 143 deletions(-) create mode 100644 lang/calamares_bn.ts create mode 100644 lang/calamares_lv.ts diff --git a/lang/calamares_bn.ts b/lang/calamares_bn.ts new file mode 100644 index 000000000..a74690da3 --- /dev/null +++ b/lang/calamares_bn.ts @@ -0,0 +1,3827 @@ + + + + + BootInfoWidget + + + The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode. + + + + + This system was started with an <strong>EFI</strong> boot environment.<br><br>To configure startup from an EFI environment, this installer must deploy a boot loader application, like <strong>GRUB</strong> or <strong>systemd-boot</strong> on an <strong>EFI System Partition</strong>. This is automatic, unless you choose manual partitioning, in which case you must choose it or create it on your own. + + + + + This system was started with a <strong>BIOS</strong> boot environment.<br><br>To configure startup from a BIOS environment, this installer must install a boot loader, like <strong>GRUB</strong>, either at the beginning of a partition or on the <strong>Master Boot Record</strong> near the beginning of the partition table (preferred). This is automatic, unless you choose manual partitioning, in which case you must set it up on your own. + + + + + BootLoaderModel + + + Master Boot Record of %1 + 1% মাস্টার বুট রেকর্ড + + + + Boot Partition + বুট পার্টিশন + + + + System Partition + সিস্টেম পার্টিশন + + + + Do not install a boot loader + + + + + %1 (%2) + + + + + Calamares::BlankViewStep + + + Blank Page + + + + + Calamares::DebugWindow + + + Form + + + + + GlobalStorage + + + + + JobQueue + + + + + Modules + + + + + Type: + + + + + + none + + + + + Interface: + + + + + Tools + + + + + Reload Stylesheet + + + + + Widget Tree + + + + + Debug information + + + + + Calamares::ExecutionViewStep + + + Set up + + + + + Install + + + + + Calamares::FailJob + + + Job failed (%1) + + + + + Programmed job failure was explicitly requested. + + + + + Calamares::JobThread + + + Done + সম্পন্ন + + + + Calamares::NamedJob + + + Example job (%1) + + + + + Calamares::ProcessJob + + + Run command '%1' in target system. + + + + + Run command '%1'. + + + + + Running command %1 %2 + + + + + Calamares::PythonJob + + + Running %1 operation. + + + + + Bad working directory path + খারাপ ওয়ার্কিং ডিরেক্টরি পাথ + + + + Working directory %1 for python job %2 is not readable. + ওয়ার্কিং ডিরেক্টরি 1% পাইথন কাজের জন্য % 2 পাঠযোগ্য নয়। + + + + Bad main script file + খারাপ প্রধান স্ক্রিপ্ট ফাইল + + + + Main script file %1 for python job %2 is not readable. + মূল স্ক্রিপ্ট ফাইল 1% পাইথন কাজের জন্য 2% পাঠযোগ্য নয়। + + + + Boost.Python error in job "%1". + বুস্ট.পাইথন কাজে 1% ত্রুটি + + + + Calamares::QmlViewStep + + + Loading ... + + + + + QML Step <i>%1</i>. + + + + + Loading failed. + + + + + Calamares::RequirementsChecker + + + Waiting for %n module(s). + + + + + + + + (%n second(s)) + + + + + + + + System-requirements checking is complete. + + + + + Calamares::ViewManager + + + Setup Failed + + + + + Installation Failed + ইনস্টলেশন ব্যর্থ হয়েছে + + + + Would you like to paste the install log to the web? + + + + + Error + ত্রুটি + + + + + &Yes + + + + + + &No + + + + + &Close + + + + + Install Log Paste URL + + + + + The upload was unsuccessful. No web-paste was done. + + + + + Calamares Initialization Failed + + + + + %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. + + + + + <br/>The following modules could not be loaded: + + + + + Continue with setup? + + + + + Continue with installation? + + + + + The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + &Set up now + + + + + &Install now + + + + + Go &back + + + + + &Set up + + + + + &Install + + + + + Setup is complete. Close the setup program. + + + + + The installation is complete. Close the installer. + + + + + Cancel setup without changing the system. + + + + + Cancel installation without changing the system. + + + + + &Next + এবং পরবর্তী + + + + &Back + এবং পেছনে + + + + &Done + + + + + &Cancel + + + + + Cancel setup? + + + + + Cancel installation? + + + + + Do you really want to cancel the current setup process? +The setup program will quit and all changes will be lost. + + + + + Do you really want to cancel the current install process? +The installer will quit and all changes will be lost. + + + + + CalamaresPython::Helper + + + Unknown exception type + অজানা ব্যতিক্রম প্রকার + + + + unparseable Python error + আনপারসেবল পাইথন ত্রুটি + + + + unparseable Python traceback + আনপারসেবল পাইথন ট্রেসব্যাক + + + + Unfetchable Python error. + অপরিবর্তনীয় পাইথন ত্রুটি। + + + + CalamaresUtils + + + Install log posted to: +%1 + + + + + CalamaresWindow + + + Show debug information + + + + + &Back + এবং পেছনে + + + + &Next + এবং পরবর্তী + + + + &Cancel + + + + + %1 Setup Program + + + + + %1 Installer + 1% ইনস্টল + + + + CheckerContainer + + + Gathering system information... + + + + + ChoicePage + + + Form + + + + + Select storage de&vice: + + + + + + + + Current: + + + + + After: + + + + + <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. Having a GPT partition table and <strong>fat32 512Mb /boot partition is a must for UEFI installs</strong>, either use an existing without formatting or create one. + + + + + Reuse %1 as home partition for %2. + + + + + <strong>Select a partition to shrink, then drag the bottom bar to resize</strong> + + + + + %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. + + + + + Boot loader location: + + + + + <strong>Select a partition to install on</strong> + + + + + An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + + + + <strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device. + + + + + + + + <strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1. + + + + + + + + <strong>Replace a partition</strong><br/>Replaces a partition with %1. + + + + + This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + No Swap + + + + + Reuse Swap + + + + + Swap (no Hibernate) + + + + + Swap (with Hibernate) + + + + + Swap to file + + + + + ClearMountsJob + + + Clear mounts for partitioning operations on %1 + + + + + Clearing mounts for partitioning operations on %1. + + + + + Cleared all mounts for %1 + + + + + ClearTempMountsJob + + + Clear all temporary mounts. + + + + + Clearing all temporary mounts. + + + + + Cannot get list of temporary mounts. + + + + + Cleared all temporary mounts. + + + + + CommandList + + + + Could not run command. + + + + + The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. + + + + + The command needs to know the user's name, but no username is defined. + + + + + Config + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + Network Installation. (Disabled: Incorrect configuration) + + + + + Network Installation. (Disabled: Received invalid groups data) + + + + + Network Installation. (Disabled: internal error) + + + + + Network Installation. (Disabled: Unable to fetch package lists, check your network connection) + + + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + ContextualProcessJob + + + Contextual Processes Job + + + + + CreatePartitionDialog + + + Create a Partition + একটি পার্টিশন তৈরি করুন + + + + Si&ze: + + + + + MiB + + + + + Partition &Type: + পার্টিশন এবং প্রকার: + + + + &Primary + এবং প্রাথমিক + + + + E&xtended + সম্প্রসারিত + + + + Fi&le System: + + + + + LVM LV name + + + + + &Mount Point: + এবং মাউন্ট পয়েন্ট: + + + + Flags: + + + + + En&crypt + + + + + Logical + + + + + Primary + + + + + GPT + + + + + Mountpoint already in use. Please select another one. + + + + + CreatePartitionJob + + + Create new %2MiB partition on %4 (%3) with file system %1. + + + + + Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. + + + + + Creating new %1 partition on %2. + + + + + The installer failed to create partition on disk '%1'. + + + + + CreatePartitionTableDialog + + + Create Partition Table + + + + + Creating a new partition table will delete all existing data on the disk. + + + + + What kind of partition table do you want to create? + + + + + Master Boot Record (MBR) + + + + + GUID Partition Table (GPT) + + + + + CreatePartitionTableJob + + + Create new %1 partition table on %2. + + + + + Create new <strong>%1</strong> partition table on <strong>%2</strong> (%3). + + + + + Creating new %1 partition table on %2. + + + + + The installer failed to create a partition table on %1. + + + + + CreateUserJob + + + Create user %1 + + + + + Create user <strong>%1</strong>. + + + + + Creating user %1. + + + + + Sudoers dir is not writable. + + + + + Cannot create sudoers file for writing. + + + + + Cannot chmod sudoers file. + + + + + Cannot open groups file for reading. + + + + + CreateVolumeGroupDialog + + + Create Volume Group + + + + + CreateVolumeGroupJob + + + Create new volume group named %1. + + + + + Create new volume group named <strong>%1</strong>. + + + + + Creating new volume group named %1. + + + + + The installer failed to create a volume group named '%1'. + + + + + DeactivateVolumeGroupJob + + + + Deactivate volume group named %1. + + + + + Deactivate volume group named <strong>%1</strong>. + + + + + The installer failed to deactivate a volume group named %1. + + + + + DeletePartitionJob + + + Delete partition %1. + + + + + Delete partition <strong>%1</strong>. + + + + + Deleting partition %1. + + + + + The installer failed to delete partition %1. + + + + + DeviceInfoWidget + + + This device has a <strong>%1</strong> partition table. + + + + + This is a <strong>loop</strong> device.<br><br>It is a pseudo-device with no partition table that makes a file accessible as a block device. This kind of setup usually only contains a single filesystem. + + + + + This installer <strong>cannot detect a partition table</strong> on the selected storage device.<br><br>The device either has no partition table, or the partition table is corrupted or of an unknown type.<br>This installer can create a new partition table for you, either automatically, or through the manual partitioning page. + + + + + <br><br>This is the recommended partition table type for modern systems which start from an <strong>EFI</strong> boot environment. + + + + + <br><br>This partition table type is only advisable on older systems which start from a <strong>BIOS</strong> boot environment. GPT is recommended in most other cases.<br><br><strong>Warning:</strong> the MBR partition table is an obsolete MS-DOS era standard.<br>Only 4 <em>primary</em> partitions may be created, and of those 4, one can be an <em>extended</em> partition, which may in turn contain many <em>logical</em> partitions. + + + + + The type of <strong>partition table</strong> on the selected storage device.<br><br>The only way to change the partition table type is to erase and recreate the partition table from scratch, which destroys all data on the storage device.<br>This installer will keep the current partition table unless you explicitly choose otherwise.<br>If unsure, on modern systems GPT is preferred. + + + + + DeviceModel + + + %1 - %2 (%3) + device[name] - size[number] (device-node[name]) + + + + + %1 - (%2) + device[name] - (device-node[name]) + + + + + DracutLuksCfgJob + + + Write LUKS configuration for Dracut to %1 + + + + + Skip writing LUKS configuration for Dracut: "/" partition is not encrypted + + + + + Failed to open %1 + + + + + DummyCppJob + + + Dummy C++ Job + + + + + EditExistingPartitionDialog + + + Edit Existing Partition + + + + + Content: + + + + + &Keep + + + + + Format + + + + + Warning: Formatting the partition will erase all existing data. + + + + + &Mount Point: + এবং মাউন্ট পয়েন্ট: + + + + Si&ze: + + + + + MiB + + + + + Fi&le System: + + + + + Flags: + + + + + Mountpoint already in use. Please select another one. + + + + + EncryptWidget + + + Form + + + + + En&crypt system + + + + + Passphrase + + + + + Confirm passphrase + + + + + Please enter the same passphrase in both boxes. + + + + + FillGlobalStorageJob + + + Set partition information + + + + + Install %1 on <strong>new</strong> %2 system partition. + + + + + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>. + + + + + Install %2 on %3 system partition <strong>%1</strong>. + + + + + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>. + + + + + Install boot loader on <strong>%1</strong>. + + + + + Setting up mount points. + + + + + FinishedPage + + + Form + + + + + &Restart now + + + + + <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> + + + + + <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> + + + + + <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. + + + + + <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. + + + + + FinishedViewStep + + + Finish + + + + + Setup Complete + + + + + Installation Complete + + + + + The setup of %1 is complete. + + + + + The installation of %1 is complete. + + + + + FormatPartitionJob + + + Format partition %1 (file system: %2, size: %3 MiB) on %4. + + + + + Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. + + + + + Formatting partition %1 with file system %2. + + + + + The installer failed to format partition %1 on disk '%2'. + + + + + GeneralRequirements + + + has at least %1 GiB available drive space + + + + + There is not enough drive space. At least %1 GiB is required. + + + + + has at least %1 GiB working memory + + + + + The system does not have enough working memory. At least %1 GiB is required. + + + + + is plugged in to a power source + + + + + The system is not plugged in to a power source. + + + + + is connected to the Internet + + + + + The system is not connected to the Internet. + + + + + is running the installer as an administrator (root) + + + + + The setup program is not running with administrator rights. + + + + + The installer is not running with administrator rights. + + + + + has a screen large enough to show the whole installer + + + + + The screen is too small to display the setup program. + + + + + The screen is too small to display the installer. + + + + + HostInfoJob + + + Collecting information about your machine. + + + + + IDJob + + + + + + OEM Batch Identifier + + + + + Could not create directories <code>%1</code>. + + + + + Could not open file <code>%1</code>. + + + + + Could not write to file <code>%1</code>. + + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + + + InteractiveTerminalPage + + + Konsole not installed + + + + + Please install KDE Konsole and try again! + + + + + Executing script: &nbsp;<code>%1</code> + + + + + InteractiveTerminalViewStep + + + Script + + + + + KeyboardPage + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + KeyboardQmlViewStep + + + Keyboard + + + + + KeyboardViewStep + + + Keyboard + + + + + LCLocaleDialog + + + System locale setting + + + + + The system locale setting affects the language and character set for some command line user interface elements.<br/>The current setting is <strong>%1</strong>. + + + + + &Cancel + + + + + &OK + + + + + LicensePage + + + Form + + + + + <h1>License Agreement</h1> + + + + + I accept the terms and conditions above. + + + + + Please review the End User License Agreements (EULAs). + + + + + This setup procedure will install proprietary software that is subject to licensing terms. + + + + + If you do not agree with the terms, the setup procedure cannot continue. + + + + + This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. + + + + + If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. + + + + + LicenseViewStep + + + License + + + + + LicenseWidget + + + URL: %1 + + + + + <strong>%1 driver</strong><br/>by %2 + %1 is an untranslatable product name, example: Creative Audigy driver + + + + + <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> + %1 is usually a vendor name, example: Nvidia graphics driver + + + + + <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 codec</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 package</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1</strong><br/><font color="Grey">by %2</font> + + + + + File: %1 + + + + + Hide license text + + + + + Show the license text + + + + + Open license agreement in browser. + + + + + LocalePage + + + Region: + + + + + Zone: + + + + + + &Change... + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + LocaleQmlViewStep + + + Location + + + + + LocaleViewStep + + + Location + + + + + LuksBootKeyFileJob + + + Configuring LUKS key file. + + + + + + No partitions are defined. + + + + + + + Encrypted rootfs setup error + + + + + Root partition %1 is LUKS but no passphrase has been set. + + + + + Could not create LUKS key file for root partition %1. + + + + + Could not configure LUKS key file on partition %1. + + + + + MachineIdJob + + + Generate machine-id. + + + + + Configuration Error + + + + + No root mount point is set for MachineId. + + + + + NetInstallViewStep + + + + Package selection + + + + + Office software + + + + + Office package + + + + + Browser software + + + + + Browser package + + + + + Web browser + + + + + Kernel + + + + + Services + + + + + Login + + + + + Desktop + + + + + Applications + + + + + Communication + + + + + Development + + + + + Office + + + + + Multimedia + + + + + Internet + + + + + Theming + + + + + Gaming + + + + + Utilities + + + + + NotesQmlViewStep + + + Notes + + + + + OEMPage + + + Ba&tch: + + + + + <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> + + + + + <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> + + + + + OEMViewStep + + + OEM Configuration + + + + + Set the OEM Batch Identifier to <code>%1</code>. + + + + + PWQ + + + Password is too short + + + + + Password is too long + + + + + Password is too weak + + + + + Memory allocation error when setting '%1' + + + + + Memory allocation error + + + + + The password is the same as the old one + + + + + The password is a palindrome + + + + + The password differs with case changes only + + + + + The password is too similar to the old one + + + + + The password contains the user name in some form + + + + + The password contains words from the real name of the user in some form + + + + + The password contains forbidden words in some form + + + + + The password contains less than %1 digits + + + + + The password contains too few digits + + + + + The password contains less than %1 uppercase letters + + + + + The password contains too few uppercase letters + + + + + The password contains less than %1 lowercase letters + + + + + The password contains too few lowercase letters + + + + + The password contains less than %1 non-alphanumeric characters + + + + + The password contains too few non-alphanumeric characters + + + + + The password is shorter than %1 characters + + + + + The password is too short + + + + + The password is just rotated old one + + + + + The password contains less than %1 character classes + + + + + The password does not contain enough character classes + + + + + The password contains more than %1 same characters consecutively + + + + + The password contains too many same characters consecutively + + + + + The password contains more than %1 characters of the same class consecutively + + + + + The password contains too many characters of the same class consecutively + + + + + The password contains monotonic sequence longer than %1 characters + + + + + The password contains too long of a monotonic character sequence + + + + + No password supplied + + + + + Cannot obtain random numbers from the RNG device + + + + + Password generation failed - required entropy too low for settings + + + + + The password fails the dictionary check - %1 + + + + + The password fails the dictionary check + + + + + Unknown setting - %1 + + + + + Unknown setting + + + + + Bad integer value of setting - %1 + + + + + Bad integer value + + + + + Setting %1 is not of integer type + + + + + Setting is not of integer type + + + + + Setting %1 is not of string type + + + + + Setting is not of string type + + + + + Opening the configuration file failed + + + + + The configuration file is malformed + + + + + Fatal failure + + + + + Unknown error + + + + + Password is empty + + + + + PackageChooserPage + + + Form + + + + + Product Name + + + + + TextLabel + + + + + Long Product Description + + + + + Package Selection + + + + + Please pick a product from the list. The selected product will be installed. + + + + + PackageChooserViewStep + + + Packages + + + + + PackageModel + + + Name + + + + + Description + + + + + Page_Keyboard + + + Form + + + + + Keyboard Model: + + + + + Type here to test your keyboard + + + + + Page_UserSetup + + + Form + + + + + What is your name? + + + + + Your Full Name + + + + + What name do you want to use to log in? + + + + + login + + + + + What is the name of this computer? + + + + + <small>This name will be used if you make the computer visible to others on a network.</small> + + + + + Computer Name + + + + + Choose a password to keep your account safe. + + + + + + <small>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.</small> + + + + + + Password + + + + + + Repeat Password + + + + + When this box is checked, password-strength checking is done and you will not be able to use a weak password. + + + + + Require strong passwords. + + + + + Log in automatically without asking for the password. + + + + + Use the same password for the administrator account. + + + + + Choose a password for the administrator account. + + + + + + <small>Enter the same password twice, so that it can be checked for typing errors.</small> + + + + + PartitionLabelsView + + + Root + + + + + Home + + + + + Boot + + + + + EFI system + + + + + Swap + + + + + New partition for %1 + + + + + New partition + + + + + %1 %2 + size[number] filesystem[name] + + + + + PartitionModel + + + + Free Space + + + + + + New partition + + + + + Name + + + + + File System + + + + + Mount Point + + + + + Size + + + + + PartitionPage + + + Form + + + + + Storage de&vice: + + + + + &Revert All Changes + + + + + New Partition &Table + + + + + Cre&ate + + + + + &Edit + + + + + &Delete + + + + + New Volume Group + + + + + Resize Volume Group + + + + + Deactivate Volume Group + + + + + Remove Volume Group + + + + + I&nstall boot loader on: + + + + + Are you sure you want to create a new partition table on %1? + + + + + Can not create new partition + + + + + The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. + + + + + PartitionViewStep + + + Gathering system information... + + + + + Partitions + + + + + Install %1 <strong>alongside</strong> another operating system. + + + + + <strong>Erase</strong> disk and install %1. + + + + + <strong>Replace</strong> a partition with %1. + + + + + <strong>Manual</strong> partitioning. + + + + + Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3). + + + + + <strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1. + + + + + <strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1. + + + + + <strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2). + + + + + Disk <strong>%1</strong> (%2) + + + + + Current: + + + + + After: + + + + + No EFI system partition configured + + + + + An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. + + + + + An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. + + + + + EFI system partition flag not set + + + + + Option to use GPT on BIOS + + + + + A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. + + + + + Boot partition not encrypted + + + + + A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. + + + + + has at least one disk device available. + + + + + There are no partitions to install on. + + + + + PlasmaLnfJob + + + Plasma Look-and-Feel Job + + + + + + Could not select KDE Plasma Look-and-Feel package + + + + + PlasmaLnfPage + + + Form + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is set up. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + PlasmaLnfViewStep + + + Look-and-Feel + + + + + PreserveFiles + + + Saving files for later ... + + + + + No files configured to save for later. + + + + + Not all of the configured files could be preserved. + + + + + ProcessResult + + + +There was no output from the command. + + + + + +Output: + + + + + + External command crashed. + + + + + Command <i>%1</i> crashed. + + + + + External command failed to start. + + + + + Command <i>%1</i> failed to start. + + + + + Internal error when starting command. + + + + + Bad parameters for process job call. + + + + + External command failed to finish. + + + + + Command <i>%1</i> failed to finish in %2 seconds. + + + + + External command finished with errors. + + + + + Command <i>%1</i> finished with exit code %2. + + + + + QObject + + + %1 (%2) + + + + + Requirements checking for module <i>%1</i> is complete. + + + + + unknown + + + + + extended + + + + + unformatted + + + + + swap + + + + + Default Keyboard Model + + + + + + Default + + + + + + + + File not found + + + + + Path <pre>%1</pre> must be an absolute path. + + + + + Could not create new random file <pre>%1</pre>. + + + + + No product + + + + + No description provided. + + + + + (no mount point) + + + + + Unpartitioned space or unknown partition table + + + + + RemoveUserJob + + + Remove live user from target system + + + + + RemoveVolumeGroupJob + + + + Remove Volume Group named %1. + + + + + Remove Volume Group named <strong>%1</strong>. + + + + + The installer failed to remove a volume group named '%1'. + + + + + ReplaceWidget + + + Form + + + + + Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. + + + + + The selected item does not appear to be a valid partition. + + + + + %1 cannot be installed on empty space. Please select an existing partition. + + + + + %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. + + + + + %1 cannot be installed on this partition. + + + + + Data partition (%1) + + + + + Unknown system partition (%1) + + + + + %1 system partition (%2) + + + + + <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. + + + + + <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + + + <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + ResizeFSJob + + + Resize Filesystem Job + + + + + Invalid configuration + + + + + The file-system resize job has an invalid configuration and will not run. + + + + + KPMCore not Available + + + + + Calamares cannot start KPMCore for the file-system resize job. + + + + + + + + + Resize Failed + + + + + The filesystem %1 could not be found in this system, and cannot be resized. + + + + + The device %1 could not be found in this system, and cannot be resized. + + + + + + The filesystem %1 cannot be resized. + + + + + + The device %1 cannot be resized. + + + + + The filesystem %1 must be resized, but cannot. + + + + + The device %1 must be resized, but cannot + + + + + ResizePartitionJob + + + Resize partition %1. + + + + + Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. + + + + + Resizing %2MiB partition %1 to %3MiB. + + + + + The installer failed to resize partition %1 on disk '%2'. + + + + + ResizeVolumeGroupDialog + + + Resize Volume Group + + + + + ResizeVolumeGroupJob + + + + Resize volume group named %1 from %2 to %3. + + + + + Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. + + + + + The installer failed to resize a volume group named '%1'. + + + + + ResultsListDialog + + + For best results, please ensure that this computer: + + + + + System requirements + + + + + ResultsListWidget + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + ScanningDialog + + + Scanning storage devices... + + + + + Partitioning + + + + + SetHostNameJob + + + Set hostname %1 + + + + + Set hostname <strong>%1</strong>. + + + + + Setting hostname %1. + + + + + + Internal Error + + + + + + Cannot write hostname to target system + + + + + SetKeyboardLayoutJob + + + Set keyboard model to %1, layout to %2-%3 + + + + + Failed to write keyboard configuration for the virtual console. + + + + + + + Failed to write to %1 + + + + + Failed to write keyboard configuration for X11. + + + + + Failed to write keyboard configuration to existing /etc/default directory. + + + + + SetPartFlagsJob + + + Set flags on partition %1. + + + + + Set flags on %1MiB %2 partition. + + + + + Set flags on new partition. + + + + + Clear flags on partition <strong>%1</strong>. + + + + + Clear flags on %1MiB <strong>%2</strong> partition. + + + + + Clear flags on new partition. + + + + + Flag partition <strong>%1</strong> as <strong>%2</strong>. + + + + + Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. + + + + + Flag new partition as <strong>%1</strong>. + + + + + Clearing flags on partition <strong>%1</strong>. + + + + + Clearing flags on %1MiB <strong>%2</strong> partition. + + + + + Clearing flags on new partition. + + + + + Setting flags <strong>%2</strong> on partition <strong>%1</strong>. + + + + + Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. + + + + + Setting flags <strong>%1</strong> on new partition. + + + + + The installer failed to set flags on partition %1. + + + + + SetPasswordJob + + + Set password for user %1 + + + + + Setting password for user %1. + + + + + Bad destination system path. + + + + + rootMountPoint is %1 + + + + + Cannot disable root account. + + + + + passwd terminated with error code %1. + + + + + Cannot set password for user %1. + + + + + usermod terminated with error code %1. + + + + + SetTimezoneJob + + + Set timezone to %1/%2 + + + + + Cannot access selected timezone path. + + + + + Bad path: %1 + + + + + Cannot set timezone. + + + + + Link creation failed, target: %1; link name: %2 + + + + + Cannot set timezone, + + + + + Cannot open /etc/timezone for writing + + + + + ShellProcessJob + + + Shell Processes Job + + + + + SlideCounter + + + %L1 / %L2 + slide counter, %1 of %2 (numeric) + + + + + SummaryPage + + + This is an overview of what will happen once you start the setup procedure. + + + + + This is an overview of what will happen once you start the install procedure. + + + + + SummaryViewStep + + + Summary + + + + + TrackingInstallJob + + + Installation feedback + + + + + Sending installation feedback. + + + + + Internal error in install-tracking. + + + + + HTTP request timed out. + + + + + TrackingMachineNeonJob + + + Machine feedback + + + + + Configuring machine feedback. + + + + + + Error in machine feedback configuration. + + + + + Could not configure machine feedback correctly, script error %1. + + + + + Could not configure machine feedback correctly, Calamares error %1. + + + + + TrackingPage + + + Form + + + + + Placeholder + + + + + <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + + + + + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> + + + + + Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with the last two options below), get continuous information about preferred applications. To see what will be sent, please click the help icon next to each area. + + + + + By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. + + + + + By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. + + + + + By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. + + + + + TrackingViewStep + + + Feedback + + + + + UsersPage + + + <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> + + + + + <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> + + + + + Your username is too long. + + + + + Your username must start with a lowercase letter or underscore. + + + + + Only lowercase letters, numbers, underscore and hyphen are allowed. + + + + + Your hostname is too short. + + + + + Your hostname is too long. + + + + + Only letters, numbers, underscore and hyphen are allowed. + + + + + Your passwords do not match! + + + + + UsersViewStep + + + Users + + + + + VariantModel + + + Key + + + + + Value + + + + + VolumeGroupBaseDialog + + + Create Volume Group + + + + + List of Physical Volumes + + + + + Volume Group Name: + + + + + Volume Group Type: + + + + + Physical Extent Size: + + + + + MiB + + + + + Total Size: + + + + + Used Size: + + + + + Total Sectors: + + + + + Quantity of LVs: + + + + + WelcomePage + + + Form + + + + + + Select application and system language + + + + + &About + + + + + Open donations website + + + + + &Donate + + + + + Open help and support website + + + + + &Support + + + + + Open issues and bug-tracking website + + + + + &Known issues + + + + + Open release notes website + + + + + &Release notes + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + %1 support + + + + + About %1 setup + + + + + About %1 installer + + + + + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. + + + + + WelcomeQmlViewStep + + + Welcome + + + + + WelcomeViewStep + + + Welcome + + + + + about + + + <h1>%1</h1><br/> + <strong>%2<br/> + for %3</strong><br/><br/> + Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + Thanks to <a href='https://calamares.io/team/'>the Calamares team</a> + and the <a href='https://www.transifex.com/calamares/calamares/'>Calamares + translators team</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + development is sponsored by <br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. + + + + + Back + + + + + keyboardq + + + Keyboard Model + + + + + Pick your preferred keyboard model or use the default one based on the detected hardware + + + + + Refresh + + + + + + Layouts + + + + + + Keyboard Layout + + + + + Models + + + + + Variants + + + + + Test your keyboard + + + + + notesqml + + + <h3>%1</h3> + <p>These are example release notes.</p> + + + + + release_notes + + + <h3>%1</h3> + <p>This an example QML file, showing options in RichText with Flickable content.</p> + + <p>QML with RichText can use HTML tags, Flickable content is useful for touchscreens.</p> + + <p><b>This is bold text</b></p> + <p><i>This is italic text</i></p> + <p><u>This is underlined text</u></p> + <p><center>This text will be center-aligned.</center></p> + <p><s>This is strikethrough</s></p> + + <p>Code example: + <code>ls -l /home</code></p> + + <p><b>Lists:</b></p> + <ul> + <li>Intel CPU systems</li> + <li>AMD CPU systems</li> + </ul> + + <p>The vertical scrollbar is adjustable, current width set to 10.</p> + + + + + Back + + + + + welcomeq + + + <h3>Welcome to the %1 <quote>%2</quote> installer</h3> + <p>This program will ask you some questions and set up %1 on your computer.</p> + + + + + About + + + + + Support + + + + + Known issues + + + + + Release notes + + + + + Donate + + + + diff --git a/lang/calamares_es.ts b/lang/calamares_es.ts index f54b26d8b..242f5a13f 100644 --- a/lang/calamares_es.ts +++ b/lang/calamares_es.ts @@ -372,7 +372,7 @@ Para configurar el arranque desde un entorno BIOS, este instalador debe instalar Cancel setup without changing the system. - + Cancelar instalación sin cambiar el sistema. @@ -402,7 +402,7 @@ Para configurar el arranque desde un entorno BIOS, este instalador debe instalar Cancel setup? - + ¿Cancelar la instalación? @@ -776,7 +776,7 @@ Saldrá del instalador y se perderán todos los cambios. <h1>Welcome to %1 setup.</h1> - + <h1>Bienvenido al instalador %1.</h1> @@ -1362,12 +1362,12 @@ Saldrá del instalador y se perderán todos los cambios. There is not enough drive space. At least %1 GiB is required. - + No hay suficiente espació en el disco duro. Se requiere al menos %1 GB libre. has at least %1 GiB working memory - + tiene al menos %1 GB de memoria. @@ -1397,12 +1397,12 @@ Saldrá del instalador y se perderán todos los cambios. is running the installer as an administrator (root) - + esta ejecutándose con permisos de administrador (root). The setup program is not running with administrator rights. - + El instalador no esta ejecutándose con permisos de administrador. @@ -1417,7 +1417,7 @@ Saldrá del instalador y se perderán todos los cambios. The screen is too small to display the setup program. - + La pantalla es demasiado pequeña para mostrar el instalador. @@ -1464,7 +1464,7 @@ Saldrá del instalador y se perderán todos los cambios. Creating initramfs with mkinitcpio. - + Creando initramfs con mkinitcpio. @@ -1472,7 +1472,7 @@ Saldrá del instalador y se perderán todos los cambios. Creating initramfs. - + Creando initramfs. @@ -1563,7 +1563,7 @@ Saldrá del instalador y se perderán todos los cambios. <h1>License Agreement</h1> - + <h1>Contrato de licencia</h1> @@ -1651,12 +1651,12 @@ Saldrá del instalador y se perderán todos los cambios. Hide license text - + Ocultar licencia Show the license text - + Ver licencia @@ -1725,7 +1725,7 @@ Saldrá del instalador y se perderán todos los cambios. No partitions are defined. - + No hay particiones definidas. @@ -1779,12 +1779,12 @@ Saldrá del instalador y se perderán todos los cambios. Office software - + Programas de oficina Office package - + Paquete de oficina @@ -1804,12 +1804,12 @@ Saldrá del instalador y se perderán todos los cambios. Kernel - + Kernel Services - + Servicios @@ -1824,7 +1824,7 @@ Saldrá del instalador y se perderán todos los cambios. Applications - + Aplicaciónes @@ -1839,32 +1839,32 @@ Saldrá del instalador y se perderán todos los cambios. Office - + Oficina Multimedia - + Multimedia Internet - + Internet Theming - + Temas Gaming - + Juegos Utilities - + Utilidades @@ -2151,7 +2151,7 @@ Saldrá del instalador y se perderán todos los cambios. Password is empty - + La contraseña vacia @@ -2164,7 +2164,7 @@ Saldrá del instalador y se perderán todos los cambios. Product Name - + Nombre del producto @@ -2174,12 +2174,12 @@ Saldrá del instalador y se perderán todos los cambios. Long Product Description - + Descripción larga del producto Package Selection - + Selección de paquetes @@ -2192,7 +2192,7 @@ Saldrá del instalador y se perderán todos los cambios. Packages - + Paquetes @@ -2241,7 +2241,7 @@ Saldrá del instalador y se perderán todos los cambios. Your Full Name - + Su nombre completo @@ -2266,7 +2266,7 @@ Saldrá del instalador y se perderán todos los cambios. Computer Name - + Nombre de computadora @@ -2283,13 +2283,13 @@ Saldrá del instalador y se perderán todos los cambios. Password - + Contraseña Repeat Password - + Repita la contraseña @@ -2299,7 +2299,7 @@ Saldrá del instalador y se perderán todos los cambios. Require strong passwords. - + Requerir contraseñas seguras @@ -3635,7 +3635,7 @@ Salida: <h1>Welcome to %1 setup.</h1> - + <h1>Bienvenido al instalador %1.</h1> diff --git a/lang/calamares_eu.ts b/lang/calamares_eu.ts index 49caf27dc..a2d04b649 100644 --- a/lang/calamares_eu.ts +++ b/lang/calamares_eu.ts @@ -212,7 +212,7 @@ Loading ... - + Kargatzen ... @@ -222,7 +222,7 @@ Loading failed. - + Kargatzeak huts egin du. @@ -321,7 +321,7 @@ Continue with installation? - + Instalazioarekin jarraitu? @@ -576,7 +576,7 @@ Instalatzailea irten egingo da eta aldaketa guztiak galduko dira. <strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device. - <strong>Diskoa ezabatu</strong><br/>Honek orain dauden datu guztiak <font color="red">ezbatuko</font> ditu biltegiratze-gailutik. + <strong>Diskoa ezabatu</strong><br/>Honek orain dauden datu guztiak <font color="red">ezabatuko</font> ditu biltegiratze-gailutik. @@ -3703,7 +3703,7 @@ Irteera: Back - + Atzera @@ -3711,7 +3711,7 @@ Irteera: Keyboard Model - + Teklatu modeloa @@ -3748,7 +3748,7 @@ Irteera: Test your keyboard - + Frogatu zure teklatua @@ -3790,7 +3790,7 @@ Irteera: Back - + Atzera @@ -3804,7 +3804,7 @@ Irteera: About - + Honi buruz @@ -3824,7 +3824,7 @@ Irteera: Donate - + Egin dohaintza diff --git a/lang/calamares_it_IT.ts b/lang/calamares_it_IT.ts index 2599b2e37..2f8a26f6a 100644 --- a/lang/calamares_it_IT.ts +++ b/lang/calamares_it_IT.ts @@ -706,7 +706,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse Set keyboard layout to %1/%2. - Impostare il layout della tastiera a %1%2. + Impostare il layout della tastiera a %1/%2. @@ -721,17 +721,17 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse Set timezone to %1/%2.<br/> - Imposta il fuso orario a %1%2.<br/> + Imposta il fuso orario a %1/%2.<br/> Network Installation. (Disabled: Incorrect configuration) - Installazione di rete. (Disabilitato: Configurazione scorretta) + Installazione di rete. (Disabilitato: Configurazione non valida) Network Installation. (Disabled: Received invalid groups data) - Installazione di rete. (Disabilitata: Ricevuti dati non validi dei gruppi) + Installazione di rete. (Disabilitata: Ricevuti dati dei gruppi non validi) @@ -746,22 +746,22 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> - Questo computer non soddisfa i requisiti minimi per l'installazione di %1.<br/>L'installazione non può continuare. <a href="#details">Dettagli...</a> + Questo computer non soddisfa i requisiti minimi per la configurazione di %1.<br/>La configurazione non può continuare. <a href="#details">Dettagli...</a> This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> - Questo computer non soddisfa i requisiti minimi per installare %1. <br/>L'installazione non può proseguire. <a href="#details">Dettagli...</a> + Questo computer non soddisfa i requisiti minimi per installare %1. <br/>L'installazione non può continuare. <a href="#details">Dettagli...</a> This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. - Questo computer non soddisfa alcuni requisiti raccomandati per l'installazione di %1.<br/>L'installazione può continuare, ma alcune funzionalità potrebbero essere disabilitate. + Questo computer non soddisfa alcuni requisiti raccomandati per la configurazione di %1.<br/>La configurazione può continuare ma alcune funzionalità potrebbero essere disabilitate. This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. - Questo computer non soddisfa alcuni requisiti consigliati per l'installazione di %1. <br/>L'installazione può proseguire ma alcune funzionalità potrebbero non essere disponibili. + Questo computer non soddisfa alcuni requisiti consigliati per l'installazione di %1.<br/>L'installazione può continuare ma alcune funzionalità potrebbero non essere disponibili. @@ -771,17 +771,17 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse <h1>Welcome to the Calamares setup program for %1.</h1> - <h1>Benvenuto nel programma di installazione Calamares di %1.</h1> + <h1>Benvenuto nel programma di configurazione Calamares per %1.</h1> <h1>Welcome to %1 setup.</h1> - <h1>Benvenuto nell'installazione di %1.</h1> + <h1>Benvenuto nella configurazione di %1.</h1> <h1>Welcome to the Calamares installer for %1.</h1> - <h1>Benvenuti nel programma di installazione Calamares per %1.</h1> + <h1>Benvenuti nel programma d'installazione Calamares per %1.</h1> @@ -880,12 +880,12 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse Create new %2MiB partition on %4 (%3) with file system %1. - Crea una nuova partizione da %2MiB su %4 (%3) con file system %1 + Crea una nuova partizione da %2MiB su %4 (%3) con file system %1. Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. - Creare nuova partizione di <strong>%2MiB</strong> su <strong>%4</strong> (%3) con file system <strong>%1</strong>. + Crea una nuova partizione di <strong>%2MiB</strong> su <strong>%4</strong> (%3) con file system <strong>%1</strong>. @@ -1015,7 +1015,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse The installer failed to create a volume group named '%1'. - Il programma di installazione non è riuscito a creare un gruppo di volumi denominato '%1'. + Il programma d'installazione non è riuscito a creare un gruppo di volumi denominato '%1'. @@ -1024,7 +1024,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno perse Deactivate volume group named %1. - Disattiva gruppo di volumi denominato %1. + Disattiva il gruppo di volumi denominato %1. @@ -3799,7 +3799,27 @@ Output: </ul> <p>The vertical scrollbar is adjustable, current width set to 10.</p> - + <h3>%1</h3> + <p>Questo è un file QML di esempio, che mostra le opzioni in RichText con contenuto scorrevole</p> + + <p>QML con RichText può utilizzare tag HTML, il contenuto scorrevole è utile per i touchscreen.</p> + + <p><b>Questo è un testo in grassetto</b></p> + <p><i>Questo è un testo in corsivo</i></p> + <p><u>Questo è un testo sottolineato</u></p> + <p><center>Questo testo sarà allineato al centro.</center></p> + <p><s>Questo è un testo barrato</s></p> + + <p>Esempio di codice: + <code>ls -l /home</code></p> + + <p><b>Liste:</b></p> + <ul> + <li>Sistemi con CPU Intel</li> + <li>Sistemi con CPU AMD</li> + </ul> + + <p>La barra di scorrimento verticale è regolabile, la larghezza corrente è impostata a 10.</p> diff --git a/lang/calamares_lv.ts b/lang/calamares_lv.ts new file mode 100644 index 000000000..4d6272e18 --- /dev/null +++ b/lang/calamares_lv.ts @@ -0,0 +1,3829 @@ + + + + + BootInfoWidget + + + The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode. + + + + + This system was started with an <strong>EFI</strong> boot environment.<br><br>To configure startup from an EFI environment, this installer must deploy a boot loader application, like <strong>GRUB</strong> or <strong>systemd-boot</strong> on an <strong>EFI System Partition</strong>. This is automatic, unless you choose manual partitioning, in which case you must choose it or create it on your own. + + + + + This system was started with a <strong>BIOS</strong> boot environment.<br><br>To configure startup from a BIOS environment, this installer must install a boot loader, like <strong>GRUB</strong>, either at the beginning of a partition or on the <strong>Master Boot Record</strong> near the beginning of the partition table (preferred). This is automatic, unless you choose manual partitioning, in which case you must set it up on your own. + + + + + BootLoaderModel + + + Master Boot Record of %1 + + + + + Boot Partition + + + + + System Partition + + + + + Do not install a boot loader + + + + + %1 (%2) + + + + + Calamares::BlankViewStep + + + Blank Page + + + + + Calamares::DebugWindow + + + Form + + + + + GlobalStorage + + + + + JobQueue + + + + + Modules + + + + + Type: + + + + + + none + + + + + Interface: + + + + + Tools + + + + + Reload Stylesheet + + + + + Widget Tree + + + + + Debug information + + + + + Calamares::ExecutionViewStep + + + Set up + + + + + Install + + + + + Calamares::FailJob + + + Job failed (%1) + + + + + Programmed job failure was explicitly requested. + + + + + Calamares::JobThread + + + Done + + + + + Calamares::NamedJob + + + Example job (%1) + + + + + Calamares::ProcessJob + + + Run command '%1' in target system. + + + + + Run command '%1'. + + + + + Running command %1 %2 + + + + + Calamares::PythonJob + + + Running %1 operation. + + + + + Bad working directory path + + + + + Working directory %1 for python job %2 is not readable. + + + + + Bad main script file + + + + + Main script file %1 for python job %2 is not readable. + + + + + Boost.Python error in job "%1". + + + + + Calamares::QmlViewStep + + + Loading ... + + + + + QML Step <i>%1</i>. + + + + + Loading failed. + + + + + Calamares::RequirementsChecker + + + Waiting for %n module(s). + + + + + + + + + (%n second(s)) + + + + + + + + + System-requirements checking is complete. + + + + + Calamares::ViewManager + + + Setup Failed + + + + + Installation Failed + + + + + Would you like to paste the install log to the web? + + + + + Error + + + + + + &Yes + + + + + + &No + + + + + &Close + + + + + Install Log Paste URL + + + + + The upload was unsuccessful. No web-paste was done. + + + + + Calamares Initialization Failed + + + + + %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. + + + + + <br/>The following modules could not be loaded: + + + + + Continue with setup? + + + + + Continue with installation? + + + + + The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + &Set up now + + + + + &Install now + + + + + Go &back + + + + + &Set up + + + + + &Install + + + + + Setup is complete. Close the setup program. + + + + + The installation is complete. Close the installer. + + + + + Cancel setup without changing the system. + + + + + Cancel installation without changing the system. + + + + + &Next + + + + + &Back + + + + + &Done + + + + + &Cancel + + + + + Cancel setup? + + + + + Cancel installation? + + + + + Do you really want to cancel the current setup process? +The setup program will quit and all changes will be lost. + + + + + Do you really want to cancel the current install process? +The installer will quit and all changes will be lost. + + + + + CalamaresPython::Helper + + + Unknown exception type + + + + + unparseable Python error + + + + + unparseable Python traceback + + + + + Unfetchable Python error. + + + + + CalamaresUtils + + + Install log posted to: +%1 + + + + + CalamaresWindow + + + Show debug information + + + + + &Back + + + + + &Next + + + + + &Cancel + + + + + %1 Setup Program + + + + + %1 Installer + + + + + CheckerContainer + + + Gathering system information... + + + + + ChoicePage + + + Form + + + + + Select storage de&vice: + + + + + + + + Current: + + + + + After: + + + + + <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. Having a GPT partition table and <strong>fat32 512Mb /boot partition is a must for UEFI installs</strong>, either use an existing without formatting or create one. + + + + + Reuse %1 as home partition for %2. + + + + + <strong>Select a partition to shrink, then drag the bottom bar to resize</strong> + + + + + %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. + + + + + Boot loader location: + + + + + <strong>Select a partition to install on</strong> + + + + + An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + + + + <strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device. + + + + + + + + <strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1. + + + + + + + + <strong>Replace a partition</strong><br/>Replaces a partition with %1. + + + + + This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + No Swap + + + + + Reuse Swap + + + + + Swap (no Hibernate) + + + + + Swap (with Hibernate) + + + + + Swap to file + + + + + ClearMountsJob + + + Clear mounts for partitioning operations on %1 + + + + + Clearing mounts for partitioning operations on %1. + + + + + Cleared all mounts for %1 + + + + + ClearTempMountsJob + + + Clear all temporary mounts. + + + + + Clearing all temporary mounts. + + + + + Cannot get list of temporary mounts. + + + + + Cleared all temporary mounts. + + + + + CommandList + + + + Could not run command. + + + + + The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. + + + + + The command needs to know the user's name, but no username is defined. + + + + + Config + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + Network Installation. (Disabled: Incorrect configuration) + + + + + Network Installation. (Disabled: Received invalid groups data) + + + + + Network Installation. (Disabled: internal error) + + + + + Network Installation. (Disabled: Unable to fetch package lists, check your network connection) + + + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + ContextualProcessJob + + + Contextual Processes Job + + + + + CreatePartitionDialog + + + Create a Partition + + + + + Si&ze: + + + + + MiB + + + + + Partition &Type: + + + + + &Primary + + + + + E&xtended + + + + + Fi&le System: + + + + + LVM LV name + + + + + &Mount Point: + + + + + Flags: + + + + + En&crypt + + + + + Logical + + + + + Primary + + + + + GPT + + + + + Mountpoint already in use. Please select another one. + + + + + CreatePartitionJob + + + Create new %2MiB partition on %4 (%3) with file system %1. + + + + + Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. + + + + + Creating new %1 partition on %2. + + + + + The installer failed to create partition on disk '%1'. + + + + + CreatePartitionTableDialog + + + Create Partition Table + + + + + Creating a new partition table will delete all existing data on the disk. + + + + + What kind of partition table do you want to create? + + + + + Master Boot Record (MBR) + + + + + GUID Partition Table (GPT) + + + + + CreatePartitionTableJob + + + Create new %1 partition table on %2. + + + + + Create new <strong>%1</strong> partition table on <strong>%2</strong> (%3). + + + + + Creating new %1 partition table on %2. + + + + + The installer failed to create a partition table on %1. + + + + + CreateUserJob + + + Create user %1 + + + + + Create user <strong>%1</strong>. + + + + + Creating user %1. + + + + + Sudoers dir is not writable. + + + + + Cannot create sudoers file for writing. + + + + + Cannot chmod sudoers file. + + + + + Cannot open groups file for reading. + + + + + CreateVolumeGroupDialog + + + Create Volume Group + + + + + CreateVolumeGroupJob + + + Create new volume group named %1. + + + + + Create new volume group named <strong>%1</strong>. + + + + + Creating new volume group named %1. + + + + + The installer failed to create a volume group named '%1'. + + + + + DeactivateVolumeGroupJob + + + + Deactivate volume group named %1. + + + + + Deactivate volume group named <strong>%1</strong>. + + + + + The installer failed to deactivate a volume group named %1. + + + + + DeletePartitionJob + + + Delete partition %1. + + + + + Delete partition <strong>%1</strong>. + + + + + Deleting partition %1. + + + + + The installer failed to delete partition %1. + + + + + DeviceInfoWidget + + + This device has a <strong>%1</strong> partition table. + + + + + This is a <strong>loop</strong> device.<br><br>It is a pseudo-device with no partition table that makes a file accessible as a block device. This kind of setup usually only contains a single filesystem. + + + + + This installer <strong>cannot detect a partition table</strong> on the selected storage device.<br><br>The device either has no partition table, or the partition table is corrupted or of an unknown type.<br>This installer can create a new partition table for you, either automatically, or through the manual partitioning page. + + + + + <br><br>This is the recommended partition table type for modern systems which start from an <strong>EFI</strong> boot environment. + + + + + <br><br>This partition table type is only advisable on older systems which start from a <strong>BIOS</strong> boot environment. GPT is recommended in most other cases.<br><br><strong>Warning:</strong> the MBR partition table is an obsolete MS-DOS era standard.<br>Only 4 <em>primary</em> partitions may be created, and of those 4, one can be an <em>extended</em> partition, which may in turn contain many <em>logical</em> partitions. + + + + + The type of <strong>partition table</strong> on the selected storage device.<br><br>The only way to change the partition table type is to erase and recreate the partition table from scratch, which destroys all data on the storage device.<br>This installer will keep the current partition table unless you explicitly choose otherwise.<br>If unsure, on modern systems GPT is preferred. + + + + + DeviceModel + + + %1 - %2 (%3) + device[name] - size[number] (device-node[name]) + + + + + %1 - (%2) + device[name] - (device-node[name]) + + + + + DracutLuksCfgJob + + + Write LUKS configuration for Dracut to %1 + + + + + Skip writing LUKS configuration for Dracut: "/" partition is not encrypted + + + + + Failed to open %1 + + + + + DummyCppJob + + + Dummy C++ Job + + + + + EditExistingPartitionDialog + + + Edit Existing Partition + + + + + Content: + + + + + &Keep + + + + + Format + + + + + Warning: Formatting the partition will erase all existing data. + + + + + &Mount Point: + + + + + Si&ze: + + + + + MiB + + + + + Fi&le System: + + + + + Flags: + + + + + Mountpoint already in use. Please select another one. + + + + + EncryptWidget + + + Form + + + + + En&crypt system + + + + + Passphrase + + + + + Confirm passphrase + + + + + Please enter the same passphrase in both boxes. + + + + + FillGlobalStorageJob + + + Set partition information + + + + + Install %1 on <strong>new</strong> %2 system partition. + + + + + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>. + + + + + Install %2 on %3 system partition <strong>%1</strong>. + + + + + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>. + + + + + Install boot loader on <strong>%1</strong>. + + + + + Setting up mount points. + + + + + FinishedPage + + + Form + + + + + &Restart now + + + + + <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> + + + + + <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> + + + + + <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. + + + + + <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. + + + + + FinishedViewStep + + + Finish + + + + + Setup Complete + + + + + Installation Complete + + + + + The setup of %1 is complete. + + + + + The installation of %1 is complete. + + + + + FormatPartitionJob + + + Format partition %1 (file system: %2, size: %3 MiB) on %4. + + + + + Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. + + + + + Formatting partition %1 with file system %2. + + + + + The installer failed to format partition %1 on disk '%2'. + + + + + GeneralRequirements + + + has at least %1 GiB available drive space + + + + + There is not enough drive space. At least %1 GiB is required. + + + + + has at least %1 GiB working memory + + + + + The system does not have enough working memory. At least %1 GiB is required. + + + + + is plugged in to a power source + + + + + The system is not plugged in to a power source. + + + + + is connected to the Internet + + + + + The system is not connected to the Internet. + + + + + is running the installer as an administrator (root) + + + + + The setup program is not running with administrator rights. + + + + + The installer is not running with administrator rights. + + + + + has a screen large enough to show the whole installer + + + + + The screen is too small to display the setup program. + + + + + The screen is too small to display the installer. + + + + + HostInfoJob + + + Collecting information about your machine. + + + + + IDJob + + + + + + OEM Batch Identifier + + + + + Could not create directories <code>%1</code>. + + + + + Could not open file <code>%1</code>. + + + + + Could not write to file <code>%1</code>. + + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + + + InteractiveTerminalPage + + + Konsole not installed + + + + + Please install KDE Konsole and try again! + + + + + Executing script: &nbsp;<code>%1</code> + + + + + InteractiveTerminalViewStep + + + Script + + + + + KeyboardPage + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + KeyboardQmlViewStep + + + Keyboard + + + + + KeyboardViewStep + + + Keyboard + + + + + LCLocaleDialog + + + System locale setting + + + + + The system locale setting affects the language and character set for some command line user interface elements.<br/>The current setting is <strong>%1</strong>. + + + + + &Cancel + + + + + &OK + + + + + LicensePage + + + Form + + + + + <h1>License Agreement</h1> + + + + + I accept the terms and conditions above. + + + + + Please review the End User License Agreements (EULAs). + + + + + This setup procedure will install proprietary software that is subject to licensing terms. + + + + + If you do not agree with the terms, the setup procedure cannot continue. + + + + + This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. + + + + + If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. + + + + + LicenseViewStep + + + License + + + + + LicenseWidget + + + URL: %1 + + + + + <strong>%1 driver</strong><br/>by %2 + %1 is an untranslatable product name, example: Creative Audigy driver + + + + + <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> + %1 is usually a vendor name, example: Nvidia graphics driver + + + + + <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 codec</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 package</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1</strong><br/><font color="Grey">by %2</font> + + + + + File: %1 + + + + + Hide license text + + + + + Show the license text + + + + + Open license agreement in browser. + + + + + LocalePage + + + Region: + + + + + Zone: + + + + + + &Change... + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + LocaleQmlViewStep + + + Location + + + + + LocaleViewStep + + + Location + + + + + LuksBootKeyFileJob + + + Configuring LUKS key file. + + + + + + No partitions are defined. + + + + + + + Encrypted rootfs setup error + + + + + Root partition %1 is LUKS but no passphrase has been set. + + + + + Could not create LUKS key file for root partition %1. + + + + + Could not configure LUKS key file on partition %1. + + + + + MachineIdJob + + + Generate machine-id. + + + + + Configuration Error + + + + + No root mount point is set for MachineId. + + + + + NetInstallViewStep + + + + Package selection + + + + + Office software + + + + + Office package + + + + + Browser software + + + + + Browser package + + + + + Web browser + + + + + Kernel + + + + + Services + + + + + Login + + + + + Desktop + + + + + Applications + + + + + Communication + + + + + Development + + + + + Office + + + + + Multimedia + + + + + Internet + + + + + Theming + + + + + Gaming + + + + + Utilities + + + + + NotesQmlViewStep + + + Notes + + + + + OEMPage + + + Ba&tch: + + + + + <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> + + + + + <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> + + + + + OEMViewStep + + + OEM Configuration + + + + + Set the OEM Batch Identifier to <code>%1</code>. + + + + + PWQ + + + Password is too short + + + + + Password is too long + + + + + Password is too weak + + + + + Memory allocation error when setting '%1' + + + + + Memory allocation error + + + + + The password is the same as the old one + + + + + The password is a palindrome + + + + + The password differs with case changes only + + + + + The password is too similar to the old one + + + + + The password contains the user name in some form + + + + + The password contains words from the real name of the user in some form + + + + + The password contains forbidden words in some form + + + + + The password contains less than %1 digits + + + + + The password contains too few digits + + + + + The password contains less than %1 uppercase letters + + + + + The password contains too few uppercase letters + + + + + The password contains less than %1 lowercase letters + + + + + The password contains too few lowercase letters + + + + + The password contains less than %1 non-alphanumeric characters + + + + + The password contains too few non-alphanumeric characters + + + + + The password is shorter than %1 characters + + + + + The password is too short + + + + + The password is just rotated old one + + + + + The password contains less than %1 character classes + + + + + The password does not contain enough character classes + + + + + The password contains more than %1 same characters consecutively + + + + + The password contains too many same characters consecutively + + + + + The password contains more than %1 characters of the same class consecutively + + + + + The password contains too many characters of the same class consecutively + + + + + The password contains monotonic sequence longer than %1 characters + + + + + The password contains too long of a monotonic character sequence + + + + + No password supplied + + + + + Cannot obtain random numbers from the RNG device + + + + + Password generation failed - required entropy too low for settings + + + + + The password fails the dictionary check - %1 + + + + + The password fails the dictionary check + + + + + Unknown setting - %1 + + + + + Unknown setting + + + + + Bad integer value of setting - %1 + + + + + Bad integer value + + + + + Setting %1 is not of integer type + + + + + Setting is not of integer type + + + + + Setting %1 is not of string type + + + + + Setting is not of string type + + + + + Opening the configuration file failed + + + + + The configuration file is malformed + + + + + Fatal failure + + + + + Unknown error + + + + + Password is empty + + + + + PackageChooserPage + + + Form + + + + + Product Name + + + + + TextLabel + + + + + Long Product Description + + + + + Package Selection + + + + + Please pick a product from the list. The selected product will be installed. + + + + + PackageChooserViewStep + + + Packages + + + + + PackageModel + + + Name + + + + + Description + + + + + Page_Keyboard + + + Form + + + + + Keyboard Model: + + + + + Type here to test your keyboard + + + + + Page_UserSetup + + + Form + + + + + What is your name? + + + + + Your Full Name + + + + + What name do you want to use to log in? + + + + + login + + + + + What is the name of this computer? + + + + + <small>This name will be used if you make the computer visible to others on a network.</small> + + + + + Computer Name + + + + + Choose a password to keep your account safe. + + + + + + <small>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.</small> + + + + + + Password + + + + + + Repeat Password + + + + + When this box is checked, password-strength checking is done and you will not be able to use a weak password. + + + + + Require strong passwords. + + + + + Log in automatically without asking for the password. + + + + + Use the same password for the administrator account. + + + + + Choose a password for the administrator account. + + + + + + <small>Enter the same password twice, so that it can be checked for typing errors.</small> + + + + + PartitionLabelsView + + + Root + + + + + Home + + + + + Boot + + + + + EFI system + + + + + Swap + + + + + New partition for %1 + + + + + New partition + + + + + %1 %2 + size[number] filesystem[name] + + + + + PartitionModel + + + + Free Space + + + + + + New partition + + + + + Name + + + + + File System + + + + + Mount Point + + + + + Size + + + + + PartitionPage + + + Form + + + + + Storage de&vice: + + + + + &Revert All Changes + + + + + New Partition &Table + + + + + Cre&ate + + + + + &Edit + + + + + &Delete + + + + + New Volume Group + + + + + Resize Volume Group + + + + + Deactivate Volume Group + + + + + Remove Volume Group + + + + + I&nstall boot loader on: + + + + + Are you sure you want to create a new partition table on %1? + + + + + Can not create new partition + + + + + The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. + + + + + PartitionViewStep + + + Gathering system information... + + + + + Partitions + + + + + Install %1 <strong>alongside</strong> another operating system. + + + + + <strong>Erase</strong> disk and install %1. + + + + + <strong>Replace</strong> a partition with %1. + + + + + <strong>Manual</strong> partitioning. + + + + + Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3). + + + + + <strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1. + + + + + <strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1. + + + + + <strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2). + + + + + Disk <strong>%1</strong> (%2) + + + + + Current: + + + + + After: + + + + + No EFI system partition configured + + + + + An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. + + + + + An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. + + + + + EFI system partition flag not set + + + + + Option to use GPT on BIOS + + + + + A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. + + + + + Boot partition not encrypted + + + + + A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. + + + + + has at least one disk device available. + + + + + There are no partitions to install on. + + + + + PlasmaLnfJob + + + Plasma Look-and-Feel Job + + + + + + Could not select KDE Plasma Look-and-Feel package + + + + + PlasmaLnfPage + + + Form + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is set up. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + PlasmaLnfViewStep + + + Look-and-Feel + + + + + PreserveFiles + + + Saving files for later ... + + + + + No files configured to save for later. + + + + + Not all of the configured files could be preserved. + + + + + ProcessResult + + + +There was no output from the command. + + + + + +Output: + + + + + + External command crashed. + + + + + Command <i>%1</i> crashed. + + + + + External command failed to start. + + + + + Command <i>%1</i> failed to start. + + + + + Internal error when starting command. + + + + + Bad parameters for process job call. + + + + + External command failed to finish. + + + + + Command <i>%1</i> failed to finish in %2 seconds. + + + + + External command finished with errors. + + + + + Command <i>%1</i> finished with exit code %2. + + + + + QObject + + + %1 (%2) + + + + + Requirements checking for module <i>%1</i> is complete. + + + + + unknown + + + + + extended + + + + + unformatted + + + + + swap + + + + + Default Keyboard Model + + + + + + Default + + + + + + + + File not found + + + + + Path <pre>%1</pre> must be an absolute path. + + + + + Could not create new random file <pre>%1</pre>. + + + + + No product + + + + + No description provided. + + + + + (no mount point) + + + + + Unpartitioned space or unknown partition table + + + + + RemoveUserJob + + + Remove live user from target system + + + + + RemoveVolumeGroupJob + + + + Remove Volume Group named %1. + + + + + Remove Volume Group named <strong>%1</strong>. + + + + + The installer failed to remove a volume group named '%1'. + + + + + ReplaceWidget + + + Form + + + + + Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. + + + + + The selected item does not appear to be a valid partition. + + + + + %1 cannot be installed on empty space. Please select an existing partition. + + + + + %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. + + + + + %1 cannot be installed on this partition. + + + + + Data partition (%1) + + + + + Unknown system partition (%1) + + + + + %1 system partition (%2) + + + + + <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. + + + + + <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + + + <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + ResizeFSJob + + + Resize Filesystem Job + + + + + Invalid configuration + + + + + The file-system resize job has an invalid configuration and will not run. + + + + + KPMCore not Available + + + + + Calamares cannot start KPMCore for the file-system resize job. + + + + + + + + + Resize Failed + + + + + The filesystem %1 could not be found in this system, and cannot be resized. + + + + + The device %1 could not be found in this system, and cannot be resized. + + + + + + The filesystem %1 cannot be resized. + + + + + + The device %1 cannot be resized. + + + + + The filesystem %1 must be resized, but cannot. + + + + + The device %1 must be resized, but cannot + + + + + ResizePartitionJob + + + Resize partition %1. + + + + + Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. + + + + + Resizing %2MiB partition %1 to %3MiB. + + + + + The installer failed to resize partition %1 on disk '%2'. + + + + + ResizeVolumeGroupDialog + + + Resize Volume Group + + + + + ResizeVolumeGroupJob + + + + Resize volume group named %1 from %2 to %3. + + + + + Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. + + + + + The installer failed to resize a volume group named '%1'. + + + + + ResultsListDialog + + + For best results, please ensure that this computer: + + + + + System requirements + + + + + ResultsListWidget + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + ScanningDialog + + + Scanning storage devices... + + + + + Partitioning + + + + + SetHostNameJob + + + Set hostname %1 + + + + + Set hostname <strong>%1</strong>. + + + + + Setting hostname %1. + + + + + + Internal Error + + + + + + Cannot write hostname to target system + + + + + SetKeyboardLayoutJob + + + Set keyboard model to %1, layout to %2-%3 + + + + + Failed to write keyboard configuration for the virtual console. + + + + + + + Failed to write to %1 + + + + + Failed to write keyboard configuration for X11. + + + + + Failed to write keyboard configuration to existing /etc/default directory. + + + + + SetPartFlagsJob + + + Set flags on partition %1. + + + + + Set flags on %1MiB %2 partition. + + + + + Set flags on new partition. + + + + + Clear flags on partition <strong>%1</strong>. + + + + + Clear flags on %1MiB <strong>%2</strong> partition. + + + + + Clear flags on new partition. + + + + + Flag partition <strong>%1</strong> as <strong>%2</strong>. + + + + + Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. + + + + + Flag new partition as <strong>%1</strong>. + + + + + Clearing flags on partition <strong>%1</strong>. + + + + + Clearing flags on %1MiB <strong>%2</strong> partition. + + + + + Clearing flags on new partition. + + + + + Setting flags <strong>%2</strong> on partition <strong>%1</strong>. + + + + + Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. + + + + + Setting flags <strong>%1</strong> on new partition. + + + + + The installer failed to set flags on partition %1. + + + + + SetPasswordJob + + + Set password for user %1 + + + + + Setting password for user %1. + + + + + Bad destination system path. + + + + + rootMountPoint is %1 + + + + + Cannot disable root account. + + + + + passwd terminated with error code %1. + + + + + Cannot set password for user %1. + + + + + usermod terminated with error code %1. + + + + + SetTimezoneJob + + + Set timezone to %1/%2 + + + + + Cannot access selected timezone path. + + + + + Bad path: %1 + + + + + Cannot set timezone. + + + + + Link creation failed, target: %1; link name: %2 + + + + + Cannot set timezone, + + + + + Cannot open /etc/timezone for writing + + + + + ShellProcessJob + + + Shell Processes Job + + + + + SlideCounter + + + %L1 / %L2 + slide counter, %1 of %2 (numeric) + + + + + SummaryPage + + + This is an overview of what will happen once you start the setup procedure. + + + + + This is an overview of what will happen once you start the install procedure. + + + + + SummaryViewStep + + + Summary + + + + + TrackingInstallJob + + + Installation feedback + + + + + Sending installation feedback. + + + + + Internal error in install-tracking. + + + + + HTTP request timed out. + + + + + TrackingMachineNeonJob + + + Machine feedback + + + + + Configuring machine feedback. + + + + + + Error in machine feedback configuration. + + + + + Could not configure machine feedback correctly, script error %1. + + + + + Could not configure machine feedback correctly, Calamares error %1. + + + + + TrackingPage + + + Form + + + + + Placeholder + + + + + <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + + + + + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> + + + + + Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with the last two options below), get continuous information about preferred applications. To see what will be sent, please click the help icon next to each area. + + + + + By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. + + + + + By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. + + + + + By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. + + + + + TrackingViewStep + + + Feedback + + + + + UsersPage + + + <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> + + + + + <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> + + + + + Your username is too long. + + + + + Your username must start with a lowercase letter or underscore. + + + + + Only lowercase letters, numbers, underscore and hyphen are allowed. + + + + + Your hostname is too short. + + + + + Your hostname is too long. + + + + + Only letters, numbers, underscore and hyphen are allowed. + + + + + Your passwords do not match! + + + + + UsersViewStep + + + Users + + + + + VariantModel + + + Key + + + + + Value + + + + + VolumeGroupBaseDialog + + + Create Volume Group + + + + + List of Physical Volumes + + + + + Volume Group Name: + + + + + Volume Group Type: + + + + + Physical Extent Size: + + + + + MiB + + + + + Total Size: + + + + + Used Size: + + + + + Total Sectors: + + + + + Quantity of LVs: + + + + + WelcomePage + + + Form + + + + + + Select application and system language + + + + + &About + + + + + Open donations website + + + + + &Donate + + + + + Open help and support website + + + + + &Support + + + + + Open issues and bug-tracking website + + + + + &Known issues + + + + + Open release notes website + + + + + &Release notes + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + %1 support + + + + + About %1 setup + + + + + About %1 installer + + + + + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. + + + + + WelcomeQmlViewStep + + + Welcome + + + + + WelcomeViewStep + + + Welcome + + + + + about + + + <h1>%1</h1><br/> + <strong>%2<br/> + for %3</strong><br/><br/> + Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + Thanks to <a href='https://calamares.io/team/'>the Calamares team</a> + and the <a href='https://www.transifex.com/calamares/calamares/'>Calamares + translators team</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + development is sponsored by <br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. + + + + + Back + + + + + keyboardq + + + Keyboard Model + + + + + Pick your preferred keyboard model or use the default one based on the detected hardware + + + + + Refresh + + + + + + Layouts + + + + + + Keyboard Layout + + + + + Models + + + + + Variants + + + + + Test your keyboard + + + + + notesqml + + + <h3>%1</h3> + <p>These are example release notes.</p> + + + + + release_notes + + + <h3>%1</h3> + <p>This an example QML file, showing options in RichText with Flickable content.</p> + + <p>QML with RichText can use HTML tags, Flickable content is useful for touchscreens.</p> + + <p><b>This is bold text</b></p> + <p><i>This is italic text</i></p> + <p><u>This is underlined text</u></p> + <p><center>This text will be center-aligned.</center></p> + <p><s>This is strikethrough</s></p> + + <p>Code example: + <code>ls -l /home</code></p> + + <p><b>Lists:</b></p> + <ul> + <li>Intel CPU systems</li> + <li>AMD CPU systems</li> + </ul> + + <p>The vertical scrollbar is adjustable, current width set to 10.</p> + + + + + Back + + + + + welcomeq + + + <h3>Welcome to the %1 <quote>%2</quote> installer</h3> + <p>This program will ask you some questions and set up %1 on your computer.</p> + + + + + About + + + + + Support + + + + + Known issues + + + + + Release notes + + + + + Donate + + + + diff --git a/lang/calamares_sq.ts b/lang/calamares_sq.ts index 869a1f18c..cbbc2e9d9 100644 --- a/lang/calamares_sq.ts +++ b/lang/calamares_sq.ts @@ -124,7 +124,7 @@ Install - Instaloje + Instalim @@ -520,7 +520,7 @@ Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. After: - Pas: + Më Pas: @@ -937,7 +937,7 @@ Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. Create new <strong>%1</strong> partition table on <strong>%2</strong> (%3). - Krijoni tabelë pjesësh të re <strong>%1</strong> te <strong>%2</strong> (%3). + Krijo tabelë pjesësh të re <strong>%1</strong> te <strong>%2</strong> (%3). @@ -1307,7 +1307,7 @@ Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. Finish - Përfundoje + Përfundim @@ -3080,7 +3080,7 @@ Përfundim: Partitioning - Pjesëzim + Pjesëtim diff --git a/lang/calamares_sv.ts b/lang/calamares_sv.ts index c9824f26e..82238ca09 100644 --- a/lang/calamares_sv.ts +++ b/lang/calamares_sv.ts @@ -106,7 +106,7 @@ Widget Tree - + Widgetträd @@ -246,7 +246,7 @@ System-requirements checking is complete. - + Kontroll av systemkrav är färdig @@ -264,7 +264,7 @@ Would you like to paste the install log to the web? - + Vill du ladda upp installationsloggen på webben? @@ -291,7 +291,7 @@ Install Log Paste URL - + URL till installationslogg @@ -306,7 +306,7 @@ %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. - + %1 kan inte installeras. Calamares kunde inte ladda alla konfigurerade moduler. Detta är ett problem med hur Calamares används av distributionen. @@ -326,7 +326,7 @@ The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> - + %1-installeraren är på väg att göra ändringar på disk för att installera %2.<br/><strong>Du kommer inte att kunna ångra dessa ändringar.</strong> @@ -412,7 +412,7 @@ Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. - + Vill du verkligen avbryta den nuvarande uppstartsprocessen? Uppstartsprogrammet kommer avsluta och alla ändringar kommer förloras. @@ -524,7 +524,7 @@ Alla ändringar kommer att gå förlorade. <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. Having a GPT partition table and <strong>fat32 512Mb /boot partition is a must for UEFI installs</strong>, either use an existing without formatting or create one. - + <strong>Manuell partitionering</strong><br/>Du kan skapa eller ändra storlek på partitioner själv. UEFI-installationer kräver en GPT-partitionstabell och en <strong>fat32-partition för /boot på 512MB</strong>, använd en existerande utan formatering eller skapa en. @@ -688,7 +688,7 @@ Alla ändringar kommer att gå förlorade. The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. - + Kommandot körs på värden och behöver känna till sökvägen till root, men rootMountPoint är inte definierat. @@ -716,7 +716,7 @@ Alla ändringar kommer att gå förlorade. The numbers and dates locale will be set to %1. - + Systemspråket för siffror och datum kommer sättas till %1. @@ -731,7 +731,7 @@ Alla ändringar kommer att gå förlorade. Network Installation. (Disabled: Received invalid groups data) - + Nätverksinstallation. (Inaktiverad: Fick felaktig gruppdata) @@ -1070,12 +1070,12 @@ Alla ändringar kommer att gå förlorade. This is a <strong>loop</strong> device.<br><br>It is a pseudo-device with no partition table that makes a file accessible as a block device. This kind of setup usually only contains a single filesystem. - + Detta är en <strong>loop</strong>enhet.<br><br>Det är en pseudo-enhet som inte har någon partitionstabell, och som gör en fil tillgänglig som en blockenhet. Denna typ av upplägg innehåller vanligtvis ett enda filsystem. This installer <strong>cannot detect a partition table</strong> on the selected storage device.<br><br>The device either has no partition table, or the partition table is corrupted or of an unknown type.<br>This installer can create a new partition table for you, either automatically, or through the manual partitioning page. - + Installationsprogrammet <strong>kan inte hitta någon partitionstabell</strong> på den valda lagringsenheten.<br><br>Antingen har enheten ingen partitionstabell, eller så är partitionstabellen trasig eller av okänd typ.<br>Installationsprogrammet kan skapa en ny partitionstabell åt dig, antingen automatiskt, eller genom sidan för manuell partitionering. @@ -1085,7 +1085,7 @@ Alla ändringar kommer att gå förlorade. <br><br>This partition table type is only advisable on older systems which start from a <strong>BIOS</strong> boot environment. GPT is recommended in most other cases.<br><br><strong>Warning:</strong> the MBR partition table is an obsolete MS-DOS era standard.<br>Only 4 <em>primary</em> partitions may be created, and of those 4, one can be an <em>extended</em> partition, which may in turn contain many <em>logical</em> partitions. - + <br><br>Denna partitionstabell är endast lämplig på äldre system som startar från en <strong>BIOS</strong>-startmiljö. GPT rekommenderas i de flesta andra fall.<br><br><strong>Varning:</strong> MBR-partitionstabellen är en föråldrad standard från MS-DOS-tiden.<br>Endast 4 <em>primära</em> partitioner kan skapas, och av dessa 4 kan en vara en <em>utökad</em> partition, som i sin tur kan innehålla många <em>logiska</em> partitioner. @@ -1278,7 +1278,7 @@ Alla ändringar kommer att gå förlorade. <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> - + <html><head/><body><p>När denna ruta är ikryssad kommer systemet starta om omedelbart när du klickar på <span style="font-style:italic;">Klar</span> eller stänger installationsprogrammet.</p></body></html> @@ -1288,7 +1288,7 @@ Alla ändringar kommer att gå förlorade. <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> - + <html><head/><body><p>När denna ruta är ikryssad kommer systemet starta om omedelbart när du klickar på <span style="font-style:italic;">Klar</span> eller stänger installationsprogrammet.</p></body></html> @@ -1573,27 +1573,27 @@ Alla ändringar kommer att gå förlorade. Please review the End User License Agreements (EULAs). - + Vänligen läs igenom licensavtalen för slutanvändare (EULA). This setup procedure will install proprietary software that is subject to licensing terms. - + Denna installationsprocess kommer installera proprietär mjukvara för vilken särskilda licensvillkor gäller. If you do not agree with the terms, the setup procedure cannot continue. - + Om du inte accepterar villkoren kan inte installationsproceduren fortsätta. This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. - + Denna installationsprocess kan installera proprietär mjukvara för vilken särskilda licensvillkor gäller, för att kunna erbjuda ytterligare funktionalitet och förbättra användarupplevelsen. If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. - + Om du inte godkänner villkoren kommer inte proprietär mjukvara att installeras, och alternativ med öppen källkod kommer användas istället. @@ -1690,7 +1690,7 @@ Alla ändringar kommer att gå förlorade. The numbers and dates locale will be set to %1. - + Systemspråket för siffror och datum kommer sättas till %1. @@ -1732,7 +1732,7 @@ Alla ändringar kommer att gå förlorade. Encrypted rootfs setup error - + Fel vid inställning av krypterat rootfs @@ -1946,7 +1946,7 @@ Alla ändringar kommer att gå förlorade. The password differs with case changes only - + Endast stora och små bokstäver skiljer lösenorden åt @@ -1961,7 +1961,7 @@ Alla ändringar kommer att gå förlorade. The password contains words from the real name of the user in some form - + Lösenordet innehåller ord från användarens namn i någon form @@ -2001,7 +2001,7 @@ Alla ändringar kommer att gå förlorade. The password contains less than %1 non-alphanumeric characters - + Lösenordet innehåller färre än %1 icke alfanumeriska tecken @@ -2021,22 +2021,22 @@ Alla ändringar kommer att gå förlorade. The password is just rotated old one - + Lösenordet är ett roterat gammalt lösenord The password contains less than %1 character classes - + Lösenordet innehåller färre än %1 teckenklasser The password does not contain enough character classes - + Lösenordet innehåller inte tillräckligt många teckenklasser The password contains more than %1 same characters consecutively - + Lösenordet innehåller fler än %1 likadana tecken i rad @@ -2046,22 +2046,22 @@ Alla ändringar kommer att gå förlorade. The password contains more than %1 characters of the same class consecutively - + Lösenordet innehåller fler än %1 tecken från samma klass i rad The password contains too many characters of the same class consecutively - + Lösenordet innehåller för många tecken från samma klass i rad The password contains monotonic sequence longer than %1 characters - + Lösenordet innehåller en monoton sekvens längre än %1 tecken The password contains too long of a monotonic character sequence - + Lösenordet innehåller en för lång monoton teckensekvens @@ -2071,22 +2071,22 @@ Alla ändringar kommer att gå förlorade. Cannot obtain random numbers from the RNG device - + Kan inte hämta slumptal från slumptalsgeneratorn Password generation failed - required entropy too low for settings - + Lösenordsgenerering misslyckades - för lite entropi tillgänglig för givna inställningar The password fails the dictionary check - %1 - + Lösenordet klarar inte ordlistekontrollen - %1 The password fails the dictionary check - + Lösenordet klarar inte ordlistekontrollen @@ -2184,7 +2184,7 @@ Alla ändringar kommer att gå förlorade. Please pick a product from the list. The selected product will be installed. - + Välj en produkt från listan. Den valda produkten kommer att installeras. @@ -2294,7 +2294,7 @@ Alla ändringar kommer att gå förlorade. When this box is checked, password-strength checking is done and you will not be able to use a weak password. - + När den här rutan är förkryssad kommer kontroll av lösenordsstyrka att genomföras, och du kommer inte kunna använda ett svagt lösenord. @@ -2477,7 +2477,7 @@ Alla ändringar kommer att gå förlorade. The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. - + Partitionstabellen på %1 har redan %2 primära partitioner och inga fler kan läggas till. Var god ta bort en primär partition och lägg till en utökad partition istället. @@ -2555,12 +2555,12 @@ Alla ändringar kommer att gå förlorade. An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. - + En EFI-systempartition krävs för att starta %1. <br/><br/> För att konfigurera en EFI-systempartition, gå tillbaka och välj eller skapa ett FAT32-filsystem med <strong>%3</strong>-flaggan satt och monteringspunkt <strong>%2</strong>. <br/><br/>Du kan fortsätta utan att ställa in en EFI-systempartition, men ditt system kanske misslyckas med att starta. An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. - + En EFI-systempartition krävs för att starta %1. <br/><br/>En partition är konfigurerad med monteringspunkt <strong>%2</strong>, men dess <strong>%3</strong>-flagga är inte satt.<br/>För att sätta flaggan, gå tillbaka och redigera partitionen.<br/><br/>Du kan fortsätta utan att sätta flaggan, men ditt system kanske misslyckas med att starta @@ -2575,7 +2575,7 @@ Alla ändringar kommer att gå förlorade. A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. - + En GPT-partitionstabell är det bästa alternativet för alla system. Detta installationsprogram stödjer det för system med BIOS också.<br/><br/>För att konfigurera en GPT-partitionstabell på BIOS (om det inte redan är gjort), gå tillbaka och sätt partitionstabell till GPT, skapa sedan en oformaterad partition på 8MB med <strong>bios_grub</strong>-flaggan satt.<br/><br/>En oformaterad partition på 8MB är nödvändig för att starta %1 på ett BIOS-system med GPT. @@ -2585,12 +2585,12 @@ Alla ändringar kommer att gå förlorade. A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. - + En separat uppstartspartition skapades tillsammans med den krypterade rootpartitionen, men uppstartspartitionen är inte krypterad.<br/><br/>Det finns säkerhetsproblem med den här inställningen, eftersom viktiga systemfiler sparas på en okrypterad partition.<br/>Du kan fortsätta om du vill, men upplåsning av filsystemet kommer hända senare under uppstart av systemet.<br/>För att kryptera uppstartspartitionen, gå tillbaka och återskapa den, och välj <strong>Kryptera</strong> i fönstret när du skapar partitionen. has at least one disk device available. - + har åtminstone en diskenhet tillgänglig. @@ -2603,13 +2603,13 @@ Alla ändringar kommer att gå förlorade. Plasma Look-and-Feel Job - + Jobb för Plasmas utseende och känsla Could not select KDE Plasma Look-and-Feel package - + Kunde inte välja KDE Plasma-paket för utseende och känsla @@ -2622,12 +2622,12 @@ Alla ändringar kommer att gå förlorade. Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is set up. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. - + Var god välj ett utseende och känsla för KDE Plasma skrivbordet. Du kan hoppa över detta steget och ställa in utseende och känsla när systemet är installerat. Klicka på ett val för utseende och känsla för att få en förhandsgranskning av det valet. Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. - + Var god välj ett utseende och känsla för KDE Plasma skrivbordet. Du kan hoppa över detta steget och ställa in utseende och känsla när systemet är installerat. Klicka på ett val för utseende och känsla för att få en förhandsgranskning av det valet. @@ -2635,7 +2635,7 @@ Alla ändringar kommer att gå förlorade. Look-and-Feel - + Utseende och känsla @@ -2735,7 +2735,7 @@ Utdata: Requirements checking for module <i>%1</i> is complete. - + Kontroll av krav för modul <i>%1</i> är färdig. @@ -2779,7 +2779,7 @@ Utdata: Path <pre>%1</pre> must be an absolute path. - + Sökväg <pre>%1</pre> måste vara en absolut sökväg. @@ -2889,7 +2889,7 @@ Utdata: <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. - + <strong>%2</strong><br/><br/>Kan inte hitta en EFI-systempartition någonstans på detta system. Var god gå tillbaka och använd manuell partitionering för att installera %1. @@ -2914,7 +2914,7 @@ Utdata: Resize Filesystem Job - + Jobb för storleksförändring av filsystem @@ -2924,7 +2924,7 @@ Utdata: The file-system resize job has an invalid configuration and will not run. - + Jobbet för storleksförändring av filsystem har en felaktig konfiguration och kommer inte köras. @@ -2934,7 +2934,7 @@ Utdata: Calamares cannot start KPMCore for the file-system resize job. - + Calamares kan inte starta KPMCore för jobbet att ändra filsystemsstorlek. @@ -2948,34 +2948,34 @@ Utdata: The filesystem %1 could not be found in this system, and cannot be resized. - + Kunde inte hitta filsystemet %1 på systemet, och kan inte ändra storlek på det. The device %1 could not be found in this system, and cannot be resized. - + Kunde inte hitta enheten %1 på systemet, och kan inte ändra storlek på den. The filesystem %1 cannot be resized. - + Det går inte att ändra storlek på filsystemet %1. The device %1 cannot be resized. - + Det går inte att ändra storlek på enheten %1. The filesystem %1 must be resized, but cannot. - + Filsystemet %1 måste ändra storlek, men storleken kan inte ändras. The device %1 must be resized, but cannot - + Enheten %1 måste ändra storlek, men storleken kan inte ändras @@ -3015,7 +3015,7 @@ Utdata: Resize volume group named %1 from %2 to %3. - + Ändra storlek på volymgruppen som heter %1 från %2 till %3. @@ -3311,7 +3311,7 @@ Utdata: Shell Processes Job - + Jobb för skalprocesser @@ -3328,7 +3328,7 @@ Utdata: This is an overview of what will happen once you start the setup procedure. - + Detta är en översikt över vad som kommer hända när du startar installationsprocessen. @@ -3364,7 +3364,7 @@ Utdata: HTTP request timed out. - + HTTP-begäran tog för lång tid. @@ -3411,7 +3411,7 @@ Utdata: <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> - + <html><head/><body><p>Genom att välja detta, kommer du inte skicka <span style=" font-weight:600;">någon information alls</span> om din installation.</p></body></html> @@ -3426,7 +3426,7 @@ Utdata: By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. - + Genom att välja detta, kommer du skicka information om din installation och hårdvara. Denna information kommer <b>enbart skickas en gång</b> efter att installationen slutförts. @@ -3541,7 +3541,7 @@ Utdata: Physical Extent Size: - + Storlek på fysisk volymdel (PE): @@ -3566,7 +3566,7 @@ Utdata: Quantity of LVs: - + Antal LV: @@ -3665,7 +3665,7 @@ Utdata: <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. - + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Tack till <a href="https://calamares.io/team/">Calamares-teamet</a> och <a href="https://www.transifex.com/calamares/calamares/">Calamares översättar-team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> utveckling sponsras av <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. @@ -3700,7 +3700,18 @@ Utdata: development is sponsored by <br/> <a href='http://www.blue-systems.com/'>Blue Systems</a> - Liberating Software. - + <h1>%1</h1><br/> + <strong>%2<br/> + for %3</strong><br/><br/> + Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + Tack till <a href='https://calamares.io/team/'>Calamares-teamet</a> + och <a href='https://www.transifex.com/calamares/calamares/'>Calamares + översättar-team</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + utveckling sponsras av <br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. @@ -3718,7 +3729,7 @@ Utdata: Pick your preferred keyboard model or use the default one based on the detected hardware - + Välj din föredragna tangentbordsmodell, eller använd ett förval baserat på vilken hårdvara vi känt av @@ -3788,7 +3799,27 @@ Utdata: </ul> <p>The vertical scrollbar is adjustable, current width set to 10.</p> - + <h3>%1</h3> + <p>Detta är en exempelfil för QML, som visar inställningar för RichText och innehåll som är Flickable.</p> + + <p>QML med RichText kan använda HTML-taggar. Innehåll som är Flickable är användbart på pekskärmar.</p> + + <p><b>Detta är fet text</b></p> + <p><i>Detta är kursiv text</i></p> + <p>Detta är understruken text</p> + <p><center>Denna text är centrerad.</center></p> + <p><s>Detta är överstruket</s></p> + + <p>Kodexample: + <code>ls -l /home</code></p> + + <p><b>Listor:</b></p> + <ul> + <li>System med Intel-processor</li> + <li>System med AMD-processor</li> + </ul> + + <p>Den vertikala rullningslisten är justerbar, nuvarande bredd är satt till 10.</p> @@ -3802,7 +3833,8 @@ Utdata: <h3>Welcome to the %1 <quote>%2</quote> installer</h3> <p>This program will ask you some questions and set up %1 on your computer.</p> - + <h3>Välkommen till %2 installationsprogram för <quote>%1</quote></h3> + <p>Detta program kommer ställa några frågor och installera %1 på din dator.</p> From ba89b9f7f208a4e3b9032b28e73e73aae448dde4 Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Fri, 12 Jun 2020 14:36:48 +0200 Subject: [PATCH 058/105] i18n: [dummypythonqt] Automatic merge of Transifex translations --- .../lang/bn/LC_MESSAGES/dummypythonqt.mo | Bin 0 -> 380 bytes .../lang/bn/LC_MESSAGES/dummypythonqt.po | 42 ++++++++++++++++++ .../lang/lv/LC_MESSAGES/dummypythonqt.mo | Bin 0 -> 415 bytes .../lang/lv/LC_MESSAGES/dummypythonqt.po | 42 ++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.mo create mode 100644 src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.po create mode 100644 src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.mo create mode 100644 src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po diff --git a/src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.mo b/src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.mo new file mode 100644 index 0000000000000000000000000000000000000000..a8045f8df34f2820ee38ebc6aed4560395b9f24d GIT binary patch literal 380 zcmYL@!A`d~`@G4TM=WxG9)x}*odVu&IQR_;p~%9?h!*ui!xIEsD~HOF{HyU193C8PDk0SXimfmfUGkn!NPN0$Uv1EkR26zHRmmY, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"PO-Revision-Date: 2016-12-16 12:18+0000\n" +"Language-Team: Bengali (https://www.transifex.com/calamares/teams/20061/bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/modules/dummypythonqt/main.py:84 +msgid "Click me!" +msgstr "" + +#: src/modules/dummypythonqt/main.py:94 +msgid "A new QLabel." +msgstr "" + +#: src/modules/dummypythonqt/main.py:97 +msgid "Dummy PythonQt ViewStep" +msgstr "" + +#: src/modules/dummypythonqt/main.py:183 +msgid "The Dummy PythonQt Job" +msgstr "" + +#: src/modules/dummypythonqt/main.py:186 +msgid "This is the Dummy PythonQt Job. The dummy job says: {}" +msgstr "" + +#: src/modules/dummypythonqt/main.py:190 +msgid "A status message for Dummy PythonQt Job." +msgstr "" diff --git a/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.mo b/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.mo new file mode 100644 index 0000000000000000000000000000000000000000..cdb444be01e74d2c19a8a37d66317e71e93d73cc GIT binary patch literal 415 zcmYL@QBT4!6ooPRv`3$PxFkv-TH4Np%#wv54nqW4aPnS988xF@+A{Em`1kxRcACIR zzVzJm+}!hXdGXzFI&)k(t{vx&J4da+A>8MKd+W?mu`WJEYSCncmO>j@CPmmCi7QsA<9BqG&7l8p~qcjP*O1P;yGG~O4d8*iCe+IC$xvCk7y65&uDNASu0FLE8bvBCR#IgQf)8nr zH5ufU7w0?8b2KjW)-X`z-)O@7KK$FTt!^j@Lkg`H)Rr_uN?`y5TpXIAGXtP*@H>64 F@e2W)aufgn literal 0 HcmV?d00001 diff --git a/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po new file mode 100644 index 000000000..651fe2fa4 --- /dev/null +++ b/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po @@ -0,0 +1,42 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"PO-Revision-Date: 2016-12-16 12:18+0000\n" +"Language-Team: Latvian (https://www.transifex.com/calamares/teams/20061/lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" + +#: src/modules/dummypythonqt/main.py:84 +msgid "Click me!" +msgstr "" + +#: src/modules/dummypythonqt/main.py:94 +msgid "A new QLabel." +msgstr "" + +#: src/modules/dummypythonqt/main.py:97 +msgid "Dummy PythonQt ViewStep" +msgstr "" + +#: src/modules/dummypythonqt/main.py:183 +msgid "The Dummy PythonQt Job" +msgstr "" + +#: src/modules/dummypythonqt/main.py:186 +msgid "This is the Dummy PythonQt Job. The dummy job says: {}" +msgstr "" + +#: src/modules/dummypythonqt/main.py:190 +msgid "A status message for Dummy PythonQt Job." +msgstr "" From e34c0576e745178c5e85359a04fac7666699dd7a Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Fri, 12 Jun 2020 14:36:48 +0200 Subject: [PATCH 059/105] i18n: [python] Automatic merge of Transifex translations --- lang/python/bn/LC_MESSAGES/python.mo | Bin 0 -> 380 bytes lang/python/bn/LC_MESSAGES/python.po | 336 ++++++++++++++++++++++++++ lang/python/hu/LC_MESSAGES/python.po | 2 +- lang/python/lv/LC_MESSAGES/python.mo | Bin 0 -> 415 bytes lang/python/lv/LC_MESSAGES/python.po | 338 +++++++++++++++++++++++++++ lang/python/sv/LC_MESSAGES/python.mo | Bin 5899 -> 7891 bytes lang/python/sv/LC_MESSAGES/python.po | 31 ++- 7 files changed, 696 insertions(+), 11 deletions(-) create mode 100644 lang/python/bn/LC_MESSAGES/python.mo create mode 100644 lang/python/bn/LC_MESSAGES/python.po create mode 100644 lang/python/lv/LC_MESSAGES/python.mo create mode 100644 lang/python/lv/LC_MESSAGES/python.po diff --git a/lang/python/bn/LC_MESSAGES/python.mo b/lang/python/bn/LC_MESSAGES/python.mo new file mode 100644 index 0000000000000000000000000000000000000000..b067dcf7187f1142e0012d7560c7ca481e0009bb GIT binary patch literal 380 zcmYL@!A=4(5QZ^&>d~`@G4TM=Zo6o7DcJ+yVu&IeT)CH}EH%6BrY(XG;_LY=b~S-N z`7$$^`7{5|`Pp~N>%?>6x$>NPZaj@5&(JS>zBV@prAB{<+~LUzFNCpDD+cLc^gMV< zV3Ew~_1r8Lq5ci+zymisZcH6*s~X=Pj0WDZLNLQjrdt zPNvB*X&6v6(#i?taQ0RE2u|!BsY@?0e0DIAOHXW literal 0 HcmV?d00001 diff --git a/lang/python/bn/LC_MESSAGES/python.po b/lang/python/bn/LC_MESSAGES/python.po new file mode 100644 index 000000000..c0feed0ec --- /dev/null +++ b/lang/python/bn/LC_MESSAGES/python.po @@ -0,0 +1,336 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"PO-Revision-Date: 2017-08-09 10:34+0000\n" +"Language-Team: Bengali (https://www.transifex.com/calamares/teams/20061/bn/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/modules/packages/main.py:59 src/modules/packages/main.py:68 +#: src/modules/packages/main.py:78 +msgid "Install packages." +msgstr "" + +#: src/modules/packages/main.py:66 +#, python-format +msgid "Processing packages (%(count)d / %(total)d)" +msgstr "" + +#: src/modules/packages/main.py:71 +#, python-format +msgid "Installing one package." +msgid_plural "Installing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/packages/main.py:74 +#, python-format +msgid "Removing one package." +msgid_plural "Removing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/networkcfg/main.py:37 +msgid "Saving network configuration." +msgstr "" + +#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205 +#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144 +#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95 +#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332 +#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94 +#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171 +msgid "Configuration Error" +msgstr "" + +#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210 +#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145 +#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339 +#: src/modules/initramfscfg/main.py:99 +msgid "No root mount point is given for

{!s}
to use." +msgstr "" + +#: src/modules/umount/main.py:40 +msgid "Unmount file systems." +msgstr "" + +#: src/modules/initcpiocfg/main.py:37 +msgid "Configuring mkinitcpio." +msgstr "" + +#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79 +#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96 +#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95 +#: src/modules/rawfs/main.py:172 +msgid "No partitions are defined for
{!s}
to use." +msgstr "" + +#: src/modules/openrcdmcryptcfg/main.py:34 +msgid "Configuring OpenRC dmcrypt service." +msgstr "" + +#: src/modules/unpackfs/main.py:44 +msgid "Filling up filesystems." +msgstr "" + +#: src/modules/unpackfs/main.py:257 +msgid "rsync failed with error code {}." +msgstr "" + +#: src/modules/unpackfs/main.py:302 +msgid "Unpacking image {}/{}, file {}/{}" +msgstr "" + +#: src/modules/unpackfs/main.py:317 +msgid "Starting to unpack {}" +msgstr "" + +#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432 +msgid "Failed to unpack image \"{}\"" +msgstr "" + +#: src/modules/unpackfs/main.py:399 +msgid "No mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:400 +msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:405 +msgid "Bad mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:406 +msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426 +#: src/modules/unpackfs/main.py:446 +msgid "Bad unsquash configuration" +msgstr "" + +#: src/modules/unpackfs/main.py:423 +msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" +msgstr "" + +#: src/modules/unpackfs/main.py:427 +msgid "The source filesystem \"{}\" does not exist" +msgstr "" + +#: src/modules/unpackfs/main.py:433 +msgid "" +"Failed to find unsquashfs, make sure you have the squashfs-tools package " +"installed" +msgstr "" + +#: src/modules/unpackfs/main.py:447 +msgid "The destination \"{}\" in the target system is not a directory" +msgstr "" + +#: src/modules/services-systemd/main.py:35 +msgid "Configure systemd services" +msgstr "" + +#: src/modules/services-systemd/main.py:68 +#: src/modules/services-openrc/main.py:102 +msgid "Cannot modify service" +msgstr "" + +#: src/modules/services-systemd/main.py:69 +msgid "" +"systemctl {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:72 +#: src/modules/services-systemd/main.py:76 +msgid "Cannot enable systemd service {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:74 +msgid "Cannot enable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:78 +msgid "Cannot disable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:80 +msgid "Cannot mask systemd unit {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:82 +msgid "" +"Unknown systemd commands {command!s} and " +"{suffix!s} for unit {name!s}." +msgstr "" + +#: src/modules/dummypython/main.py:44 +msgid "Dummy python job." +msgstr "" + +#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102 +#: src/modules/dummypython/main.py:103 +msgid "Dummy python step {}" +msgstr "" + +#: src/modules/bootloader/main.py:51 +msgid "Install bootloader." +msgstr "" + +#: src/modules/localecfg/main.py:39 +msgid "Configuring locales." +msgstr "" + +#: src/modules/mount/main.py:38 +msgid "Mounting partitions." +msgstr "" + +#: src/modules/plymouthcfg/main.py:36 +msgid "Configure Plymouth theme" +msgstr "" + +#: src/modules/luksopenswaphookcfg/main.py:35 +msgid "Configuring encrypted swap." +msgstr "" + +#: src/modules/fstab/main.py:38 +msgid "Writing fstab." +msgstr "" + +#: src/modules/services-openrc/main.py:38 +msgid "Configure OpenRC services" +msgstr "" + +#: src/modules/services-openrc/main.py:66 +msgid "Cannot add service {name!s} to run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:68 +msgid "Cannot remove service {name!s} from run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:70 +msgid "" +"Unknown service-action {arg!s} for service {name!s} in run-" +"level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:103 +msgid "" +"rc-update {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:110 +msgid "Target runlevel does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:111 +msgid "" +"The path for runlevel {level!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/services-openrc/main.py:119 +msgid "Target service does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:120 +msgid "" +"The path for service {name!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/dracut/main.py:36 +msgid "Creating initramfs with dracut." +msgstr "" + +#: src/modules/dracut/main.py:58 +msgid "Failed to run dracut on the target" +msgstr "" + +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "" + +#: src/modules/grubcfg/main.py:37 +msgid "Configure GRUB." +msgstr "" + +#: src/modules/displaymanager/main.py:515 +msgid "Cannot write KDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:516 +msgid "KDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:577 +msgid "Cannot write LXDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:578 +msgid "LXDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:661 +msgid "Cannot write LightDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:662 +msgid "LightDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:736 +msgid "Cannot configure LightDM" +msgstr "" + +#: src/modules/displaymanager/main.py:737 +msgid "No LightDM greeter installed." +msgstr "" + +#: src/modules/displaymanager/main.py:768 +msgid "Cannot write SLIM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:769 +msgid "SLIM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:895 +msgid "No display managers selected for the displaymanager module." +msgstr "" + +#: src/modules/displaymanager/main.py:896 +msgid "" +"The displaymanagers list is empty or undefined in bothglobalstorage and " +"displaymanager.conf." +msgstr "" + +#: src/modules/displaymanager/main.py:978 +msgid "Display manager configuration was incomplete" +msgstr "" + +#: src/modules/initramfscfg/main.py:41 +msgid "Configuring initramfs." +msgstr "" + +#: src/modules/hwclock/main.py:35 +msgid "Setting hardware clock." +msgstr "" + +#: src/modules/rawfs/main.py:35 +msgid "Installing data." +msgstr "" diff --git a/lang/python/hu/LC_MESSAGES/python.po b/lang/python/hu/LC_MESSAGES/python.po index 3fe19a8ec..eece1030a 100644 --- a/lang/python/hu/LC_MESSAGES/python.po +++ b/lang/python/hu/LC_MESSAGES/python.po @@ -5,7 +5,7 @@ # # Translators: # Adriaan de Groot , 2018 -# Balázs Meskó , 2018 +# Balázs Meskó , 2018 # miku84, 2019 # Lajos Pasztor , 2019 # diff --git a/lang/python/lv/LC_MESSAGES/python.mo b/lang/python/lv/LC_MESSAGES/python.mo new file mode 100644 index 0000000000000000000000000000000000000000..f6651cf375a665bdc32888dbe73cb0784d499e9a GIT binary patch literal 415 zcmYL@QBT4!6oobVv`3$PxFkv-TH1oqQL+%kVTd3LPTuP%V`j8VTL%6R|DM0aP7^rE zm!6xRn|ppP&c9EbP92wyE617R)=|lK2>01_Z=m~dNWTtZ`QZDAP3yWOs3HJ2t^iG3?k8=UZ*Z@3l)Teo6xn~-~o^Ab0` z>3A9*o6;8XhDur?EsDPiSHX(C#YN6D*@I-wwGlRWk4MNq=BiUGp;0IkwajG7!2ihX zp(ca8^rC#Ld5%U(Zwv!j{Ea5)^x)qH4S7vT5KySsp|YeFPzrq@;NnmVoaqB~L%Z4Y GPJRIf0&*At literal 0 HcmV?d00001 diff --git a/lang/python/lv/LC_MESSAGES/python.po b/lang/python/lv/LC_MESSAGES/python.po new file mode 100644 index 000000000..50d7ca7e4 --- /dev/null +++ b/lang/python/lv/LC_MESSAGES/python.po @@ -0,0 +1,338 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"PO-Revision-Date: 2017-08-09 10:34+0000\n" +"Language-Team: Latvian (https://www.transifex.com/calamares/teams/20061/lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" + +#: src/modules/packages/main.py:59 src/modules/packages/main.py:68 +#: src/modules/packages/main.py:78 +msgid "Install packages." +msgstr "" + +#: src/modules/packages/main.py:66 +#, python-format +msgid "Processing packages (%(count)d / %(total)d)" +msgstr "" + +#: src/modules/packages/main.py:71 +#, python-format +msgid "Installing one package." +msgid_plural "Installing %(num)d packages." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: src/modules/packages/main.py:74 +#, python-format +msgid "Removing one package." +msgid_plural "Removing %(num)d packages." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: src/modules/networkcfg/main.py:37 +msgid "Saving network configuration." +msgstr "" + +#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205 +#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144 +#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95 +#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332 +#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94 +#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171 +msgid "Configuration Error" +msgstr "" + +#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210 +#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145 +#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339 +#: src/modules/initramfscfg/main.py:99 +msgid "No root mount point is given for
{!s}
to use." +msgstr "" + +#: src/modules/umount/main.py:40 +msgid "Unmount file systems." +msgstr "" + +#: src/modules/initcpiocfg/main.py:37 +msgid "Configuring mkinitcpio." +msgstr "" + +#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79 +#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96 +#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95 +#: src/modules/rawfs/main.py:172 +msgid "No partitions are defined for
{!s}
to use." +msgstr "" + +#: src/modules/openrcdmcryptcfg/main.py:34 +msgid "Configuring OpenRC dmcrypt service." +msgstr "" + +#: src/modules/unpackfs/main.py:44 +msgid "Filling up filesystems." +msgstr "" + +#: src/modules/unpackfs/main.py:257 +msgid "rsync failed with error code {}." +msgstr "" + +#: src/modules/unpackfs/main.py:302 +msgid "Unpacking image {}/{}, file {}/{}" +msgstr "" + +#: src/modules/unpackfs/main.py:317 +msgid "Starting to unpack {}" +msgstr "" + +#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432 +msgid "Failed to unpack image \"{}\"" +msgstr "" + +#: src/modules/unpackfs/main.py:399 +msgid "No mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:400 +msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:405 +msgid "Bad mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:406 +msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426 +#: src/modules/unpackfs/main.py:446 +msgid "Bad unsquash configuration" +msgstr "" + +#: src/modules/unpackfs/main.py:423 +msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" +msgstr "" + +#: src/modules/unpackfs/main.py:427 +msgid "The source filesystem \"{}\" does not exist" +msgstr "" + +#: src/modules/unpackfs/main.py:433 +msgid "" +"Failed to find unsquashfs, make sure you have the squashfs-tools package " +"installed" +msgstr "" + +#: src/modules/unpackfs/main.py:447 +msgid "The destination \"{}\" in the target system is not a directory" +msgstr "" + +#: src/modules/services-systemd/main.py:35 +msgid "Configure systemd services" +msgstr "" + +#: src/modules/services-systemd/main.py:68 +#: src/modules/services-openrc/main.py:102 +msgid "Cannot modify service" +msgstr "" + +#: src/modules/services-systemd/main.py:69 +msgid "" +"systemctl {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:72 +#: src/modules/services-systemd/main.py:76 +msgid "Cannot enable systemd service {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:74 +msgid "Cannot enable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:78 +msgid "Cannot disable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:80 +msgid "Cannot mask systemd unit {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:82 +msgid "" +"Unknown systemd commands {command!s} and " +"{suffix!s} for unit {name!s}." +msgstr "" + +#: src/modules/dummypython/main.py:44 +msgid "Dummy python job." +msgstr "" + +#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102 +#: src/modules/dummypython/main.py:103 +msgid "Dummy python step {}" +msgstr "" + +#: src/modules/bootloader/main.py:51 +msgid "Install bootloader." +msgstr "" + +#: src/modules/localecfg/main.py:39 +msgid "Configuring locales." +msgstr "" + +#: src/modules/mount/main.py:38 +msgid "Mounting partitions." +msgstr "" + +#: src/modules/plymouthcfg/main.py:36 +msgid "Configure Plymouth theme" +msgstr "" + +#: src/modules/luksopenswaphookcfg/main.py:35 +msgid "Configuring encrypted swap." +msgstr "" + +#: src/modules/fstab/main.py:38 +msgid "Writing fstab." +msgstr "" + +#: src/modules/services-openrc/main.py:38 +msgid "Configure OpenRC services" +msgstr "" + +#: src/modules/services-openrc/main.py:66 +msgid "Cannot add service {name!s} to run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:68 +msgid "Cannot remove service {name!s} from run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:70 +msgid "" +"Unknown service-action {arg!s} for service {name!s} in run-" +"level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:103 +msgid "" +"rc-update {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:110 +msgid "Target runlevel does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:111 +msgid "" +"The path for runlevel {level!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/services-openrc/main.py:119 +msgid "Target service does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:120 +msgid "" +"The path for service {name!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/dracut/main.py:36 +msgid "Creating initramfs with dracut." +msgstr "" + +#: src/modules/dracut/main.py:58 +msgid "Failed to run dracut on the target" +msgstr "" + +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "" + +#: src/modules/grubcfg/main.py:37 +msgid "Configure GRUB." +msgstr "" + +#: src/modules/displaymanager/main.py:515 +msgid "Cannot write KDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:516 +msgid "KDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:577 +msgid "Cannot write LXDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:578 +msgid "LXDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:661 +msgid "Cannot write LightDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:662 +msgid "LightDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:736 +msgid "Cannot configure LightDM" +msgstr "" + +#: src/modules/displaymanager/main.py:737 +msgid "No LightDM greeter installed." +msgstr "" + +#: src/modules/displaymanager/main.py:768 +msgid "Cannot write SLIM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:769 +msgid "SLIM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:895 +msgid "No display managers selected for the displaymanager module." +msgstr "" + +#: src/modules/displaymanager/main.py:896 +msgid "" +"The displaymanagers list is empty or undefined in bothglobalstorage and " +"displaymanager.conf." +msgstr "" + +#: src/modules/displaymanager/main.py:978 +msgid "Display manager configuration was incomplete" +msgstr "" + +#: src/modules/initramfscfg/main.py:41 +msgid "Configuring initramfs." +msgstr "" + +#: src/modules/hwclock/main.py:35 +msgid "Setting hardware clock." +msgstr "" + +#: src/modules/rawfs/main.py:35 +msgid "Installing data." +msgstr "" diff --git a/lang/python/sv/LC_MESSAGES/python.mo b/lang/python/sv/LC_MESSAGES/python.mo index e903d55a925630030f02844ab74caef4486b65ba..20667a99cb68885e8344edcfc7e137421b6ddfda 100644 GIT binary patch delta 3198 zcmbW1TWl0n7{|{RYAv*da;YG;JrqGMEw_RoEl{w43Z;f%Ach#HyVKoacW3I%Y@t@N zPiVZM$wcu1Fp)MyA4sH$2@fSC8;$xRiIE3QNQfbj5Tk^|gy@66Z)UfYQe)ytPk(b} z&-pI@^L_K~${#o9ug#kJkz(v(KEd2yrj!BSo60}N%tw@Z0oE3I2sW`k2Oo#u!&Z0$ z&V%zSlv)SZ7MX6O664@4~tlL!zZB!pMswh*O%dJ);Hh`cn{8p zm6eghMNk51hhpadTmT1Q9Xtu=!1M4iSb&Z27ubw{^%oDdyjVId+PDesW8DoU)6bw7 z{2GdZ>reu^2jyJ#bX0W)B@h!zLT^J!=sc7_uEKhF8@AzJRaPmr5bl8MVG<&Z zIt^FAt8g_etBwq|LNRaY($nfVoG(uy{t!PMfR(ZZ8__g zp(Jp8Hu`Vl;VdsC@*8j~oQh7HU?1YEE`f4>Ba|9?sSf=m5{DOZSML`$T!13&4^T3`38lI#c_{{(pairP60`CkThv=n zYUd0TCGWr`Z~=#jMQw*ttOub40#InN1-TKjhqMIT6hS)1Gz1A6H4HJL#drcob1BCTFJvEUi3qe`b!vtWz2S_ zj4jM{OwNWwG8Or!M$57Pnx~CS3O-Dt5mqq8VQH-AL268ViT`lO9X-tysbxr2i+rWA zk_WC*RWi3R+n6G!j2#ie>?w3bw}wNm^BJb7OQzuvC8iah586z0#>g~cG1 zELFLg8IJb2lQ6fq@s?a)!thN!Xt>FR-m&&o;d>o7G8t{zI-YVJ$Jegu=Um%NXw!8a zSIZtfXy>w=Sg9gY-hk(u*|?u6ncDDwY;89Z!QM(8RFyY18;OMWOt;^Pi!&o@;!XRG zc5`-1#_Tuo6heXsmXu$fX?STJg^|!X+wz0oYvu*l%Inv-X4dI9A2!zOI@w9hjod9i zA6sF0eHmjwXARp(nv%8MYbA58;aiTaj~E^T#hq+l#`MkL(~7mv^;)(#_Fl^wUaHq? z=42YLIoH$!PEMx`V(?SEDQ;--9Vg@IJ|mvS0oFVp+0DerHx*s6`FpHn%J1ybN!P@I zJMQP2$}_Px?#tw2a&{y|!ZAH88PBP0jj9%8IA%8w~|`@N6s@T&nuGVZYO3 zackWfBji>@pu_p9}YtR$DW+v?WaffbYIb)RHkClbW(q^eq!EScA1(}0Jf=OaPb7tO;Vaj+`U}J3JLO!> z&rg($WN8`GH70gVU67yAuw{2?mv87E$My9jZhGCqusyk-*v$Hoi!-jqT6aItH@(E9 z6H#lW3^H*Im%#fCsql2vPJVErwt3&~oQ-)yEY%#)uo2<)1p(c^s8W-2N4`65A@PszAY}-r~hWVmM*hxg5 x*kvvDKs;?`nzcuXB;{gcpFgqF5Tn>?{ZtNNeXZP!xOz9?0t+HFy^$c6(!4??1mv{gk9wz9Ukuyqk>gD~mA zfr=u62v(v&(jzybiHL+CLj8+K+(`KT-oC_>Oh5DP?z}VeJTo0>?5j$?3a0lPVkxbd z_RcY;39pai4>6i<%uM`C}b-2p68*6#KiXnW3v+xI&;gk%0r2q^lC^Q5oFfyB{^~ z7^MXF+6pfdCkDW#V+ zU0DSmd5czm5lx5h|Ik9Xgi@baQAj~+B+Hb*3BHUSy`dfmaNN;t;nfP zUC)U+sl2>1&fwb#j*a9e?C<;mTN>zh*LTO-+;tuC*!GV2F1KNOXCl!VTh-pSv!kAV zTiiYke74O6>+Ji2=eDOX$Nnk|+S{SxRA=a!WA}wCQ{Te}oK)Y``;I+2?VEj6++|Nr KAF#JdX8r*mPnw

, 2020 +# Tobias Olausson , 2020 # #, fuzzy msgid "" @@ -14,7 +15,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-04-30 23:13+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Luna Jernberg , 2020\n" +"Last-Translator: Tobias Olausson , 2020\n" "Language-Team: Swedish (https://www.transifex.com/calamares/teams/20061/sv/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -113,7 +114,7 @@ msgstr "Ingen monteringspunkt för root partition" #: src/modules/unpackfs/main.py:400 msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" -msgstr "" +msgstr "globalstorage innehåller ingen \"rootMountPoint\"-nyckel, så gör inget" #: src/modules/unpackfs/main.py:405 msgid "Bad mount point for root partition" @@ -121,7 +122,7 @@ msgstr "Dålig monteringspunkt för root partition" #: src/modules/unpackfs/main.py:406 msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" -msgstr "" +msgstr "rootMountPoint är \"{}\", vilket inte finns, så gör inget" #: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426 #: src/modules/unpackfs/main.py:446 @@ -141,6 +142,8 @@ msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed" msgstr "" +"Kunde inte hitta unsquashfs, se till att du har paketet squashfs-tools " +"installerat" #: src/modules/unpackfs/main.py:447 msgid "The destination \"{}\" in the target system is not a directory" @@ -159,6 +162,8 @@ msgstr "Kunde inte modifiera tjänst" msgid "" "systemctl {arg!s} call in chroot returned error code {num!s}." msgstr "" +"Anrop till systemctl {arg!s}i chroot returnerade felkod " +"{num!s}." #: src/modules/services-systemd/main.py:72 #: src/modules/services-systemd/main.py:76 @@ -175,7 +180,7 @@ msgstr "Kunde inte inaktivera systemd målsystem {name!s}." #: src/modules/services-systemd/main.py:80 msgid "Cannot mask systemd unit {name!s}." -msgstr "" +msgstr "Kan inte maskera systemd unit {name!s}" #: src/modules/services-systemd/main.py:82 msgid "" @@ -224,36 +229,42 @@ msgstr "Konfigurera OpenRC tjänster" #: src/modules/services-openrc/main.py:66 msgid "Cannot add service {name!s} to run-level {level!s}." -msgstr "" +msgstr "Kan inte lägga till tjänsten {name!s} till körnivå {level!s}." #: src/modules/services-openrc/main.py:68 msgid "Cannot remove service {name!s} from run-level {level!s}." -msgstr "" +msgstr "Kan inte ta bort tjänsten {name!s} från körnivå {level!s}." #: src/modules/services-openrc/main.py:70 msgid "" "Unknown service-action {arg!s} for service {name!s} in run-" "level {level!s}." msgstr "" +"Okänt tjänst-anrop {arg!s}för tjänsten {name!s} i körnivå " +"{level!s}." #: src/modules/services-openrc/main.py:103 msgid "" "rc-update {arg!s} call in chroot returned error code {num!s}." msgstr "" +"Anrop till rc-update {arg!s} i chroot returnerade felkod " +"{num!s}." #: src/modules/services-openrc/main.py:110 msgid "Target runlevel does not exist" -msgstr "" +msgstr "Begärd körnivå existerar inte" #: src/modules/services-openrc/main.py:111 msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." msgstr "" +"Sökvägen till körnivå {level!s} är {path!s}, som inte " +"existerar." #: src/modules/services-openrc/main.py:119 msgid "Target service does not exist" -msgstr "" +msgstr "Begärd tjänst existerar inte" #: src/modules/services-openrc/main.py:120 msgid "" @@ -308,7 +319,7 @@ msgstr "Kunde inte konfigurera LightDM" #: src/modules/displaymanager/main.py:737 msgid "No LightDM greeter installed." -msgstr "" +msgstr "Ingen LightDM greeter installerad." #: src/modules/displaymanager/main.py:768 msgid "Cannot write SLIM configuration file" @@ -332,7 +343,7 @@ msgstr "" #: src/modules/displaymanager/main.py:978 msgid "Display manager configuration was incomplete" -msgstr "" +msgstr "Konfiguration för displayhanteraren var inkomplett" #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." From 713774ab4090717764021b822071158056cdcacc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 12 Jun 2020 14:50:12 +0200 Subject: [PATCH 060/105] i18n: adjust tooling to renamed resource --- .tx/config | 7 +------ ci/txpush.sh | 2 +- ci/txstats.py | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.tx/config b/.tx/config index 3cf9489f6..686a98bbe 100644 --- a/.tx/config +++ b/.tx/config @@ -1,17 +1,12 @@ [main] host = https://www.transifex.com -[calamares.calamares-master] +[calamares.calamares] file_filter = lang/calamares_.ts source_file = lang/calamares_en.ts source_lang = en type = QT -[calamares.dummypythonqt] -file_filter = src/modules/dummypythonqt/lang//LC_MESSAGES/dummypythonqt.po -source_file = src/modules/dummypythonqt/lang/dummypythonqt.pot -source_lang = en - [calamares.fdo] file_filter = lang/desktop_.desktop source_file = calamares.desktop diff --git a/ci/txpush.sh b/ci/txpush.sh index dc8c8c413..00d8d401b 100755 --- a/ci/txpush.sh +++ b/ci/txpush.sh @@ -101,7 +101,7 @@ if test -n "$XMLLINT" ; then $XMLLINT --c14n11 "$TS_FILE" | { echo "" ; cat - ; } | $XMLLINT --format --encode utf-8 -o "$TS_FILE".new - && mv "$TS_FILE".new "$TS_FILE" fi -tx push --source --no-interactive -r calamares.calamares-master +tx push --source --no-interactive -r calamares.calamares tx push --source --no-interactive -r calamares.fdo diff --git a/ci/txstats.py b/ci/txstats.py index e78a8ad9c..139ebe523 100755 --- a/ci/txstats.py +++ b/ci/txstats.py @@ -58,7 +58,7 @@ def get_tx_stats(token, verbose): """ import requests - r = requests.get("https://api.transifex.com/organizations/calamares/projects/calamares/resources/calamares-master/", auth=("api", token)) + r = requests.get("https://api.transifex.com/organizations/calamares/projects/calamares/resources/calamares/", auth=("api", token)) if r.status_code != 200: return 1 From 55abe0247bb7ece86277230c56488c0457a72317 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 14 Jun 2020 23:42:25 +0200 Subject: [PATCH 061/105] [libcalamares] Fix tests on 32-bit platforms - The size of a 2GiB partition (in bytes) is larger than the largest 32-bit signed integer; we hit signed overflow while calculating 2^11 * 2^10 * 2^10 and the test fails. - Switch the whole table of sizes to qint64 instead. - For testing purposes only, introduce a _qi suffix for qint64. FIXES #1430 --- src/libcalamares/partition/Tests.cpp | 53 ++++++++++++++++------------ 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/libcalamares/partition/Tests.cpp b/src/libcalamares/partition/Tests.cpp index 7719f2e84..e52b8edf1 100644 --- a/src/libcalamares/partition/Tests.cpp +++ b/src/libcalamares/partition/Tests.cpp @@ -1,5 +1,5 @@ /* === This file is part of Calamares - === - * + * * SPDX-FileCopyrightText: 2019 Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify @@ -103,36 +103,43 @@ PartitionSizeTests::testUnitComparison() QCOMPARE( original_compare( u1, u2 ), PartitionSize::unitsComparable( u1, u2 ) ); } +/* Operator to make the table in testUnitNormalisation_data easier to write */ +constexpr qint64 operator""_qi( unsigned long long m ) +{ + return qint64( m ); +} + void PartitionSizeTests::testUnitNormalisation_data() { QTest::addColumn< SizeUnit >( "u1" ); QTest::addColumn< int >( "v" ); - QTest::addColumn< long >( "bytes" ); + QTest::addColumn< qint64 >( "bytes" ); - QTest::newRow( "none" ) << SizeUnit::None << 16 << -1L; - QTest::newRow( "none" ) << SizeUnit::None << 0 << -1L; - QTest::newRow( "none" ) << SizeUnit::None << -2 << -1L; + QTest::newRow( "none" ) << SizeUnit::None << 16 << -1_qi; + QTest::newRow( "none" ) << SizeUnit::None << 0 << -1_qi; + QTest::newRow( "none" ) << SizeUnit::None << -2 << -1_qi; - QTest::newRow( "percent" ) << SizeUnit::Percent << 0 << -1L; - QTest::newRow( "percent" ) << SizeUnit::Percent << 16 << -1L; - QTest::newRow( "percent" ) << SizeUnit::Percent << -2 << -1L; + QTest::newRow( "percent" ) << SizeUnit::Percent << 0 << -1_qi; + QTest::newRow( "percent" ) << SizeUnit::Percent << 16 << -1_qi; + QTest::newRow( "percent" ) << SizeUnit::Percent << -2 << -1_qi; - QTest::newRow( "KiB" ) << SizeUnit::KiB << 0 << -1L; - QTest::newRow( "KiB" ) << SizeUnit::KiB << 1 << 1024L; - QTest::newRow( "KiB" ) << SizeUnit::KiB << 1000 << 1024000L; - QTest::newRow( "KiB" ) << SizeUnit::KiB << 1024 << 1024 * 1024L; - QTest::newRow( "KiB" ) << SizeUnit::KiB << -2 << -1L; + QTest::newRow( "KiB" ) << SizeUnit::KiB << 0 << -1_qi; + QTest::newRow( "KiB" ) << SizeUnit::KiB << 1 << 1024_qi; + QTest::newRow( "KiB" ) << SizeUnit::KiB << 1000 << 1024000_qi; + QTest::newRow( "KiB" ) << SizeUnit::KiB << 1024 << 1024 * 1024_qi; + QTest::newRow( "KiB" ) << SizeUnit::KiB << -2 << -1_qi; - QTest::newRow( "MiB" ) << SizeUnit::MiB << 0 << -1L; - QTest::newRow( "MiB" ) << SizeUnit::MiB << 1 << 1024 * 1024L; - QTest::newRow( "MiB" ) << SizeUnit::MiB << 1000 << 1024 * 1024000L; - QTest::newRow( "MiB" ) << SizeUnit::MiB << 1024 << 1024 * 1024 * 1024L; - QTest::newRow( "MiB" ) << SizeUnit::MiB << -2 << -1L; + QTest::newRow( "MiB" ) << SizeUnit::MiB << 0 << -1_qi; + QTest::newRow( "MiB" ) << SizeUnit::MiB << 1 << 1024 * 1024_qi; + QTest::newRow( "MiB" ) << SizeUnit::MiB << 1000 << 1024 * 1024000_qi; + QTest::newRow( "MiB" ) << SizeUnit::MiB << 1024 << 1024 * 1024 * 1024_qi; + QTest::newRow( "MiB" ) << SizeUnit::MiB << -2 << -1_qi; - QTest::newRow( "GiB" ) << SizeUnit::GiB << 0 << -1L; - QTest::newRow( "GiB" ) << SizeUnit::GiB << 1 << 1024 * 1024 * 1024L; - QTest::newRow( "GiB" ) << SizeUnit::GiB << 2 << 2048 * 1024 * 1024L; + QTest::newRow( "GiB" ) << SizeUnit::GiB << 0 << -1_qi; + QTest::newRow( "GiB" ) << SizeUnit::GiB << 1 << 1024_qi * 1024 * 1024_qi; + // This one overflows 32-bits, which is why we want 64-bits for the whole table + QTest::newRow( "GiB" ) << SizeUnit::GiB << 2 << 2048_qi * 1024 * 1024_qi; } void @@ -140,7 +147,7 @@ PartitionSizeTests::testUnitNormalisation() { QFETCH( SizeUnit, u1 ); QFETCH( int, v ); - QFETCH( long, bytes ); + QFETCH( qint64, bytes ); - QCOMPARE( PartitionSize( v, u1 ).toBytes(), static_cast< qint64 >( bytes ) ); + QCOMPARE( PartitionSize( v, u1 ).toBytes(), bytes ); } From fe8459b7f09107a745f00da85100af3c727d7ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Mon, 15 Jun 2020 12:33:26 +0200 Subject: [PATCH 062/105] [CMake] fix typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a209e2d0..269b2e9b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -595,7 +595,7 @@ install( if( INSTALL_CONFIG ) install( FILES settings.conf - DESTINATIONshare/calamares + DESTINATION share/calamares ) endif() From 19b48c3c8214a177aa757c314532b0f78a475740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Mon, 15 Jun 2020 12:35:52 +0200 Subject: [PATCH 063/105] [CMake] fix typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09e5c6d1d..ce3f42ac4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -588,7 +588,7 @@ install( if( INSTALL_CONFIG ) install( FILES settings.conf - DESTINATIONshare/calamares + DESTINATION share/calamares ) endif() From c1b5426c6630b34fb83a144984bf532a1b919d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 21 Mar 2020 14:21:16 -0400 Subject: [PATCH 064/105] [partition] Add support for partition attributes --- src/libcalamares/utils/Variant.cpp | 13 +++++++++++++ src/libcalamares/utils/Variant.h | 5 +++++ src/modules/partition/core/PartitionCoreModule.cpp | 1 + src/modules/partition/core/PartitionLayout.cpp | 10 ++++++++++ src/modules/partition/core/PartitionLayout.h | 2 ++ src/modules/partition/partition.conf | 2 ++ 6 files changed, 33 insertions(+) diff --git a/src/libcalamares/utils/Variant.cpp b/src/libcalamares/utils/Variant.cpp index cf6ff91fe..e0156c35e 100644 --- a/src/libcalamares/utils/Variant.cpp +++ b/src/libcalamares/utils/Variant.cpp @@ -85,6 +85,19 @@ getInteger( const QVariantMap& map, const QString& key, qint64 d ) return result; } +quint64 +getUnsignedInteger( const QVariantMap& map, const QString& key, quint64 u ) +{ + quint64 result = u; + if ( map.contains( key ) ) + { + auto v = map.value( key ); + result = v.toString().toULongLong(nullptr, 0); + } + + return result; +} + double getDouble( const QVariantMap& map, const QString& key, double d ) { diff --git a/src/libcalamares/utils/Variant.h b/src/libcalamares/utils/Variant.h index a05d281c3..8405f7659 100644 --- a/src/libcalamares/utils/Variant.h +++ b/src/libcalamares/utils/Variant.h @@ -48,6 +48,11 @@ DLLEXPORT QString getString( const QVariantMap& map, const QString& key ); */ DLLEXPORT qint64 getInteger( const QVariantMap& map, const QString& key, qint64 d ); +/** + * Get an unsigned integer value from a mapping; returns @p u if no value. + */ +DLLEXPORT quint64 getUnsignedInteger( const QVariantMap& map, const QString& key, quint64 u ); + /** * Get a double value from a mapping (integers are converted); returns @p d if no value. */ diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index aee1ab10f..5e0f8d363 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -884,6 +884,7 @@ PartitionCoreModule::initLayout( const QVariantList& config ) if ( !m_partLayout->addEntry( CalamaresUtils::getString( pentry, "name" ), CalamaresUtils::getString( pentry, "type" ), + CalamaresUtils::getUnsignedInteger( pentry, "attributes", 0 ), CalamaresUtils::getString( pentry, "mountPoint" ), CalamaresUtils::getString( pentry, "filesystem" ), CalamaresUtils::getSubMap( pentry, "features", ok ), diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 33d2a7679..2e573acd6 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -119,6 +119,7 @@ PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const bool PartitionLayout::addEntry( const QString& label, const QString& type, + quint64 attributes, const QString& mountPoint, const QString& fs, const QVariantMap& features, @@ -141,6 +142,7 @@ PartitionLayout::addEntry( const QString& label, entry.partLabel = label; entry.partType = type; + entry.partAttributes = attributes; entry.partMountPoint = mountPoint; PartUtils::findFS( fs, &entry.partFileSystem ); if ( entry.partFileSystem == FileSystem::Unknown ) @@ -250,6 +252,14 @@ PartitionLayout::execute( Device* dev, currentPartition->setType( part.partType ); #else cWarning() << "Ignoring type; requires KPMcore >= 4.2.0."; +#endif + } + if ( part.partAttributes ) + { +#if defined( WITH_KPMCORE42API ) + currentPartition->setAttributes( part.partAttributes ); +#else + cWarning() << "Ignoring attributes; requires KPMcore >= 4.2.0."; #endif } if ( !part.partFeatures.isEmpty() ) diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 5651ae995..d7af5df0c 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -42,6 +42,7 @@ public: { QString partLabel; QString partType; + quint64 partAttributes; QString partMountPoint; FileSystem::Type partFileSystem = FileSystem::Unknown; QVariantMap partFeatures; @@ -77,6 +78,7 @@ public: const QString& max = QString() ); bool addEntry( const QString& label, const QString& type, + quint64 attributes, const QString& mountPoint, const QString& fs, const QVariantMap& features, diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index f6cc34ee4..b04688138 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -106,6 +106,7 @@ defaultFileSystemType: "ext4" # size: 20% # minSize: 500M # maxSize: 10G +# attributes: 0xffff000000000003 # - name: "home" # type = "933ac7e1-2eb4-4f13-b844-0e14e2aef915" # filesystem: "ext4" @@ -128,6 +129,7 @@ defaultFileSystemType: "ext4" # and # partition name (gpt only; since 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 # - mountPoint: partition mount point # - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB) From 71249866df72be654a2456fbf1b0f452005bdec9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 12:45:29 +0200 Subject: [PATCH 065/105] CI: add tooling for schema validation The config files have fairly extensive documentation but no formal description; adding JSON-Schema into the mix makes it possible to write a machine-checkable description. --- ci/configvalidator.py | 110 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 ci/configvalidator.py diff --git a/ci/configvalidator.py b/ci/configvalidator.py new file mode 100644 index 000000000..e3b8ac24e --- /dev/null +++ b/ci/configvalidator.py @@ -0,0 +1,110 @@ +#! /usr/bin/env python3 +# +# SPDX-FileCopyrightText: 2020 Adriaan de Groot +# SPDX-License-Identifier: BSD-2-Clause +# License-Filename: LICENSES/BSD2 +# +usage = """ +Validates a Calamares config file -- YAML syntax -- against a schema. + +The schema is also written in YAML syntax, but the schema itself +is JSON-schema. This is possible because all JSON is YAML, and most +YAML is JSON. The limited subset of YAML that Calamares uses is +JSON-representable, anyway. + +Usage: + configvalidator.py ... +""" + +# The schemata originally lived outside the Calamares repository, +# without documented tooling. By putting them in the repository +# with the example files and explicit tooling, there's a better +# chance of them catching problems and acting as documentation. + +dependencies = """ +Dependencies for this tool are: py-yaml and py-jsonschema. + + https://pyyaml.org/ + https://github.com/Julian/jsonschema + +Simple installation is `pip install pyyaml jsonschema` +""" + +ERR_IMPORT, ERR_USAGE, ERR_FILE_NOT_FOUND, ERR_SYNTAX, ERR_INVALID = range(1,6) + +### DEPENDENCIES +# +# +try: + from jsonschema import validate, SchemaError, ValidationError + from yaml import safe_load, YAMLError +except ImportError as e: + print(e) + print(dependencies) + exit(ERR_IMPORT) + +from os.path import exists +import sys + +### INPUT VALIDATION +# +# +if len(sys.argv) < 3: + print(usage) + exit(ERR_USAGE) + +schema_file_name = sys.argv[1] +config_file_names = sys.argv[2:] + +if not exists(schema_file_name): + print(usage) + print("\nSchema file '{}' does not exist.".format(schema_file_name)) + exit(ERR_FILE_NOT_FOUND) +for f in config_file_names: + if not exists(f): + print(usage) + print("\nYAML file '{}' does not exist.".format(f)) + exit(ERR_FILE_NOT_FOUND) + +### FILES SYNTAX CHECK +# +# +with open(schema_file_name, "r") as data: + try: + schema = safe_load(data) + except YAMLError as e: + print("Schema error: {} {}.".format(e.problem, e.problem_mark)) + print("\nSchema file '{}' is invalid YAML.".format(schema_file_name)) + exit(ERR_SYNTAX) + +try: + validate(instance={}, schema=schema) +except SchemaError as e: + print(e.message) + print("\nSchema file '{}' is invalid JSON-Schema.".format(schema_file_name)) + exit(ERR_INVALID) +except ValidationError: + # Just means that empty isn't valid, but the Schema itself is + pass + +configs = [] +for f in config_file_names: + config = None + with open(f, "r") as data: + try: + config = safe_load(data) + except YAMLError as e: + print("YAML error: {} {}.".format(e.problem, e.problem_mark)) + print("\nYAML file '{}' is invalid.".format(f)) + exit(ERR_SYNTAX) + if config is None: + print("YAML file '{}' is empty.".format(f)) + configs.append(config) + +### SCHEMA VALIDATION +# +# +# Here a ValidationError from jsonschema carries a lot of useful information, +# so just let it go. +for c in configs: + validate(instance=c, schema=schema) From deec0b862fbb34aec8de96b2457a102d78c16805 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 13:04:34 +0200 Subject: [PATCH 066/105] [finished] Add schema for config - Original schema from artoo@manjaro.org, modified for current JSON-Schema use --- src/modules/finished/finished.schema.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/modules/finished/finished.schema.yaml diff --git a/src/modules/finished/finished.schema.yaml b/src/modules/finished/finished.schema.yaml new file mode 100644 index 000000000..56a844f50 --- /dev/null +++ b/src/modules/finished/finished.schema.yaml @@ -0,0 +1,11 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/finished +type: object +properties: + restartNowEnabled: { type: boolean, default: true } # TODO:3.3: remove + restartNowChecked: { type: boolean, default: false } # TODO:3.3: remove + restartNowCommand: { type: string } + restartNowMode: { type: string, enum: [ never, user-unchecked, user-checked, always ] } + notifyOnFinished: { type: boolean } +additionalProperties: false From 2e850f23e600a6fc745543da5b2e9d92a13ea594 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 13:12:22 +0200 Subject: [PATCH 067/105] Changes: thanks Phil, and change-of-branch --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index b1b74f4ee..e53c59437 100644 --- a/CHANGES +++ b/CHANGES @@ -7,8 +7,11 @@ website will have to do for older versions. This release contains contributions from (alphabetically by first name): - Pablo Ovelleiro Corral + - Philip Müller ## Core ## + - The default branch for Calamares source repositories (calamares + and calamares-extensions) is now *calamares*. - External modules can now be built again, outside of the Calamares source and build-tree. From 62e7128ff616d0295e75cfbf8ce3f84a8e8b5bfb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 13:54:13 +0200 Subject: [PATCH 068/105] CMake: document WITH_ and BUILD_ a little more - also mark TODO:3.3: for incompatible / surprising changes for 3.3 --- CMakeLists.txt | 12 ++++++++---- src/modules/packagechooser/CMakeLists.txt | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 269b2e9b1..b643dbd51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,8 +27,12 @@ # USE_ : fills in SKIP_MODULES for modules called - # WITH_ : try to enable (these usually default to ON). For # a list of WITH_ grep CMakeCache.txt after running -# CMake once. +# CMake once. These affect the ABI offered by Calamares. +# - PYTHON (enable Python Job modules) +# - QML (enable QML UI View modules) +# - PYTHONQT # TODO:3.3: remove # BUILD_ : choose additional things to build +# - TESTING (standard CMake option) # DEBUG_ : special developer flags for debugging # # Example usage: @@ -51,12 +55,12 @@ option( INSTALL_CONFIG "Install configuration files" OFF ) option( INSTALL_POLKIT "Install Polkit configuration" ON ) option( INSTALL_COMPLETION "Install shell completions" OFF ) # Options for the calamares executable -option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) -option( WITH_KF5DBus "Use DBus service for unique-application." OFF ) +option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) # TODO:3.3: WITH->BUILD (this isn't an ABI thing) +option( WITH_KF5DBus "Use DBus service for unique-application." OFF ) # TODO:3.3: WITH->BUILD # When adding WITH_* that affects the ABI offered by libcalamares, # also update libcalamares/CalamaresConfig.h.in option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) -option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF ) +option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF ) # TODO:3.3: remove option( WITH_QML "Enable QML UI options." ON ) # Possible debugging flags are: diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index d85eda8e2..d949829de 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -5,6 +5,7 @@ set( _extra_src "" ) ### OPTIONAL AppData XML support in PackageModel # # +# TODO:3.3:WITH->BUILD (this doesn't affect the ABI offered by Calamares) option( WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON ) if ( WITH_APPDATA ) find_package(Qt5 COMPONENTS Xml) From 0dbc44d3887c237c800e9e274ff9870fe1989566 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 14:06:26 +0200 Subject: [PATCH 069/105] CMake: update Python3-finding - mark for updates in 3.3: update to CMake 3.12 and use the more-modern Python modules for it then. --- CMakeLists.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b643dbd51..4506e9f6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ # One special target is "show-version", which can be built # to obtain the version number from here. +# TODO:3.3: Require CMake 3.12 cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) project( CALAMARES VERSION 3.2.26 @@ -326,15 +327,27 @@ if( NOT KF5DBusAddons_FOUND ) set( WITH_KF5DBus OFF ) endif() +# TODO:3.3: Use FindPython3 instead +find_package( PythonInterp ${PYTHONLIBS_VERSION} ) +set_package_properties( + PythonInterp PROPERTIES + DESCRIPTION "Python 3 interpreter." + URL "https://python.org" + PURPOSE "Python 3 interpreter for certain tests." +) +if ( PYTHONINTERP_FOUND ) + message(STATUS "Found Python 3 interpreter ${PYTHON_EXECUTABLE}") +endif() find_package( PythonLibs ${PYTHONLIBS_VERSION} ) set_package_properties( PythonLibs PROPERTIES DESCRIPTION "C interface libraries for the Python 3 interpreter." - URL "http://python.org" + URL "https://python.org" PURPOSE "Python 3 is used for Python job modules." ) if ( PYTHONLIBS_FOUND ) + # TODO:3.3: Require Boost + CMake; sort out Boost::Python # Since Boost provides CMake config files (starting with Boost 1.70. # or so) the mess that is the Calamares find code picks the wrong # bits. Suppress those CMake config files, as suggested by @jmrcpn @@ -345,7 +358,7 @@ if ( PYTHONLIBS_FOUND ) Boost PROPERTIES PURPOSE "Boost.Python is used for Python job modules." ) - + # TODO:3.3: Remove PythonQt support find_package( PythonQt ) set_package_properties( PythonQt PROPERTIES DESCRIPTION "A Python embedding solution for Qt applications." From b48c2745c149a608a9c3dc47ec6c0e18b660cb11 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 14:38:13 +0200 Subject: [PATCH 070/105] CI: apply schema-validation to the example config files - Any config file with a schema gets a test (validate-) to test the file. --- src/modules/CMakeLists.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 533c704f8..0b81c4b3f 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -66,3 +66,21 @@ endforeach() include( CalamaresAddTranslations ) add_calamares_python_translations( ${CALAMARES_TRANSLATION_LANGUAGES} ) + +# TODO:3.3: Use FindPython3 +if ( BUILD_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE ) + # The tests for each config file are independent of whether the + # module is enabled or not: the config file should match its schema + # regardless. + foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) + set( _schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.schema.yaml" ) + set( _conf_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.conf" ) + if ( EXISTS "${_schema_file}" AND EXISTS "${_conf_file}" ) + add_test( + NAME validate-${SUBDIRECTORY} + COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" "${_conf_file}" + ) + endif() + endforeach() +endif() + From a0d56acabee57a845c004483baf944a578c18fbc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 15:37:19 +0200 Subject: [PATCH 071/105] CI: verbose schema-failure diagnostics --- ci/configvalidator.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ci/configvalidator.py b/ci/configvalidator.py index e3b8ac24e..858c53224 100644 --- a/ci/configvalidator.py +++ b/ci/configvalidator.py @@ -79,8 +79,9 @@ with open(schema_file_name, "r") as data: try: validate(instance={}, schema=schema) +# While developing the schemata, get full exceptions from schema failure except SchemaError as e: - print(e.message) + print(e) print("\nSchema file '{}' is invalid JSON-Schema.".format(schema_file_name)) exit(ERR_INVALID) except ValidationError: @@ -101,10 +102,15 @@ for f in config_file_names: print("YAML file '{}' is empty.".format(f)) configs.append(config) +assert len(configs) == len(config_file_names), "Not all configurations loaded." + ### SCHEMA VALIDATION # # -# Here a ValidationError from jsonschema carries a lot of useful information, -# so just let it go. -for c in configs: - validate(instance=c, schema=schema) +for c, f in zip(configs, config_file_names): + try: + validate(instance=c, schema=schema) + except ValidationError as e: + print(e) + print("\nConfig file '{}' does not validate in schema.".format(f)) + exit(ERR_INVALID) From df183d40269e63bc8406ee7e2df7d9ce24795583 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 16:03:28 +0200 Subject: [PATCH 072/105] [welcome] Add schema for welcome config - Note that this is missing *languageIcon* so if that gets uncommented, it will fail validation. - While here decide that should be right up front in object (mappings) declaration. --- src/modules/finished/finished.schema.yaml | 2 +- src/modules/welcome/welcome.schema.yaml | 36 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/modules/welcome/welcome.schema.yaml diff --git a/src/modules/finished/finished.schema.yaml b/src/modules/finished/finished.schema.yaml index 56a844f50..53189c7fa 100644 --- a/src/modules/finished/finished.schema.yaml +++ b/src/modules/finished/finished.schema.yaml @@ -1,6 +1,7 @@ --- $schema: https://json-schema.org/schema# $id: https://calamares.io/schemas/finished +additionalProperties: false type: object properties: restartNowEnabled: { type: boolean, default: true } # TODO:3.3: remove @@ -8,4 +9,3 @@ properties: restartNowCommand: { type: string } restartNowMode: { type: string, enum: [ never, user-unchecked, user-checked, always ] } notifyOnFinished: { type: boolean } -additionalProperties: false diff --git a/src/modules/welcome/welcome.schema.yaml b/src/modules/welcome/welcome.schema.yaml new file mode 100644 index 000000000..56a79be06 --- /dev/null +++ b/src/modules/welcome/welcome.schema.yaml @@ -0,0 +1,36 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/welcome +additionalProperties: false +type: object +properties: + # TODO:3.3: drop the string alternatives and put the URL part in Branding + showSupportUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] } + showKnownIssuesUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] } + showReleaseNotesUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] } + showDonateUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] } + + requirements: + additionalProperties: false + type: object + properties: + requiredStorage: { type: number } + requiredRam: { type: number } + internetCheckUrl: { type: string } + check: + type: array + items: { type: string, enum: [storage, ram, power, internet, root, screen], unique: true } + required: # Key-name in the config-file + type: array + items: { type: string, enum: [storage, ram, power, internet, root, screen], unique: true } + required: [ requiredStorage, requiredRam, check ] # Schema keyword + + # TODO: refactor, this is reused in locale + geoip: + additionalProperties: false + type: object + properties: + style: { type: string, enum: [ none, fixed, xml, json ] } + url: { type: string } + selector: { type: string } + required: [ style, url, selector ] From 4a07bd4ae3ad297b48ee520f099434fa456e88bb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 16:06:56 +0200 Subject: [PATCH 073/105] CI: import all the rest of the YAML schema - These have **not** been fixed for validation, so the schema's themselves will fail to load. This is a consequence of variations in JSON-Schema representations through various drafts. Fixing the schemata is fairly straightforward. This gives us 19 new tests, all of which fail. --- src/modules/bootloader/bootloader.schema.yaml | 18 ++++++++++ .../displaymanager/displaymanager.schema.yaml | 16 +++++++++ src/modules/fstab/fstab.schema.yaml | 19 +++++++++++ src/modules/grubcfg/grubcfg.schema.yaml | 15 +++++++++ src/modules/initcpio/initcpio.schema.yaml | 7 ++++ src/modules/keyboard/keyboard.schema.yaml | 8 +++++ src/modules/license/license.schema.yaml | 17 ++++++++++ src/modules/locale/locale.schema.yaml | 10 ++++++ .../luksopenswaphookcfg.schema.yaml | 7 ++++ src/modules/machineid/machineid.schema.yaml | 9 +++++ src/modules/mount/mount.schema.yaml | 24 ++++++++++++++ src/modules/netinstall/netinstall.schema.yaml | 7 ++++ src/modules/packages/packages.schema.yaml | 33 +++++++++++++++++++ src/modules/partition/partition.schema.yaml | 11 +++++++ .../plymouthcfg/plymouthcfg.schema.yaml | 7 ++++ src/modules/removeuser/removeuser.schema.yaml | 7 ++++ src/modules/umount/umount.schema.yaml | 8 +++++ src/modules/unpackfs/unpackfs.schema.yaml | 14 ++++++++ src/modules/users/users.schema.yaml | 18 ++++++++++ 19 files changed, 255 insertions(+) create mode 100644 src/modules/bootloader/bootloader.schema.yaml create mode 100644 src/modules/displaymanager/displaymanager.schema.yaml create mode 100644 src/modules/fstab/fstab.schema.yaml create mode 100644 src/modules/grubcfg/grubcfg.schema.yaml create mode 100644 src/modules/initcpio/initcpio.schema.yaml create mode 100644 src/modules/keyboard/keyboard.schema.yaml create mode 100644 src/modules/license/license.schema.yaml create mode 100644 src/modules/locale/locale.schema.yaml create mode 100644 src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml create mode 100644 src/modules/machineid/machineid.schema.yaml create mode 100644 src/modules/mount/mount.schema.yaml create mode 100644 src/modules/netinstall/netinstall.schema.yaml create mode 100644 src/modules/packages/packages.schema.yaml create mode 100644 src/modules/partition/partition.schema.yaml create mode 100644 src/modules/plymouthcfg/plymouthcfg.schema.yaml create mode 100644 src/modules/removeuser/removeuser.schema.yaml create mode 100644 src/modules/umount/umount.schema.yaml create mode 100644 src/modules/unpackfs/unpackfs.schema.yaml create mode 100644 src/modules/users/users.schema.yaml diff --git a/src/modules/bootloader/bootloader.schema.yaml b/src/modules/bootloader/bootloader.schema.yaml new file mode 100644 index 000000000..45e8d4996 --- /dev/null +++ b/src/modules/bootloader/bootloader.schema.yaml @@ -0,0 +1,18 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/bootloader +additionalProperties: false +type: object +properties: + efiBootLoader: { type: string, required: true } + kernel: { type: string, required: true } + img: { type: string, required: true } + fallback: { type: str } + timeout: { type: str } + bootloaderEntryName: { type: str } + kernelLine: { type: str } + fallbackKernelLine: { type: str } + grubInstall: { type: string, required: true } + grubMkconfig: { type: string, required: true } + grubCfg: { type: string, required: true } + efiBootloaderId: { type: str } diff --git a/src/modules/displaymanager/displaymanager.schema.yaml b/src/modules/displaymanager/displaymanager.schema.yaml new file mode 100644 index 000000000..a16af732f --- /dev/null +++ b/src/modules/displaymanager/displaymanager.schema.yaml @@ -0,0 +1,16 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/displaymanager +additionalProperties: false +type: object +properties: + "displaymanagers": + type: seq + sequence: + - { type: string, required: true, enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm] } + "defaultDesktopEnvironment": + type: map + mapping: + "executable": { type: str } + "desktopFile": { type: str } + "basicSetup": { type: boolean, default: false } diff --git a/src/modules/fstab/fstab.schema.yaml b/src/modules/fstab/fstab.schema.yaml new file mode 100644 index 000000000..1c2bf459c --- /dev/null +++ b/src/modules/fstab/fstab.schema.yaml @@ -0,0 +1,19 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/fstab +additionalProperties: false +type: object +properties: + "mountOptions": + type: map + mapping: + "default": { type: string, required: true } + "btrfs": { type: string, required: true } + "ssdExtraMountOptions": + type: map + mapping: + "ext4": { type: string, required: true } + "jfs": { type: string, required: true } + "xfs": { type: string, required: true } + "swap": { type: string, required: true } + "btrfs": { type: string, required: true } diff --git a/src/modules/grubcfg/grubcfg.schema.yaml b/src/modules/grubcfg/grubcfg.schema.yaml new file mode 100644 index 000000000..10aa34c2b --- /dev/null +++ b/src/modules/grubcfg/grubcfg.schema.yaml @@ -0,0 +1,15 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/grubcfg +additionalProperties: false +type: object +properties: + "overwrite": { type: boolean, default: false } + "defaults": + type: map + mapping: + "GRUB_TIMEOUT": { type: int, required: true } + "GRUB_DEFAULT": { type: string, required: true } + "GRUB_DISABLE_SUBMENU": { type: boolean, default: true } + "GRUB_TERMINAL_OUTPUT": { type: string, required: true } + "GRUB_DISABLE_RECOVERY": { type: boolean, default: true } diff --git a/src/modules/initcpio/initcpio.schema.yaml b/src/modules/initcpio/initcpio.schema.yaml new file mode 100644 index 000000000..db81ba68e --- /dev/null +++ b/src/modules/initcpio/initcpio.schema.yaml @@ -0,0 +1,7 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/initcpio +additionalProperties: false +type: object +properties: + kernel: { type: string, required: true } diff --git a/src/modules/keyboard/keyboard.schema.yaml b/src/modules/keyboard/keyboard.schema.yaml new file mode 100644 index 000000000..33175b84d --- /dev/null +++ b/src/modules/keyboard/keyboard.schema.yaml @@ -0,0 +1,8 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/finished +additionalProperties: keyboard +type: object +properties: + xOrgConfFileName: { type: string, required: true } + convertedKeymapPath: { type: string, required: true } diff --git a/src/modules/license/license.schema.yaml b/src/modules/license/license.schema.yaml new file mode 100644 index 000000000..62bd07035 --- /dev/null +++ b/src/modules/license/license.schema.yaml @@ -0,0 +1,17 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/license +additionalProperties: false +type: object +properties: + "entries": + type: seq + sequence: + - type: map + mapping: + "id": { type: str } + "name": { type: str } + "vendor": { type: str } + "type": { type: str } + "url": { type: str } + "required": { type: boolean, default: false } diff --git a/src/modules/locale/locale.schema.yaml b/src/modules/locale/locale.schema.yaml new file mode 100644 index 000000000..41c3ad487 --- /dev/null +++ b/src/modules/locale/locale.schema.yaml @@ -0,0 +1,10 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/locale +additionalProperties: false +type: object +properties: + "region": { type: str } + "zone": { type: str } + "localeGenPath": { type: string, required: true } + "geoipUrl": { type: str } diff --git a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml b/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml new file mode 100644 index 000000000..660e06d0b --- /dev/null +++ b/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml @@ -0,0 +1,7 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/luksopenswaphookcfg +additionalProperties: false +type: object +properties: + "configFilePath": { type: string, required: true } diff --git a/src/modules/machineid/machineid.schema.yaml b/src/modules/machineid/machineid.schema.yaml new file mode 100644 index 000000000..588a7fa4e --- /dev/null +++ b/src/modules/machineid/machineid.schema.yaml @@ -0,0 +1,9 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/machineid +additionalProperties: false +type: object +properties: + "systemd": { type: boolean, default: true } + "dbus": { type: boolean, default: true } + "symlink": { type: boolean, default: true } diff --git a/src/modules/mount/mount.schema.yaml b/src/modules/mount/mount.schema.yaml new file mode 100644 index 000000000..8a81d9462 --- /dev/null +++ b/src/modules/mount/mount.schema.yaml @@ -0,0 +1,24 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/mount +additionalProperties: false +type: object +properties: + "extraMounts": + type: seq + sequence: + - type: map + mapping: + "device": { type: string, required: true } + "fs": { type: str } + "mountPoint": { type: string, required: true } + "options": { type: str } + "extraMountsEfi": + type: seq + sequence: + - type: map + mapping: + "device": { type: string, required: true } + "fs": { type: str } + "mountPoint": { type: string, required: true } + "options": { type: str } diff --git a/src/modules/netinstall/netinstall.schema.yaml b/src/modules/netinstall/netinstall.schema.yaml new file mode 100644 index 000000000..8420ea501 --- /dev/null +++ b/src/modules/netinstall/netinstall.schema.yaml @@ -0,0 +1,7 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/netinstall +additionalProperties: false +type: object +properties: + groupsUrl: { type: string, required: true } diff --git a/src/modules/packages/packages.schema.yaml b/src/modules/packages/packages.schema.yaml new file mode 100644 index 000000000..8b8a9eb1d --- /dev/null +++ b/src/modules/packages/packages.schema.yaml @@ -0,0 +1,33 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/packages +additionalProperties: false +type: object +properties: + "backend": { type: string, required: true, enum: [packagekit, zypp, yum, dnf, urpmi, apt, pacman, portage, entropy] } + "update_db": { type: boolean, default: true } + "operations": + type: seq + sequence: + - type: map + mapping: + "install": + type: seq + sequence: + - { type: text } + "remove": + type: seq + sequence: + - { type: text } + "localInstall": + type: seq + sequence: + - { type: text } + "try_install": + type: seq + sequence: + - { type: text } + "try_remove": + type: seq + sequence: + - { type: text } diff --git a/src/modules/partition/partition.schema.yaml b/src/modules/partition/partition.schema.yaml new file mode 100644 index 000000000..198123dd5 --- /dev/null +++ b/src/modules/partition/partition.schema.yaml @@ -0,0 +1,11 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/partition +additionalProperties: false +type: object +properties: + efiSystemPartition: { type: string, required: true } + ensureSuspendToDisk: { type: boolean, default: true } + drawNestedPartitions: { type: boolean, default: false } + alwaysShowPartitionLabels: { type: boolean, default: true } + defaultFileSystemType: { type: string, required: true } diff --git a/src/modules/plymouthcfg/plymouthcfg.schema.yaml b/src/modules/plymouthcfg/plymouthcfg.schema.yaml new file mode 100644 index 000000000..b15db1527 --- /dev/null +++ b/src/modules/plymouthcfg/plymouthcfg.schema.yaml @@ -0,0 +1,7 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/plymouthcfg +additionalProperties: false +type: object +properties: + plymouth_theme: { type: str } diff --git a/src/modules/removeuser/removeuser.schema.yaml b/src/modules/removeuser/removeuser.schema.yaml new file mode 100644 index 000000000..7ed6cfbbe --- /dev/null +++ b/src/modules/removeuser/removeuser.schema.yaml @@ -0,0 +1,7 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/removeuser +additionalProperties: false +type: object +properties: + "username": { type: string, required: true } diff --git a/src/modules/umount/umount.schema.yaml b/src/modules/umount/umount.schema.yaml new file mode 100644 index 000000000..b76a14ac6 --- /dev/null +++ b/src/modules/umount/umount.schema.yaml @@ -0,0 +1,8 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/umount +additionalProperties: false +type: object +properties: + "srcLog": { type: str } + "destLog": { type: str } diff --git a/src/modules/unpackfs/unpackfs.schema.yaml b/src/modules/unpackfs/unpackfs.schema.yaml new file mode 100644 index 000000000..0d6f0955a --- /dev/null +++ b/src/modules/unpackfs/unpackfs.schema.yaml @@ -0,0 +1,14 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/unpackfs +additionalProperties: false +type: object +properties: + "unpack": + type: seq + sequence: + - type: map + mapping: + "source": { type: string, required: true } + "sourcefs": { type: str } + "destination": { type: str } diff --git a/src/modules/users/users.schema.yaml b/src/modules/users/users.schema.yaml new file mode 100644 index 000000000..b667df7f6 --- /dev/null +++ b/src/modules/users/users.schema.yaml @@ -0,0 +1,18 @@ +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/users +additionalProperties: false +type: object +properties: + "defaultGroups": + required: true + type: seq + sequence: + - { type: str } + "autologinGroup": { type: string, required: true } + "doAutologin": { type: boolean, default: true } + "sudoersGroup": { type: string, required: true } + "setRootPassword": { type: boolean, default: true } + "availableShells": { type: str } + "avatarFilePath": { type: str } + "doReusePassword": { type: boolean, default: true } From 0cd894036363069c5a22abb62eb6b6ae3d2c169c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 16:16:07 +0200 Subject: [PATCH 074/105] [bootloader] Fix up schema --- src/modules/bootloader/bootloader.schema.yaml | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/modules/bootloader/bootloader.schema.yaml b/src/modules/bootloader/bootloader.schema.yaml index 45e8d4996..4670ea3db 100644 --- a/src/modules/bootloader/bootloader.schema.yaml +++ b/src/modules/bootloader/bootloader.schema.yaml @@ -4,15 +4,30 @@ $id: https://calamares.io/schemas/bootloader additionalProperties: false type: object properties: - efiBootLoader: { type: string, required: true } - kernel: { type: string, required: true } - img: { type: string, required: true } - fallback: { type: str } - timeout: { type: str } - bootloaderEntryName: { type: str } - kernelLine: { type: str } - fallbackKernelLine: { type: str } - grubInstall: { type: string, required: true } - grubMkconfig: { type: string, required: true } - grubCfg: { type: string, required: true } - efiBootloaderId: { type: str } + efiBootLoader: { type: string } + kernel: { type: string } + img: { type: string } + fallback: { type: string } + timeout: { type: string } # Inserted verbatim + bootloaderEntryName: { type: string } + kernelLine: { type: string } + fallbackKernelLine: { type: string } + + # Programs + grubInstall: { type: string } + grubMkconfig: { type: string } + grubCfg: { type: string } + grubProbe: { type: string } + efiBootMgr: { type: string } + + efiBootloaderId: { type: string } + installEFIFallback: { type: boolean } + +required: + - efiBootLoader + - kernel + - img + - grubInstall + - grubMkconfig + - grubCfg + - grubProbe From f2a8f0fcddb77c5d6fca8edabbd66122afc69475 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 17:17:59 +0200 Subject: [PATCH 075/105] =?UTF-8?q?Changes:=20thank=20Ga=C3=ABl=20and=20me?= =?UTF-8?q?ntion=20removal=20of=20-tools?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index e53c59437..e874dc866 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ website will have to do for older versions. # 3.2.26 (unreleased) # This release contains contributions from (alphabetically by first name): + - Gaël PORTAY - Pablo Ovelleiro Corral - Philip Müller @@ -14,6 +15,10 @@ This release contains contributions from (alphabetically by first name): and calamares-extensions) is now *calamares*. - External modules can now be built again, outside of the Calamares source and build-tree. + - The repository *calamares-tools* has been removed. The idea behind + the tooling was to provide schema validation for Calamares configuration + files. This has been merged into the primary repository, where it + is now part of the test suite. ## Modules ## - *locale* put some more places into the correct timezone **visually**; From 635f53a8044fe2b607865b56236eb0b8f4805ff3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 16 Jun 2020 17:36:59 +0200 Subject: [PATCH 076/105] CI: add a BUILD_SCHEMA_TESTING - ON by default, so if tests are built and the script works, those tests will run as well. - Check that the script works by invoking it once. --- CMakeLists.txt | 19 +++++++++++++++++++ ci/configvalidator.py | 12 ++++++++++++ src/modules/CMakeLists.txt | 2 +- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4506e9f6c..9795da8ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ # - PYTHONQT # TODO:3.3: remove # BUILD_ : choose additional things to build # - TESTING (standard CMake option) +# - SCHEMA_TESTING (requires Python, see ci/configvalidator.py) # DEBUG_ : special developer flags for debugging # # Example usage: @@ -63,6 +64,10 @@ option( WITH_KF5DBus "Use DBus service for unique-application." OFF ) # TODO:3. option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF ) # TODO:3.3: remove option( WITH_QML "Enable QML UI options." ON ) +# +# Additional parts to build +option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) + # Possible debugging flags are: # - DEBUG_TIMEZONES draws latitude and longitude lines on the timezone @@ -337,6 +342,20 @@ set_package_properties( ) if ( PYTHONINTERP_FOUND ) message(STATUS "Found Python 3 interpreter ${PYTHON_EXECUTABLE}") + if ( BUILD_SCHEMA_TESTING ) + # The configuration validator script has some dependencies, + # and if they are not installed, don't run. If errors out + # with exit(1) on missing dependencies. + exec_program( ${PYTHON_EXECUTABLE} ARGS "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" -x RETURN_VALUE _validator_deps ) + # It should never succeed, but only returns 1 when the imports fail + if ( _validator_deps EQUAL 1 ) + message(STATUS "BUILD_SCHEMA_TESTING dependencies are missing." ) + set( BUILD_SCHEMA_TESTING OFF ) + endif() + endif() +else() + # Can't run schema tests without Python3. + set( BUILD_SCHEMA_TESTING OFF ) endif() find_package( PythonLibs ${PYTHONLIBS_VERSION} ) set_package_properties( diff --git a/ci/configvalidator.py b/ci/configvalidator.py index 858c53224..9d1bc21a5 100644 --- a/ci/configvalidator.py +++ b/ci/configvalidator.py @@ -14,6 +14,15 @@ JSON-representable, anyway. Usage: configvalidator.py ... + configvalidator.py -x + +Exits with value 0 on success, otherwise: + 1 on missing dependencies + 2 on invalid command-line arguments + 3 on missing files + 4 if files have invalid syntax + 5 if files fail to validate +Use -x as only command-line argument to check the imports only. """ # The schemata originally lived outside the Calamares repository, @@ -50,6 +59,9 @@ import sys # # if len(sys.argv) < 3: + # Special-case: called with -x to just test the imports + if len(sys.argv) == 2 and sys.argv[1] == "-x": + exit(0) print(usage) exit(ERR_USAGE) diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 0b81c4b3f..08e5a8520 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -68,7 +68,7 @@ include( CalamaresAddTranslations ) add_calamares_python_translations( ${CALAMARES_TRANSLATION_LANGUAGES} ) # TODO:3.3: Use FindPython3 -if ( BUILD_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE ) +if ( BUILD_TESTING AND BUILD_SCHEMA_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE ) # The tests for each config file are independent of whether the # module is enabled or not: the config file should match its schema # regardless. From e68723f1c7f5619c532f433d86ef6a6712b2633c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Mon, 15 Jun 2020 10:16:13 -0400 Subject: [PATCH 077/105] [libcalamares] Handle integers prefixed with 0 or 0x - QString to-integer members detect if an integer string begins with "0x" (base 16) or "0", base 8; but QVariant members do not. - QString: the C language convention is used is base is set to 0. - Convert to QString and use its member toLongLong() and set base to 0 to detect integer strings begin with a prefix. --- src/libcalamares/utils/Variant.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/libcalamares/utils/Variant.cpp b/src/libcalamares/utils/Variant.cpp index e0156c35e..b8173acfa 100644 --- a/src/libcalamares/utils/Variant.cpp +++ b/src/libcalamares/utils/Variant.cpp @@ -72,14 +72,7 @@ getInteger( const QVariantMap& map, const QString& key, qint64 d ) if ( map.contains( key ) ) { auto v = map.value( key ); - if ( v.type() == QVariant::Int ) - { - result = v.toInt(); - } - else if ( v.type() == QVariant::LongLong ) - { - result = v.toLongLong(); - } + result = v.toString().toLongLong(nullptr, 0); } return result; From e84193a2cb5ddeffea7558d44311482e0fca44e2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 00:20:25 +0200 Subject: [PATCH 078/105] Docs: add a FreeBSD port directory (copy it to sysutils/calamares) --- data/FreeBSD/Makefile | 34 +++++++ data/FreeBSD/distinfo | 3 + data/FreeBSD/pkg-descr | 14 +++ data/FreeBSD/pkg-plist | 224 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 data/FreeBSD/Makefile create mode 100644 data/FreeBSD/distinfo create mode 100644 data/FreeBSD/pkg-descr create mode 100644 data/FreeBSD/pkg-plist diff --git a/data/FreeBSD/Makefile b/data/FreeBSD/Makefile new file mode 100644 index 000000000..520a05638 --- /dev/null +++ b/data/FreeBSD/Makefile @@ -0,0 +1,34 @@ +# $FreeBSD$ + +PORTNAME= calamares +DISTVERSION= 3.2.25 +CATEGORIES= sysutils +MASTER_SITES= https://github.com/${PORTNAME}/${PORTNAME}/releases/download/v${DISTVERSION}/ + +MAINTAINER= adridg@FreeBSD.org +COMMENT= GUI System installer and OEM configurator + +LICENSE= GPLv3 +LICENSE_FILE= ${WRKSRC}/LICENSE + +LIB_DEPENDS= libyaml-cpp.so:devel/yaml-cpp \ + libpwquality.so:security/libpwquality \ + libboost_python${PYTHON_SUFFIX}.so:devel/boost-python-libs + +USES= cmake compiler:c++17-lang gettext kde:5 pkgconfig \ + python:3.3+ qt:5 +USE_QT= concurrent core dbus declarative gui \ + network quickcontrols2 svg widgets xml \ + buildtools_build linguist_build qmake_build +USE_KDE= coreaddons dbusaddons parts service \ + ecm_build +USE_LDCONFIG= yes + +CMAKE_OFF= WITH_KF5Crash \ + INSTALL_CONFIG \ + INSTALL_COMPLETION \ + INSTALL_POLKIT +CMAKE_ON= CMAKE_DISABLE_FIND_PACKAGE_KPMcore +CMAKE_ARGS= -DSKIP_MODULES="webview" + +.include diff --git a/data/FreeBSD/distinfo b/data/FreeBSD/distinfo new file mode 100644 index 000000000..e333963a8 --- /dev/null +++ b/data/FreeBSD/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1592339404 +SHA256 (calamares-3.2.25.tar.gz) = 797ce33db7d4e4c06bbccef95f6c4023f7628e91bd142896695565fed4ae8c4b +SIZE (calamares-3.2.25.tar.gz) = 3580197 diff --git a/data/FreeBSD/pkg-descr b/data/FreeBSD/pkg-descr new file mode 100644 index 000000000..39cb4335c --- /dev/null +++ b/data/FreeBSD/pkg-descr @@ -0,0 +1,14 @@ +Calamares is an installer framework. By design it is very customizable, +in order to satisfy a wide variety of needs and use cases. + +Calamares aims to be easy, usable, beautiful, pragmatic, inclusive and +distribution-agnostic. + +Got a Linux distribution but no system installer? Grab Calamares, mix +and match any number of Calamares modules (or write your own in Python +or C++), throw together some branding, package it up and you are ready +to ship! + +(The above applies to FreeBSD as well) + +WWW: https://calamares.io/ diff --git a/data/FreeBSD/pkg-plist b/data/FreeBSD/pkg-plist new file mode 100644 index 000000000..7f588b7a9 --- /dev/null +++ b/data/FreeBSD/pkg-plist @@ -0,0 +1,224 @@ +bin/calamares +include/libcalamares/CalamaresConfig.h +include/libcalamares/CppJob.h +include/libcalamares/DllMacro.h +include/libcalamares/GlobalStorage.h +include/libcalamares/Job.h +include/libcalamares/JobExample.h +include/libcalamares/JobQueue.h +include/libcalamares/ProcessJob.h +include/libcalamares/PythonHelper.h +include/libcalamares/PythonJob.h +include/libcalamares/PythonJobApi.h +include/libcalamares/Settings.h +include/libcalamares/utils/BoostPython.h +include/libcalamares/utils/CalamaresUtilsSystem.h +include/libcalamares/utils/CommandList.h +include/libcalamares/utils/Dirs.h +include/libcalamares/utils/Entropy.h +include/libcalamares/utils/Logger.h +include/libcalamares/utils/NamedEnum.h +include/libcalamares/utils/NamedSuffix.h +include/libcalamares/utils/PluginFactory.h +include/libcalamares/utils/RAII.h +include/libcalamares/utils/Retranslator.h +include/libcalamares/utils/String.h +include/libcalamares/utils/Tests.h +include/libcalamares/utils/UMask.h +include/libcalamares/utils/Units.h +include/libcalamares/utils/Variant.h +include/libcalamares/utils/Yaml.h +include/libcalamares/utils/moc-warnings.h +lib/calamares/libcalamares.so +lib/calamares/modules/bootloader/main.py +lib/calamares/modules/bootloader/module.desc +lib/calamares/modules/bootloader/test.yaml +lib/calamares/modules/contextualprocess/libcalamares_job_contextualprocess.so +lib/calamares/modules/contextualprocess/module.desc +lib/calamares/modules/displaymanager/main.py +lib/calamares/modules/displaymanager/module.desc +lib/calamares/modules/dracut/main.py +lib/calamares/modules/dracut/module.desc +lib/calamares/modules/dracutlukscfg/libcalamares_job_dracutlukscfg.so +lib/calamares/modules/dracutlukscfg/module.desc +lib/calamares/modules/dummycpp/libcalamares_job_dummycpp.so +lib/calamares/modules/dummycpp/module.desc +lib/calamares/modules/dummyprocess/module.desc +lib/calamares/modules/dummypython/main.py +lib/calamares/modules/dummypython/module.desc +lib/calamares/modules/finished/libcalamares_viewmodule_finished.so +lib/calamares/modules/finished/module.desc +lib/calamares/modules/fstab/main.py +lib/calamares/modules/fstab/module.desc +lib/calamares/modules/fstab/test.yaml +lib/calamares/modules/grubcfg/main.py +lib/calamares/modules/grubcfg/module.desc +lib/calamares/modules/hostinfo/libcalamares_job_hostinfo.so +lib/calamares/modules/hostinfo/module.desc +lib/calamares/modules/hwclock/main.py +lib/calamares/modules/hwclock/module.desc +lib/calamares/modules/initcpio/libcalamares_job_initcpio.so +lib/calamares/modules/initcpio/module.desc +lib/calamares/modules/initcpiocfg/main.py +lib/calamares/modules/initcpiocfg/module.desc +lib/calamares/modules/initramfs/libcalamares_job_initramfs.so +lib/calamares/modules/initramfs/module.desc +lib/calamares/modules/initramfscfg/encrypt_hook +lib/calamares/modules/initramfscfg/encrypt_hook_nokey +lib/calamares/modules/initramfscfg/main.py +lib/calamares/modules/initramfscfg/module.desc +lib/calamares/modules/interactiveterminal/libcalamares_viewmodule_interactiveterminal.so +lib/calamares/modules/interactiveterminal/module.desc +lib/calamares/modules/keyboard/libcalamares_viewmodule_keyboard.so +lib/calamares/modules/keyboard/module.desc +lib/calamares/modules/keyboardq/libcalamares_viewmodule_keyboardq.so +lib/calamares/modules/keyboardq/module.desc +lib/calamares/modules/license/libcalamares_viewmodule_license.so +lib/calamares/modules/license/module.desc +lib/calamares/modules/locale/libcalamares_viewmodule_locale.so +lib/calamares/modules/locale/module.desc +lib/calamares/modules/localecfg/main.py +lib/calamares/modules/localecfg/module.desc +lib/calamares/modules/localeq/libcalamares_viewmodule_localeq.so +lib/calamares/modules/localeq/module.desc +lib/calamares/modules/luksbootkeyfile/libcalamares_job_luksbootkeyfile.so +lib/calamares/modules/luksbootkeyfile/module.desc +lib/calamares/modules/luksopenswaphookcfg/main.py +lib/calamares/modules/luksopenswaphookcfg/module.desc +lib/calamares/modules/machineid/libcalamares_job_machineid.so +lib/calamares/modules/machineid/module.desc +lib/calamares/modules/mount/main.py +lib/calamares/modules/mount/module.desc +lib/calamares/modules/mount/test.yaml +lib/calamares/modules/netinstall/libcalamares_viewmodule_netinstall.so +lib/calamares/modules/netinstall/module.desc +lib/calamares/modules/networkcfg/main.py +lib/calamares/modules/networkcfg/module.desc +lib/calamares/modules/notesqml/libcalamares_viewmodule_notesqml.so +lib/calamares/modules/notesqml/module.desc +lib/calamares/modules/oemid/libcalamares_viewmodule_oemid.so +lib/calamares/modules/oemid/module.desc +lib/calamares/modules/openrcdmcryptcfg/main.py +lib/calamares/modules/openrcdmcryptcfg/module.desc +lib/calamares/modules/packagechooser/libcalamares_viewmodule_packagechooser.so +lib/calamares/modules/packagechooser/module.desc +lib/calamares/modules/packages/main.py +lib/calamares/modules/packages/module.desc +lib/calamares/modules/packages/test.yaml +lib/calamares/modules/plymouthcfg/main.py +lib/calamares/modules/plymouthcfg/module.desc +lib/calamares/modules/preservefiles/libcalamares_job_preservefiles.so +lib/calamares/modules/preservefiles/module.desc +lib/calamares/modules/rawfs/main.py +lib/calamares/modules/rawfs/module.desc +lib/calamares/modules/removeuser/libcalamares_job_removeuser.so +lib/calamares/modules/removeuser/module.desc +lib/calamares/modules/services-openrc/main.py +lib/calamares/modules/services-openrc/module.desc +lib/calamares/modules/services-systemd/main.py +lib/calamares/modules/services-systemd/module.desc +lib/calamares/modules/shellprocess/libcalamares_job_shellprocess.so +lib/calamares/modules/shellprocess/module.desc +lib/calamares/modules/summary/libcalamares_viewmodule_summary.so +lib/calamares/modules/summary/module.desc +lib/calamares/modules/tracking/libcalamares_viewmodule_tracking.so +lib/calamares/modules/tracking/module.desc +lib/calamares/modules/umount/main.py +lib/calamares/modules/umount/module.desc +lib/calamares/modules/unpackfs/main.py +lib/calamares/modules/unpackfs/module.desc +lib/calamares/modules/unpackfs/runtests.sh +lib/calamares/modules/users/libcalamares_viewmodule_users.so +lib/calamares/modules/users/module.desc +lib/calamares/modules/welcome/libcalamares_viewmodule_welcome.so +lib/calamares/modules/welcome/module.desc +lib/calamares/modules/welcomeq/libcalamares_viewmodule_welcomeq.so +lib/calamares/modules/welcomeq/module.desc +lib/cmake/Calamares/CMakeColors.cmake +lib/cmake/Calamares/CalamaresAddBrandingSubdirectory.cmake +lib/cmake/Calamares/CalamaresAddLibrary.cmake +lib/cmake/Calamares/CalamaresAddModuleSubdirectory.cmake +lib/cmake/Calamares/CalamaresAddPlugin.cmake +lib/cmake/Calamares/CalamaresAddTest.cmake +lib/cmake/Calamares/CalamaresAddTranslations.cmake +lib/cmake/Calamares/CalamaresAutomoc.cmake +lib/cmake/Calamares/CalamaresConfig.cmake +lib/cmake/Calamares/CalamaresConfigVersion.cmake +lib/cmake/Calamares/CalamaresLibraryDepends-%%CMAKE_BUILD_TYPE%%.cmake +lib/cmake/Calamares/CalamaresLibraryDepends.cmake +lib/cmake/Calamares/CalamaresUse.cmake +lib/libcalamares.so +lib/libcalamares.so.3.2.25 +lib/libcalamaresui.so +lib/libcalamaresui.so.3.2.25 +man/man8/calamares.8.gz +share/applications/calamares.desktop +%%DATADIR%%/branding/default/banner.png +%%DATADIR%%/branding/default/branding.desc +%%DATADIR%%/branding/default/lang/calamares-default_ar.qm +%%DATADIR%%/branding/default/lang/calamares-default_en.qm +%%DATADIR%%/branding/default/lang/calamares-default_eo.qm +%%DATADIR%%/branding/default/lang/calamares-default_fr.qm +%%DATADIR%%/branding/default/lang/calamares-default_nl.qm +%%DATADIR%%/branding/default/languages.png +%%DATADIR%%/branding/default/show.qml +%%DATADIR%%/branding/default/squid.png +%%DATADIR%%/branding/default/stylesheet.qss +%%DATADIR%%/qml/calamares/slideshow/BackButton.qml +%%DATADIR%%/qml/calamares/slideshow/ForwardButton.qml +%%DATADIR%%/qml/calamares/slideshow/NavButton.qml +%%DATADIR%%/qml/calamares/slideshow/Presentation.qml +%%DATADIR%%/qml/calamares/slideshow/Slide.qml +%%DATADIR%%/qml/calamares/slideshow/SlideCounter.qml +%%DATADIR%%/qml/calamares/slideshow/qmldir +share/icons/hicolor/scalable/apps/calamares.svg +share/locale/ar/LC_MESSAGES/calamares-python.mo +share/locale/as/LC_MESSAGES/calamares-python.mo +share/locale/ast/LC_MESSAGES/calamares-python.mo +share/locale/be/LC_MESSAGES/calamares-python.mo +share/locale/bg/LC_MESSAGES/calamares-python.mo +share/locale/ca/LC_MESSAGES/calamares-python.mo +share/locale/cs_CZ/LC_MESSAGES/calamares-python.mo +share/locale/da/LC_MESSAGES/calamares-python.mo +share/locale/de/LC_MESSAGES/calamares-python.mo +share/locale/el/LC_MESSAGES/calamares-python.mo +share/locale/en_GB/LC_MESSAGES/calamares-python.mo +share/locale/eo/LC_MESSAGES/calamares-python.mo +share/locale/es/LC_MESSAGES/calamares-python.mo +share/locale/es_MX/LC_MESSAGES/calamares-python.mo +share/locale/es_PR/LC_MESSAGES/calamares-python.mo +share/locale/et/LC_MESSAGES/calamares-python.mo +share/locale/eu/LC_MESSAGES/calamares-python.mo +share/locale/fi_FI/LC_MESSAGES/calamares-python.mo +share/locale/fr/LC_MESSAGES/calamares-python.mo +share/locale/gl/LC_MESSAGES/calamares-python.mo +share/locale/he/LC_MESSAGES/calamares-python.mo +share/locale/hi/LC_MESSAGES/calamares-python.mo +share/locale/hr/LC_MESSAGES/calamares-python.mo +share/locale/hu/LC_MESSAGES/calamares-python.mo +share/locale/id/LC_MESSAGES/calamares-python.mo +share/locale/is/LC_MESSAGES/calamares-python.mo +share/locale/it_IT/LC_MESSAGES/calamares-python.mo +share/locale/ja/LC_MESSAGES/calamares-python.mo +share/locale/ko/LC_MESSAGES/calamares-python.mo +share/locale/lt/LC_MESSAGES/calamares-python.mo +share/locale/ml/LC_MESSAGES/calamares-python.mo +share/locale/mr/LC_MESSAGES/calamares-python.mo +share/locale/nb/LC_MESSAGES/calamares-python.mo +share/locale/nl/LC_MESSAGES/calamares-python.mo +share/locale/pl/LC_MESSAGES/calamares-python.mo +share/locale/pt_BR/LC_MESSAGES/calamares-python.mo +share/locale/pt_PT/LC_MESSAGES/calamares-python.mo +share/locale/ro/LC_MESSAGES/calamares-python.mo +share/locale/ru/LC_MESSAGES/calamares-python.mo +share/locale/sk/LC_MESSAGES/calamares-python.mo +share/locale/sl/LC_MESSAGES/calamares-python.mo +share/locale/sq/LC_MESSAGES/calamares-python.mo +share/locale/sr/LC_MESSAGES/calamares-python.mo +share/locale/sr@latin/LC_MESSAGES/calamares-python.mo +share/locale/sv/LC_MESSAGES/calamares-python.mo +share/locale/th/LC_MESSAGES/calamares-python.mo +share/locale/tr_TR/LC_MESSAGES/calamares-python.mo +share/locale/uk/LC_MESSAGES/calamares-python.mo +share/locale/zh_CN/LC_MESSAGES/calamares-python.mo +share/locale/zh_TW/LC_MESSAGES/calamares-python.mo From dda4ab0b2e44fc35524e1d49d94cddc178a2dff2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 10:06:33 +0200 Subject: [PATCH 079/105] [tracking] Improve naming - give the on-some-checkbox-state-changed slots better names - while here, refactor is-any-actual-tracking-option-checked - improve other debug messages, to be a whole sentence --- src/modules/tracking/TrackingPage.cpp | 30 +++++++++++++-------------- src/modules/tracking/TrackingPage.h | 11 ++++++++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index e42ae2312..fa5cba2bb 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -41,14 +41,14 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) CALAMARES_RETRANSLATE_SLOT( &TrackingPage::retranslate ); ui->noneCheckBox->setChecked( true ); - connect( ui->noneCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::noneChecked ); - connect( ui->installCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::otherChecked ); - connect( ui->machineCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::otherChecked ); - connect( ui->userCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::otherChecked ); + connect( ui->noneCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonNoneChecked ); + connect( ui->installCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); + connect( ui->machineCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); + connect( ui->userCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); connect( ui->installCheckBox, &QCheckBox::stateChanged, [ this ]( int s ) { cDebug() << "Checkbox install changed" << s; } ); connect( config->installTracking(), &TrackingStyleConfig::trackingChanged, [ config ]() { cDebug() << - "Install tracking changed" << config->installTracking()->isEnabled(); } ) ; + "Install tracking configuration changed to " << config->installTracking()->isEnabled(); } ) ; connect( config, &Config::generalPolicyChanged, [ this ]( const QString& url ) { this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); @@ -87,20 +87,25 @@ TrackingPage::retranslate() .arg( product ) ); } -void TrackingPage::noneChecked(int state) +bool TrackingPage::anyOtherChecked() const +{ + return ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked(); +} + + +void TrackingPage::buttonNoneChecked(int state) { if ( state ) { - cDebug() << "Unchecking all due to none box"; + cDebug() << "Unchecking all other buttons because 'None' was checked"; ui->installCheckBox->setChecked( false ); ui->machineCheckBox->setChecked( false ); ui->userCheckBox->setChecked( false ); } } -void TrackingPage::otherChecked(int state) +void TrackingPage::buttonChecked(int state) { - cDebug() << "Other checked" << state; if ( state ) { // Can't have none checked, if another one is @@ -108,12 +113,7 @@ void TrackingPage::otherChecked(int state) } else { - if ( ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked() ) - { - // One of them is still checked, leave *none* alone - ; - } - else + if ( !anyOtherChecked() ) { ui->noneCheckBox->setChecked( true ); } diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index e4c465fbc..1a995870d 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -37,6 +37,13 @@ class TrackingPage : public QWidget public: explicit TrackingPage( Config* config, QWidget* parent = nullptr ); + /** @brief is any of the enable-tracking buttons checked? + * + * Returns true if any one or more of install, machine or user + * tracking is enabled. + */ + bool anyOtherChecked() const; + public Q_SLOTS: void retranslate(); @@ -45,14 +52,14 @@ public Q_SLOTS: * @p state will be non-zero when the box is checked; this * **unchecks** all the other boxes. */ - void noneChecked( int state ); + void buttonNoneChecked( int state ); /** @brief Some other checkbox changed * * This may check the *none* button if all the others are * now unchecked. */ - void otherChecked( int state ); + void buttonChecked( int state ); private: Ui::TrackingPage* ui; From c797a30a72050a525785c24917de56a7f5a73ce4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 10:10:20 +0200 Subject: [PATCH 080/105] [tracking] Bold more relevant parts of level-descriptions --- src/modules/tracking/TrackingPage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index fa5cba2bb..cb7e5a10a 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -76,14 +76,14 @@ TrackingPage::retranslate() .arg( product ) ); ui->installExplanation->setText( tr( "By selecting this you will send information about your installation and hardware. This information " - "will only be sent once after the installation finishes." ) ); + "will only be sent once after the installation finishes." ) ); ui->machineExplanation->setText( - tr( "By selecting this you will periodically send information about your machine installation, " + tr( "By selecting this you will periodically send information about your machine installation, " "hardware and applications, to %1." ) .arg( product ) ); ui->userExplanation->setText( - tr( "By selecting this you will regularly send information about your " - "user installation, hardware, applications and application usage patterns, to %1." ) + tr( "By selecting this you will regularly send information about your " + "user installation, hardware, applications and application usage patterns, to %1." ) .arg( product ) ); } From 4d6a5d0cb537d9af4968f0b68a2cc274b38fa11f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 10:36:35 +0200 Subject: [PATCH 081/105] [tracking] Use KMacroExpander instead of homebrew for install-URL --- src/modules/tracking/TrackingJobs.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 18d01c7ca..0b27eab05 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -24,6 +24,8 @@ #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" +#include + #include #include @@ -79,14 +81,13 @@ TrackingInstallJob::addJob( Calamares::JobList& list, InstallTrackingConfig* con { if ( config->isEnabled() ) { - QString installUrl = config->installTrackingUrl(); const auto* s = CalamaresUtils::System::instance(); - - QString memory, disk; - memory.setNum( s->getTotalMemoryB().first ); - disk.setNum( s->getTotalDiskB() ); - - installUrl.replace( "$CPU", s->getCpuDescription() ).replace( "$MEMORY", memory ).replace( "$DISK", disk ); + QHash map { std::initializer_list< std::pair< QString, QString > > { + { QStringLiteral("CPU"), s->getCpuDescription() }, + { QStringLiteral("MEMORY"), QString::number( s->getTotalMemoryB().first ) }, + { QStringLiteral("DISK"), QString::number( s->getTotalDiskB() ) } + } }; + QString installUrl = KMacroExpander::expandMacros( config->installTrackingUrl(), map ); cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl; From cb2909f6d875fa90f15f50f45f633ff8e8f59b13 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 10:18:08 +0200 Subject: [PATCH 082/105] [tracking] Rename "neon" tracking KDE neon does not do this kind of tracking -- although it was originally requested by KDE neon, no server roll-out was done once the privacy policy was thought out. --- src/modules/tracking/Config.cpp | 2 +- src/modules/tracking/Config.h | 2 +- src/modules/tracking/TrackingJobs.cpp | 12 ++++++------ src/modules/tracking/TrackingJobs.h | 6 +++--- src/modules/tracking/TrackingViewStep.cpp | 8 -------- src/modules/tracking/tracking.conf | 4 ++-- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 2dc91c2a9..a75522529 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -129,7 +129,7 @@ MachineTrackingConfig::MachineTrackingConfig( QObject* parent ) static bool isValidMachineTrackingStyle( const QString& s ) { - static QStringList knownStyles { "neon" }; + static QStringList knownStyles { "updatemanager" }; return knownStyles.contains( s ); } diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index 26dcf2f4f..0bdff260a 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -118,7 +118,7 @@ private: * * When machine tracking is on, the installed system will report * back ("call home") at some point. This can mean Debian pop-con, - * or KDE neon maching tracking, or something else. The kind + * or updatemanager maching tracking, or something else. The kind * of configuration depends on the style of tracking that is enabled. */ class MachineTrackingConfig : public TrackingStyleConfig diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 0b27eab05..70e45e2eb 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -101,9 +101,9 @@ TrackingMachineJob::addJob( Calamares::JobList& list, MachineTrackingConfig* con if ( config->isEnabled() ) { const auto style = config->machineTrackingStyle(); - if ( style == "neon" ) + if ( style == "updatemanager" ) { - list.append( Calamares::job_ptr( new TrackingMachineNeonJob() ) ); + list.append( Calamares::job_ptr( new TrackingMachineUpdateManagerJob() ) ); } else { @@ -114,25 +114,25 @@ TrackingMachineJob::addJob( Calamares::JobList& list, MachineTrackingConfig* con QString -TrackingMachineNeonJob::prettyName() const +TrackingMachineUpdateManagerJob::prettyName() const { return tr( "Machine feedback" ); } QString -TrackingMachineNeonJob::prettyDescription() const +TrackingMachineUpdateManagerJob::prettyDescription() const { return prettyName(); } QString -TrackingMachineNeonJob::prettyStatusMessage() const +TrackingMachineUpdateManagerJob::prettyStatusMessage() const { return tr( "Configuring machine feedback." ); } Calamares::JobResult -TrackingMachineNeonJob::exec() +TrackingMachineUpdateManagerJob::exec() { static const auto script = QStringLiteral( R"x( diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h index 76e7dbed9..dd5ca6b92 100644 --- a/src/modules/tracking/TrackingJobs.h +++ b/src/modules/tracking/TrackingJobs.h @@ -76,13 +76,13 @@ public: static void addJob( Calamares::JobList& list, MachineTrackingConfig* config ); }; -/** @brief Tracking machines, KDE neon style +/** @brief Tracking machines, update-manager style * * The machine has a machine-id, and this is sed(1)'ed into the * update-manager configuration, to report the machine-id back - * to KDE neon servers. + * to distro servers. */ -class TrackingMachineNeonJob : public TrackingMachineJob +class TrackingMachineUpdateManagerJob : public TrackingMachineJob { Q_OBJECT public: diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 491fef12a..2cbfe4ae2 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -34,14 +34,6 @@ CALAMARES_PLUGIN_FACTORY_DEFINITION( TrackingViewStepFactory, registerPlugin< TrackingViewStep >(); ) -/** @brief Is @p s a valid machine-tracking style. */ -static bool -isValidStyle( const QString& s ) -{ - static QStringList knownStyles { "neon" }; - return knownStyles.contains( s ); -} - TrackingViewStep::TrackingViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_config( new Config( this ) ) diff --git a/src/modules/tracking/tracking.conf b/src/modules/tracking/tracking.conf index 46ba7fed6..8569f0935 100644 --- a/src/modules/tracking/tracking.conf +++ b/src/modules/tracking/tracking.conf @@ -77,11 +77,11 @@ install: # The machine area has one specific configuration key: # style: This string specifies what kind of tracking configuration # needs to be done. There is currently only one valid -# style, "neon", which edits two files in the installed +# style, "updatemanager", which edits two files in the installed # system to enable system-tracking. machine: enabled: false - style: neon + style: updatemanager # The user area is not yet implemented, and has no specific configuration. user: From 48d0c5beeb3587a815d990b8e95f5003eb6f99a2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 11:02:59 +0200 Subject: [PATCH 083/105] [tracking] Do user tracking in the job queue --- src/modules/tracking/TrackingViewStep.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 2cbfe4ae2..125d17974 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -111,6 +111,8 @@ TrackingViewStep::jobs() const Calamares::JobList l; TrackingInstallJob::addJob( l, m_config->installTracking() ); TrackingMachineJob::addJob( l, m_config->machineTracking() ); + TrackingUserJob::addJob( l, m_config->userTracking() ); + cDebug() << Logger::SubEntry << l.count() << "jobs queued."; return l; } From 9433311f2404066b94eafdf56dd041c8e370f1f8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 11:17:48 +0200 Subject: [PATCH 084/105] [tracking] Explain which tracking style is disabled by URL-validation --- src/modules/tracking/Config.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index a75522529..30c6c30d1 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -87,7 +87,7 @@ TrackingStyleConfig::validateUrl( QString& urlString ) { if ( m_state != DisabledByConfig ) { - cError() << "URL" << urlString << "is not valid; disabling this tracking type."; + cError() << "URL" << urlString << "is not valid; disabling tracking type" << objectName(); m_state = DisabledByConfig; emit trackingChanged(); } @@ -109,6 +109,7 @@ TrackingStyleConfig::setConfigurationMap( const QVariantMap& config ) InstallTrackingConfig::InstallTrackingConfig( QObject* parent ) : TrackingStyleConfig( parent ) { + setObjectName( "InstallTrackingConfig" ); } void @@ -123,6 +124,7 @@ InstallTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap MachineTrackingConfig::MachineTrackingConfig( QObject* parent ) : TrackingStyleConfig( parent ) { + setObjectName( "MachineTrackingConfig" ); } /** @brief Is @p s a valid machine-tracking style. */ @@ -146,6 +148,7 @@ MachineTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap UserTrackingConfig::UserTrackingConfig( QObject* parent ) : TrackingStyleConfig( parent ) { + setObjectName( "UserTrackingConfig" ); } static bool From 756e3084dc421a2db0cc3e0bb1110b3d3751df8d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 11:30:12 +0200 Subject: [PATCH 085/105] [tracking] Simplify updatemanager job - sed all the URI lines with a simple replacement - document policy requirements --- src/modules/tracking/TrackingJobs.cpp | 20 +++++++++----------- src/modules/tracking/tracking.conf | 14 ++++++++++---- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 70e45e2eb..3d8ea27f1 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -134,17 +134,15 @@ TrackingMachineUpdateManagerJob::prettyStatusMessage() const Calamares::JobResult TrackingMachineUpdateManagerJob::exec() { - static const auto script = QStringLiteral( - R"x( -MACHINE_ID=`cat /etc/machine-id` -sed -i "s,URI =.*,URI = http://releases.neon.kde.org/meta-release/${MACHINE_ID}," /etc/update-manager/meta-release -sed -i "s,URI_LTS =.*,URI_LTS = http://releases.neon.kde.org/meta-release-lts/${MACHINE_ID}," /etc/update-manager/meta-release -true -)x" ); - int r = CalamaresUtils::System::instance()->targetEnvCall( "/bin/sh", - QString(), // Working dir - script, - std::chrono::seconds( 1 ) ); + static const auto script = QStringLiteral( "sed -i '/^URI/s,${MACHINE_ID},'`cat /etc/machine-id`',' /etc/update-manager/meta-release || true" ); + + auto res = CalamaresUtils::System::instance()->runCommand( + CalamaresUtils::System::RunLocation::RunInTarget, + QStringList { QStringLiteral( "/bin/sh" ) }, + QString(), // Working dir + script, // standard input + std::chrono::seconds( 1 ) ); + int r = res.first; if ( r == 0 ) { diff --git a/src/modules/tracking/tracking.conf b/src/modules/tracking/tracking.conf index 8569f0935..88d1e7b59 100644 --- a/src/modules/tracking/tracking.conf +++ b/src/modules/tracking/tracking.conf @@ -34,8 +34,10 @@ # Each area has a key *policy*, which is a Url to be opened when # the user clicks on the corresponding Help button for an explanation # of the details of that particular kind of tracking. If no policy -# is set, the help button is hidden. The example policy links -# go to Calamares' generic user manual. +# is set, that tracking style is disabled. The example policy links +# go to Calamares' generic user manual (which is a terrible idea +# for distro's: you have GDPR obligations under most of these tracking +# styles, so do your homework). # # Each area may have other configuration keys, depending on the # area and how it needs to be configured. @@ -48,8 +50,7 @@ --- # This is the global policy; it is displayed as a link on the page. # If blank or commented out, no link is displayed on the tracking -# page. It is recommended to either provide policy URLs for each -# area, *or* one general link, and not to mix them. +# page. You **must** provide policy links per-area as well. policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking" # This is the default level to enable for tracking. If commented out, @@ -79,9 +80,14 @@ install: # needs to be done. There is currently only one valid # style, "updatemanager", which edits two files in the installed # system to enable system-tracking. +# +# Per-style documentation: +# - updatemanager replaces the literal string "${MACHINE_ID}" with the contents of +# /etc/machine-id, in lines starting with "URI" in the file /etc/update-manager/meta-release machine: enabled: false style: updatemanager + policy: "https://github.com/calamares/calamares/wiki/Use-Guide#machine-tracking" # The user area is not yet implemented, and has no specific configuration. user: From 8c1685d2cf327fc97f71a37a728c21b43ac07697 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 12:20:35 +0200 Subject: [PATCH 086/105] [tracking] Connect UI to configuration - policy buttons open the policy URL - hide tracking levels that are not configurable --- src/modules/tracking/TrackingPage.cpp | 33 +++++++++++++++++++++------ src/modules/tracking/TrackingPage.h | 10 ++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index cb7e5a10a..d206a20a3 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -29,7 +29,6 @@ #include "utils/Logger.h" #include "utils/Retranslator.h" -#include #include #include @@ -42,13 +41,26 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) ui->noneCheckBox->setChecked( true ); connect( ui->noneCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonNoneChecked ); - connect( ui->installCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); - connect( ui->machineCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); - connect( ui->userCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); - connect( ui->installCheckBox, &QCheckBox::stateChanged, [ this ]( int s ) { cDebug() << "Checkbox install changed" << s; } ); - connect( config->installTracking(), &TrackingStyleConfig::trackingChanged, [ config ]() { cDebug() << - "Install tracking configuration changed to " << config->installTracking()->isEnabled(); } ) ; + // Each "panel" of configuration has the same kind of setup, + // where the xButton and xCheckBox is connected to the xTracking + // configuration object; that takes macro-trickery, unfortunately. +#define trackingSetup(x) { \ + connect( ui->x ## CheckBox, &QCheckBox::stateChanged, \ + this, &TrackingPage::buttonChecked ); \ + connect( ui->x ## CheckBox, &QCheckBox::stateChanged, \ + config->x ## Tracking(), QOverload::of( &TrackingStyleConfig::setTracking ) ); \ + connect( config->x ## Tracking(), &TrackingStyleConfig::trackingChanged, \ + this, [ this, config ]() { this->trackerChanged( config->x ## Tracking(), this->ui->x ## Group, this->ui->x ## CheckBox);} ); \ + connect( ui->x ## PolicyButton, &QAbstractButton::clicked, \ + config, [ config ] { QString url( config->x ## Tracking()->policy() ); if ( !url.isEmpty() ) { QDesktopServices::openUrl( url ); } } ); \ +} + + trackingSetup( install ) + trackingSetup( machine ) + trackingSetup( user ) + +#undef trackingSetup connect( config, &Config::generalPolicyChanged, [ this ]( const QString& url ) { this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); @@ -119,3 +131,10 @@ void TrackingPage::buttonChecked(int state) } } } + +void +TrackingPage::trackerChanged(TrackingStyleConfig* config, QWidget* panel, QCheckBox* check) +{ + panel->setVisible( config->isConfigurable() ); + check->setChecked( config->isEnabled() ); +} diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index 1a995870d..48599ead4 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -21,6 +21,7 @@ #include "TrackingType.h" +#include #include #include @@ -30,6 +31,7 @@ class TrackingPage; } class Config; +class TrackingStyleConfig; class TrackingPage : public QWidget { @@ -62,6 +64,14 @@ public Q_SLOTS: void buttonChecked( int state ); private: + /** @brief Apply the tracking configuration to the UI + * + * If the config cannot be changed (disabled in config) then + * hide the UI parts on the @p panel; otherwise show it + * and set @p check state to whether the user has enabled it. + */ + void trackerChanged( TrackingStyleConfig* subconfig, QWidget* panel, QCheckBox* check); + Ui::TrackingPage* ui; }; From 45aac7db6658eacbb8095cf712fc87e24fdb96d0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 07:53:40 -0400 Subject: [PATCH 087/105] CI: update clang-format In clang-format 10, SpaceInEmptyBlock is introduced, and defaults to true .. which is different from the earlier formatting versions did. For now, refuse clang-format 10, and search specifically also for clang-format-9.0.1 because that's what I have on my laptop. At some point, switch in the config option and then require clang-format 10 or later (because earlier versions refuse to run with an unknown config option) --- .clang-format | 1 + ci/calamaresstyle | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index cc430e627..187c3638f 100644 --- a/.clang-format +++ b/.clang-format @@ -26,6 +26,7 @@ ReflowComments: "false" SortIncludes: "true" SpaceAfterCStyleCast: "false" SpacesBeforeTrailingComments: "2" +# SpaceInEmptyBlock: "true" SpacesInAngles: "true" SpacesInParentheses: "true" SpacesInSquareBrackets: "true" diff --git a/ci/calamaresstyle b/ci/calamaresstyle index 6a8285124..44f9fe91f 100755 --- a/ci/calamaresstyle +++ b/ci/calamaresstyle @@ -13,7 +13,7 @@ export LANG LC_ALL LC_NUMERIC AS=$( which astyle ) -CF_VERSIONS="clang-format-7 clang-format-8 clang-format70 clang-format80 clang-format" +CF_VERSIONS="clang-format-7 clang-format-8 clang-format70 clang-format80 clang-format-9.0.1 clang-format" for _cf in $CF_VERSIONS do # Not an error if this particular clang-format isn't found @@ -26,6 +26,8 @@ test -n "$CF" || { echo "! No clang-format ($CF_VERSIONS) found in PATH"; exit 1 test -x "$AS" || { echo "! $AS is not executable."; exit 1 ; } test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; } +expr `"$CF" --version | tr -dc '[^.0-9]' | cut -d . -f 1` '<' 10 > /dev/null || { echo "! $CF is version 10 or later, needs different .clang-format" ; exit 1 ; } + set -e any_dirs=no From 789561be6a6c4f1ff280c6c01bb4688ca3b97bfb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 14:14:06 +0200 Subject: [PATCH 088/105] [tracking] Apply coding style --- src/modules/tracking/Config.cpp | 28 ++++++------ src/modules/tracking/TrackingJobs.cpp | 25 +++++------ src/modules/tracking/TrackingPage.cpp | 53 +++++++++++++---------- src/modules/tracking/TrackingPage.h | 2 +- src/modules/tracking/TrackingViewStep.cpp | 1 - 5 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 30c6c30d1..723465862 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -47,7 +47,7 @@ TrackingStyleConfig::TrackingStyleConfig( QObject* parent ) { } -TrackingStyleConfig::~TrackingStyleConfig() { } +TrackingStyleConfig::~TrackingStyleConfig() {} void TrackingStyleConfig::setTracking( bool enabled ) @@ -179,20 +179,20 @@ Config::Config( QObject* parent ) static void enableLevelsBelow( Config* config, TrackingType level ) { - switch( level ) + switch ( level ) { - case TrackingType::UserTracking: - config->userTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); - FALLTHRU; - case TrackingType::MachineTracking: - config->machineTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); - FALLTHRU; - case TrackingType::InstallTracking: - config->installTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); - break; - case TrackingType::NoTracking: - config->noTracking( true ); - break; + case TrackingType::UserTracking: + config->userTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); + FALLTHRU; + case TrackingType::MachineTracking: + config->machineTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); + FALLTHRU; + case TrackingType::InstallTracking: + config->installTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); + break; + case TrackingType::NoTracking: + config->noTracking( true ); + break; } } diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 3d8ea27f1..cd885194c 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -36,7 +36,7 @@ TrackingInstallJob::TrackingInstallJob( const QString& url ) { } -TrackingInstallJob::~TrackingInstallJob() { } +TrackingInstallJob::~TrackingInstallJob() {} QString TrackingInstallJob::prettyName() const @@ -82,11 +82,10 @@ TrackingInstallJob::addJob( Calamares::JobList& list, InstallTrackingConfig* con if ( config->isEnabled() ) { const auto* s = CalamaresUtils::System::instance(); - QHash map { std::initializer_list< std::pair< QString, QString > > { - { QStringLiteral("CPU"), s->getCpuDescription() }, - { QStringLiteral("MEMORY"), QString::number( s->getTotalMemoryB().first ) }, - { QStringLiteral("DISK"), QString::number( s->getTotalDiskB() ) } - } }; + QHash< QString, QString > map { std::initializer_list< std::pair< QString, QString > > { + { QStringLiteral( "CPU" ), s->getCpuDescription() }, + { QStringLiteral( "MEMORY" ), QString::number( s->getTotalMemoryB().first ) }, + { QStringLiteral( "DISK" ), QString::number( s->getTotalDiskB() ) } } }; QString installUrl = KMacroExpander::expandMacros( config->installTrackingUrl(), map ); cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl; @@ -134,14 +133,14 @@ TrackingMachineUpdateManagerJob::prettyStatusMessage() const Calamares::JobResult TrackingMachineUpdateManagerJob::exec() { - static const auto script = QStringLiteral( "sed -i '/^URI/s,${MACHINE_ID},'`cat /etc/machine-id`',' /etc/update-manager/meta-release || true" ); + static const auto script = QStringLiteral( + "sed -i '/^URI/s,${MACHINE_ID},'`cat /etc/machine-id`',' /etc/update-manager/meta-release || true" ); - auto res = CalamaresUtils::System::instance()->runCommand( - CalamaresUtils::System::RunLocation::RunInTarget, - QStringList { QStringLiteral( "/bin/sh" ) }, - QString(), // Working dir - script, // standard input - std::chrono::seconds( 1 ) ); + auto res = CalamaresUtils::System::instance()->runCommand( CalamaresUtils::System::RunLocation::RunInTarget, + QStringList { QStringLiteral( "/bin/sh" ) }, + QString(), // Working dir + script, // standard input + std::chrono::seconds( 1 ) ); int r = res.first; if ( r == 0 ) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index d206a20a3..c9234d01c 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -45,27 +45,33 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) // Each "panel" of configuration has the same kind of setup, // where the xButton and xCheckBox is connected to the xTracking // configuration object; that takes macro-trickery, unfortunately. -#define trackingSetup(x) { \ - connect( ui->x ## CheckBox, &QCheckBox::stateChanged, \ - this, &TrackingPage::buttonChecked ); \ - connect( ui->x ## CheckBox, &QCheckBox::stateChanged, \ - config->x ## Tracking(), QOverload::of( &TrackingStyleConfig::setTracking ) ); \ - connect( config->x ## Tracking(), &TrackingStyleConfig::trackingChanged, \ - this, [ this, config ]() { this->trackerChanged( config->x ## Tracking(), this->ui->x ## Group, this->ui->x ## CheckBox);} ); \ - connect( ui->x ## PolicyButton, &QAbstractButton::clicked, \ - config, [ config ] { QString url( config->x ## Tracking()->policy() ); if ( !url.isEmpty() ) { QDesktopServices::openUrl( url ); } } ); \ -} +#define trackingSetup( x ) \ + { \ + connect( ui->x##CheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); \ + connect( ui->x##CheckBox, \ + &QCheckBox::stateChanged, \ + config->x##Tracking(), \ + QOverload< bool >::of( &TrackingStyleConfig::setTracking ) ); \ + connect( config->x##Tracking(), &TrackingStyleConfig::trackingChanged, this, [this, config]() { \ + this->trackerChanged( config->x##Tracking(), this->ui->x##Group, this->ui->x##CheckBox ); \ + } ); \ + connect( ui->x##PolicyButton, &QAbstractButton::clicked, config, [config] { \ + QString url( config->x##Tracking()->policy() ); \ + if ( !url.isEmpty() ) \ + { \ + QDesktopServices::openUrl( url ); \ + } \ + } ); \ + } - trackingSetup( install ) - trackingSetup( machine ) - trackingSetup( user ) + trackingSetup( install ) trackingSetup( machine ) trackingSetup( user ) #undef trackingSetup - connect( config, &Config::generalPolicyChanged, [ this ]( const QString& url ) { - this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); - } ); - connect( ui->generalPolicyLabel, &QLabel::linkActivated, [ config ] { + connect( config, &Config::generalPolicyChanged, [this]( const QString& url ) { + this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); + } ); + connect( ui->generalPolicyLabel, &QLabel::linkActivated, [config] { QString url( config->generalPolicy() ); if ( !url.isEmpty() ) { @@ -99,13 +105,15 @@ TrackingPage::retranslate() .arg( product ) ); } -bool TrackingPage::anyOtherChecked() const +bool +TrackingPage::anyOtherChecked() const { - return ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked(); + return ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked(); } -void TrackingPage::buttonNoneChecked(int state) +void +TrackingPage::buttonNoneChecked( int state ) { if ( state ) { @@ -116,7 +124,8 @@ void TrackingPage::buttonNoneChecked(int state) } } -void TrackingPage::buttonChecked(int state) +void +TrackingPage::buttonChecked( int state ) { if ( state ) { @@ -133,7 +142,7 @@ void TrackingPage::buttonChecked(int state) } void -TrackingPage::trackerChanged(TrackingStyleConfig* config, QWidget* panel, QCheckBox* check) +TrackingPage::trackerChanged( TrackingStyleConfig* config, QWidget* panel, QCheckBox* check ) { panel->setVisible( config->isConfigurable() ); check->setChecked( config->isEnabled() ); diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h index 48599ead4..7df43b846 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -70,7 +70,7 @@ private: * hide the UI parts on the @p panel; otherwise show it * and set @p check state to whether the user has enabled it. */ - void trackerChanged( TrackingStyleConfig* subconfig, QWidget* panel, QCheckBox* check); + void trackerChanged( TrackingStyleConfig* subconfig, QWidget* panel, QCheckBox* check ); Ui::TrackingPage* ui; }; diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 125d17974..8a80b2b57 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -122,4 +122,3 @@ TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_config->setConfigurationMap( configurationMap ); } - From 5623d8086bce1785bb26d505d12c5d5595aeaa28 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 14:27:23 +0200 Subject: [PATCH 089/105] [tracking] Apply coding style - massage trackingSetup macro to look like a function call --- src/modules/tracking/TrackingPage.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index c9234d01c..2dfc6050a 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -46,6 +46,7 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) // where the xButton and xCheckBox is connected to the xTracking // configuration object; that takes macro-trickery, unfortunately. #define trackingSetup( x ) \ + do \ { \ connect( ui->x##CheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); \ connect( ui->x##CheckBox, \ @@ -62,15 +63,17 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) QDesktopServices::openUrl( url ); \ } \ } ); \ - } + } while ( false ) - trackingSetup( install ) trackingSetup( machine ) trackingSetup( user ) + trackingSetup( install ); + trackingSetup( machine ); + trackingSetup( user ); #undef trackingSetup - connect( config, &Config::generalPolicyChanged, [this]( const QString& url ) { - this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); - } ); + connect( config, &Config::generalPolicyChanged, [this]( const QString& url ) { + this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); + } ); connect( ui->generalPolicyLabel, &QLabel::linkActivated, [config] { QString url( config->generalPolicy() ); if ( !url.isEmpty() ) From 3f55d415e980ef521fd538f5ee9526f53bd91f0c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 14:26:14 +0200 Subject: [PATCH 090/105] [tracking] Make names of user-tracking styles consistent - use kuserfeedback instead of "kde", to name the technology, not the community --- src/modules/tracking/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 723465862..51e51e7c8 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -154,7 +154,7 @@ UserTrackingConfig::UserTrackingConfig( QObject* parent ) static bool isValidUserTrackingStyle( const QString& s ) { - static QStringList knownStyles { "kde" }; + static QStringList knownStyles { "kuserfeedback" }; return knownStyles.contains( s ); } From 98ab4330c45143201f4f5ce9202c9e95939383a0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 14:52:48 +0200 Subject: [PATCH 091/105] [tracking] expand documentation of configuration --- src/modules/tracking/tracking.conf | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/modules/tracking/tracking.conf b/src/modules/tracking/tracking.conf index 88d1e7b59..533d0e0dd 100644 --- a/src/modules/tracking/tracking.conf +++ b/src/modules/tracking/tracking.conf @@ -28,7 +28,7 @@ # policy applies. # # Each area has a key *enabled*. If the area is enabled, it is shown to -# the user. This defaults to off, which means no tracking would be +# the user. This defaults to false, which means no tracking would be # configured or enabled by Calamares. # # Each area has a key *policy*, which is a Url to be opened when @@ -53,9 +53,11 @@ # page. You **must** provide policy links per-area as well. policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking" -# This is the default level to enable for tracking. If commented out, +# This is the default area to enable for tracking. If commented out, # empty, or otherwise invalid, "none" is used, so no tracking by default. -default: user +# Setting an area here also checks the areas before it (install, machine, +# then user) by default -- subject to those areas being enabled at all. +# default: user # The install area has one specific configuration key: # url: this URL (remember to include the protocol, and prefer https) @@ -73,22 +75,28 @@ default: user install: enabled: false policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking" - # url: "https://example.com/install.php?c=$CPU&m=$MEMORY" + url: "https://example.com/install.php?c=$CPU&m=$MEMORY" # The machine area has one specific configuration key: # style: This string specifies what kind of tracking configuration -# needs to be done. There is currently only one valid -# style, "updatemanager", which edits two files in the installed -# system to enable system-tracking. +# needs to be done. See below for valid styles. # -# Per-style documentation: -# - updatemanager replaces the literal string "${MACHINE_ID}" with the contents of +# Available styles: +# - *updatemanager* replaces the literal string "${MACHINE_ID}" with the contents of # /etc/machine-id, in lines starting with "URI" in the file /etc/update-manager/meta-release machine: enabled: false style: updatemanager policy: "https://github.com/calamares/calamares/wiki/Use-Guide#machine-tracking" -# The user area is not yet implemented, and has no specific configuration. +# The user area has one specific configuration key: +# style: This string specifies what kind of tracking configuration +# needs to be done. See below for valid styles. +# +# Available styles: +# - *kuserfeedback* sets up KUserFeedback tracking (applicable to the KDE +# Plasma Desktop) for each KUserFeedback area listed in *areas*. user: enabled: false + style: kuserfeedback + areas: [ PlasmaUserFeedback ] From e834ce532c35931386eb3e50bf3ff9cce2e84d81 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 15:02:01 +0200 Subject: [PATCH 092/105] [libcalamares] Add variant-map getStringList() convenience --- src/libcalamares/utils/Variant.cpp | 16 +++++++++++++++- src/libcalamares/utils/Variant.h | 7 ++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/Variant.cpp b/src/libcalamares/utils/Variant.cpp index cf6ff91fe..dc20e73b2 100644 --- a/src/libcalamares/utils/Variant.cpp +++ b/src/libcalamares/utils/Variant.cpp @@ -1,5 +1,5 @@ /* === This file is part of Calamares - === - * + * * SPDX-FileCopyrightText: 2013-2016 Teo Mrnjavac * SPDX-FileCopyrightText: 2018 Adriaan de Groot * @@ -65,6 +65,20 @@ getString( const QVariantMap& map, const QString& key ) return QString(); } +QStringList +getStringList( const QVariantMap& map, const QString& key ) +{ + if ( map.contains( key ) ) + { + auto v = map.value( key ); + if ( v.type() == QVariant::StringList ) + { + return v.toStringList(); + } + } + return QStringList(); +} + qint64 getInteger( const QVariantMap& map, const QString& key, qint64 d ) { diff --git a/src/libcalamares/utils/Variant.h b/src/libcalamares/utils/Variant.h index a05d281c3..643d8ae98 100644 --- a/src/libcalamares/utils/Variant.h +++ b/src/libcalamares/utils/Variant.h @@ -1,5 +1,5 @@ /* === This file is part of Calamares - === - * + * * SPDX-FileCopyrightText: 2013-2016 Teo Mrnjavac * SPDX-FileCopyrightText: 2018 Adriaan de Groot * @@ -43,6 +43,11 @@ DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d ); */ DLLEXPORT QString getString( const QVariantMap& map, const QString& key ); +/** + * Get a string list from a mapping; returns empty list if no value. + */ +DLLEXPORT QStringList getStringList( const QVariantMap& map, const QString& key ); + /** * Get an integer value from a mapping; returns @p d if no value. */ From 9b8d591b5dc63279d6bcbd9b6ddb3a78cd59d9d6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 15:11:11 +0200 Subject: [PATCH 093/105] [tracking] Configure user-tracking areas --- src/modules/tracking/Config.cpp | 2 ++ src/modules/tracking/Config.h | 2 ++ src/modules/tracking/TrackingJobs.cpp | 14 ++++++++++---- src/modules/tracking/TrackingJobs.h | 6 ++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp index 51e51e7c8..6d9dbb10b 100644 --- a/src/modules/tracking/Config.cpp +++ b/src/modules/tracking/Config.cpp @@ -165,6 +165,8 @@ UserTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) m_userTrackingStyle = CalamaresUtils::getString( configurationMap, "style" ); validate( m_userTrackingStyle, isValidUserTrackingStyle ); + + m_userTrackingAreas = CalamaresUtils::getStringList( configurationMap, "areas" ); } diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h index 0bdff260a..fb279ea93 100644 --- a/src/modules/tracking/Config.h +++ b/src/modules/tracking/Config.h @@ -149,9 +149,11 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ); QString userTrackingStyle() { return m_userTrackingStyle; } + QStringList userTrackingAreas() const { return m_userTrackingAreas; } private: QString m_userTrackingStyle; + QStringList m_userTrackingAreas; // fine-grained areas }; class Config : public QObject diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index cd885194c..35d51ce64 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -169,7 +169,8 @@ TrackingUserJob::addJob( Calamares::JobList& list, UserTrackingConfig* config ) const auto style = config->userTrackingStyle(); if ( style == "kuserfeedback" ) { - list.append( Calamares::job_ptr( new TrackingKUserFeedbackJob() ) ); + list.append( + Calamares::job_ptr( new TrackingKUserFeedbackJob( QString( "root" ), config->userTrackingAreas() ) ) ); } else { @@ -178,6 +179,12 @@ TrackingUserJob::addJob( Calamares::JobList& list, UserTrackingConfig* config ) } } +TrackingKUserFeedbackJob::TrackingKUserFeedbackJob( const QString& username, const QStringList& areas ) + : m_username( username ) + , m_areas( areas ) +{ +} + QString TrackingKUserFeedbackJob::prettyName() const { @@ -206,10 +213,9 @@ TrackingKUserFeedbackJob::exec() FeedbackLevel=16 )x"; - for ( const QString& area : QStringList { "PlasmaUserFeedback" } ) + for ( const QString& area : m_areas ) { - // TODO: get the configured user name - QString path = QStringLiteral( "/home/%1/.config/%2" ).arg( QString(), area ); + QString path = QStringLiteral( "/home/%1/.config/%2" ).arg( m_username, area ); cDebug() << "Configuring KUserFeedback" << path; int r = CalamaresUtils::System::instance()->createTargetFile( path, config ); diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h index dd5ca6b92..c65c8f621 100644 --- a/src/modules/tracking/TrackingJobs.h +++ b/src/modules/tracking/TrackingJobs.h @@ -114,10 +114,16 @@ public: class TrackingKUserFeedbackJob : public Calamares::Job { public: + TrackingKUserFeedbackJob( const QString& username, const QStringList& areas ); + QString prettyName() const override; QString prettyDescription() const override; QString prettyStatusMessage() const override; Calamares::JobResult exec() override; + +private: + QString m_username; + QStringList m_areas; }; #endif From 47b0fa5d55f4a9f44089c3c4dba3c06fbbe2d317 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 15:24:21 +0200 Subject: [PATCH 094/105] [tracking] Get username from gs --- src/modules/tracking/TrackingJobs.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 35d51ce64..2087804ec 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -20,6 +20,8 @@ #include "Config.h" +#include "GlobalStorage.h" +#include "JobQueue.h" #include "network/Manager.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" @@ -166,11 +168,20 @@ TrackingUserJob::addJob( Calamares::JobList& list, UserTrackingConfig* config ) { if ( config->isEnabled() ) { + const auto* gs = Calamares::JobQueue::instance()->globalStorage(); + static const auto key = QStringLiteral( "username" ); + QString username = ( gs && gs->contains( key ) ) ? gs->value( key ).toString() : QString(); + + if ( username.isEmpty() ) + { + cWarning() << "No username is set in GlobalStorage, skipping user-tracking."; + return; + } + const auto style = config->userTrackingStyle(); if ( style == "kuserfeedback" ) { - list.append( - Calamares::job_ptr( new TrackingKUserFeedbackJob( QString( "root" ), config->userTrackingAreas() ) ) ); + list.append( Calamares::job_ptr( new TrackingKUserFeedbackJob( username, config->userTrackingAreas() ) ) ); } else { From 8ad221311d64d2469bf22fa03c73961f9c3be995 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 17 Jun 2020 15:31:53 +0200 Subject: [PATCH 095/105] [tracking] Can't uncheck 'none' box by itself - If the 'no tracking' box is checked, then the way to uncheck it is to tick some **other** box. - It doesn't make sense to unselect 'none' and then have .. none selected. --- src/modules/tracking/TrackingPage.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 2dfc6050a..618e1bc8f 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -40,6 +40,7 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent ) CALAMARES_RETRANSLATE_SLOT( &TrackingPage::retranslate ); ui->noneCheckBox->setChecked( true ); + ui->noneCheckBox->setEnabled( false ); connect( ui->noneCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonNoneChecked ); // Each "panel" of configuration has the same kind of setup, @@ -124,6 +125,7 @@ TrackingPage::buttonNoneChecked( int state ) ui->installCheckBox->setChecked( false ); ui->machineCheckBox->setChecked( false ); ui->userCheckBox->setChecked( false ); + ui->noneCheckBox->setEnabled( false ); } } @@ -133,6 +135,7 @@ TrackingPage::buttonChecked( int state ) if ( state ) { // Can't have none checked, if another one is + ui->noneCheckBox->setEnabled( true ); ui->noneCheckBox->setChecked( false ); } else @@ -140,6 +143,7 @@ TrackingPage::buttonChecked( int state ) if ( !anyOtherChecked() ) { ui->noneCheckBox->setChecked( true ); + ui->noneCheckBox->setEnabled( false ); } } } From fc91b4ce602bbf08cbe8162df2086205f21c471f Mon Sep 17 00:00:00 2001 From: demmm Date: Wed, 17 Jun 2020 16:52:59 +0200 Subject: [PATCH 096/105] [localeq] use js to get the hasInternet status switching between Map.qml & Offline.qml now happens properly --- src/modules/localeq/localeq.qml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/modules/localeq/localeq.qml b/src/modules/localeq/localeq.qml index 0abdebfc9..ffd87f5b5 100644 --- a/src/modules/localeq/localeq.qml +++ b/src/modules/localeq/localeq.qml @@ -34,6 +34,32 @@ Page { //Needs to come from .conf/geoip property var hasInternet: true + function getInt(format) { + var requestURL = "https://example.org/"; + var xhr = new XMLHttpRequest; + + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + + if (xhr.status !== 200) { + console.log("Disconnected!!"); + var connected = false + hasInternet = connected + return; + } + + else { + console.log("Connected!!"); + } + } + } + xhr.open("GET", requestURL, true); + xhr.send(); + } + Component.onCompleted: { + getInt(); + } + Loader { id: image anchors.horizontalCenter: parent.horizontalCenter From 1b11cc90c43e1d31af444c2e585be79d02e2ab80 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Jun 2020 13:37:43 +0200 Subject: [PATCH 097/105] [tracking] Polish the phrase for 'none' a bit --- src/modules/tracking/page_trackingstep.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/tracking/page_trackingstep.ui b/src/modules/tracking/page_trackingstep.ui index 4383d312d..55a4df094 100644 --- a/src/modules/tracking/page_trackingstep.ui +++ b/src/modules/tracking/page_trackingstep.ui @@ -69,7 +69,7 @@ margin-left: 2em; - <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + <html><head/><body><p>Click here to send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> true From b9b79f11a418ba251bfa08e19032448e7117b0e4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Jun 2020 14:47:33 +0200 Subject: [PATCH 098/105] [unpackfs] Prevent accidental 0777 permissions on / FIXES #1418 --- src/modules/unpackfs/main.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py index ace289092..00de4165d 100644 --- a/src/modules/unpackfs/main.py +++ b/src/modules/unpackfs/main.py @@ -388,6 +388,22 @@ def get_supported_filesystems(): return ["file"] + get_supported_filesystems_kernel() +def repair_root_permissions(root_mount_point): + """ + If the / of the system gets permission 777, change it down + to 755. Any other permission is left alone. This + works around standard behavior from squashfs where + permissions are (easily, accidentally) set to 777. + """ + existing_root_mode = os.stat(root_mount_point).st_mode & 0o777 + if existing_root_mode == 0o777: + try: + os.chmod(root_mount_point, 0o755) # Want / to be rwxr-xr-x + except OSError as e: + utils.warning("Could not set / to safe permissions: {}".format(e)) + # But ignore it + + def run(): """ Unsquash filesystem. @@ -457,6 +473,9 @@ def run(): is_first = False - unpackop = UnpackOperation(unpack) - - return unpackop.run() + repair_root_permissions(root_mount_point) + try: + unpackop = UnpackOperation(unpack) + return unpackop.run() + finally: + repair_root_permissions(root_mount_point) From b2fcc61987ae6759cf7ed1bfe645c6ee41cddfc5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Jun 2020 14:53:19 +0200 Subject: [PATCH 099/105] Changes: pre-release housekeeping --- CHANGES | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index c14167de5..82b70f9af 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,7 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. -# 3.2.26 (unreleased) # +# 3.2.26 (2020-06-18) # This release contains contributions from (alphabetically by first name): - Anke Boersma diff --git a/CMakeLists.txt b/CMakeLists.txt index 9795da8ae..aa5ced95b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ project( CALAMARES VERSION 3.2.26 LANGUAGES C CXX ) -set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development +set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development ### OPTIONS # From 0155d051aabbef8420a9bfb53d43dd1d6c8c0b12 Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Thu, 18 Jun 2020 14:54:44 +0200 Subject: [PATCH 100/105] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_az.ts | 3827 +++++++++++++++++++++++++++++++++++++++ lang/calamares_az_AZ.ts | 3827 +++++++++++++++++++++++++++++++++++++++ lang/calamares_hi.ts | 330 ++-- 3 files changed, 7836 insertions(+), 148 deletions(-) create mode 100644 lang/calamares_az.ts create mode 100644 lang/calamares_az_AZ.ts diff --git a/lang/calamares_az.ts b/lang/calamares_az.ts new file mode 100644 index 000000000..fc250af64 --- /dev/null +++ b/lang/calamares_az.ts @@ -0,0 +1,3827 @@ + + + + + BootInfoWidget + + + The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode. + + + + + This system was started with an <strong>EFI</strong> boot environment.<br><br>To configure startup from an EFI environment, this installer must deploy a boot loader application, like <strong>GRUB</strong> or <strong>systemd-boot</strong> on an <strong>EFI System Partition</strong>. This is automatic, unless you choose manual partitioning, in which case you must choose it or create it on your own. + + + + + This system was started with a <strong>BIOS</strong> boot environment.<br><br>To configure startup from a BIOS environment, this installer must install a boot loader, like <strong>GRUB</strong>, either at the beginning of a partition or on the <strong>Master Boot Record</strong> near the beginning of the partition table (preferred). This is automatic, unless you choose manual partitioning, in which case you must set it up on your own. + + + + + BootLoaderModel + + + Master Boot Record of %1 + + + + + Boot Partition + + + + + System Partition + + + + + Do not install a boot loader + + + + + %1 (%2) + + + + + Calamares::BlankViewStep + + + Blank Page + + + + + Calamares::DebugWindow + + + Form + + + + + GlobalStorage + + + + + JobQueue + + + + + Modules + + + + + Type: + + + + + + none + + + + + Interface: + + + + + Tools + + + + + Reload Stylesheet + + + + + Widget Tree + + + + + Debug information + + + + + Calamares::ExecutionViewStep + + + Set up + + + + + Install + + + + + Calamares::FailJob + + + Job failed (%1) + + + + + Programmed job failure was explicitly requested. + + + + + Calamares::JobThread + + + Done + + + + + Calamares::NamedJob + + + Example job (%1) + + + + + Calamares::ProcessJob + + + Run command '%1' in target system. + + + + + Run command '%1'. + + + + + Running command %1 %2 + + + + + Calamares::PythonJob + + + Running %1 operation. + + + + + Bad working directory path + + + + + Working directory %1 for python job %2 is not readable. + + + + + Bad main script file + + + + + Main script file %1 for python job %2 is not readable. + + + + + Boost.Python error in job "%1". + + + + + Calamares::QmlViewStep + + + Loading ... + + + + + QML Step <i>%1</i>. + + + + + Loading failed. + + + + + Calamares::RequirementsChecker + + + Waiting for %n module(s). + + + + + + + + (%n second(s)) + + + + + + + + System-requirements checking is complete. + + + + + Calamares::ViewManager + + + Setup Failed + + + + + Installation Failed + + + + + Would you like to paste the install log to the web? + + + + + Error + + + + + + &Yes + + + + + + &No + + + + + &Close + + + + + Install Log Paste URL + + + + + The upload was unsuccessful. No web-paste was done. + + + + + Calamares Initialization Failed + + + + + %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. + + + + + <br/>The following modules could not be loaded: + + + + + Continue with setup? + + + + + Continue with installation? + + + + + The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + &Set up now + + + + + &Install now + + + + + Go &back + + + + + &Set up + + + + + &Install + + + + + Setup is complete. Close the setup program. + + + + + The installation is complete. Close the installer. + + + + + Cancel setup without changing the system. + + + + + Cancel installation without changing the system. + + + + + &Next + + + + + &Back + + + + + &Done + + + + + &Cancel + + + + + Cancel setup? + + + + + Cancel installation? + + + + + Do you really want to cancel the current setup process? +The setup program will quit and all changes will be lost. + + + + + Do you really want to cancel the current install process? +The installer will quit and all changes will be lost. + + + + + CalamaresPython::Helper + + + Unknown exception type + + + + + unparseable Python error + + + + + unparseable Python traceback + + + + + Unfetchable Python error. + + + + + CalamaresUtils + + + Install log posted to: +%1 + + + + + CalamaresWindow + + + Show debug information + + + + + &Back + + + + + &Next + + + + + &Cancel + + + + + %1 Setup Program + + + + + %1 Installer + + + + + CheckerContainer + + + Gathering system information... + + + + + ChoicePage + + + Form + + + + + Select storage de&vice: + + + + + + + + Current: + + + + + After: + + + + + <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. Having a GPT partition table and <strong>fat32 512Mb /boot partition is a must for UEFI installs</strong>, either use an existing without formatting or create one. + + + + + Reuse %1 as home partition for %2. + + + + + <strong>Select a partition to shrink, then drag the bottom bar to resize</strong> + + + + + %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. + + + + + Boot loader location: + + + + + <strong>Select a partition to install on</strong> + + + + + An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + + + + <strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device. + + + + + + + + <strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1. + + + + + + + + <strong>Replace a partition</strong><br/>Replaces a partition with %1. + + + + + This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + No Swap + + + + + Reuse Swap + + + + + Swap (no Hibernate) + + + + + Swap (with Hibernate) + + + + + Swap to file + + + + + ClearMountsJob + + + Clear mounts for partitioning operations on %1 + + + + + Clearing mounts for partitioning operations on %1. + + + + + Cleared all mounts for %1 + + + + + ClearTempMountsJob + + + Clear all temporary mounts. + + + + + Clearing all temporary mounts. + + + + + Cannot get list of temporary mounts. + + + + + Cleared all temporary mounts. + + + + + CommandList + + + + Could not run command. + + + + + The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. + + + + + The command needs to know the user's name, but no username is defined. + + + + + Config + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + Network Installation. (Disabled: Incorrect configuration) + + + + + Network Installation. (Disabled: Received invalid groups data) + + + + + Network Installation. (Disabled: internal error) + + + + + Network Installation. (Disabled: Unable to fetch package lists, check your network connection) + + + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + ContextualProcessJob + + + Contextual Processes Job + + + + + CreatePartitionDialog + + + Create a Partition + + + + + Si&ze: + + + + + MiB + + + + + Partition &Type: + + + + + &Primary + + + + + E&xtended + + + + + Fi&le System: + + + + + LVM LV name + + + + + &Mount Point: + + + + + Flags: + + + + + En&crypt + + + + + Logical + + + + + Primary + + + + + GPT + + + + + Mountpoint already in use. Please select another one. + + + + + CreatePartitionJob + + + Create new %2MiB partition on %4 (%3) with file system %1. + + + + + Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. + + + + + Creating new %1 partition on %2. + + + + + The installer failed to create partition on disk '%1'. + + + + + CreatePartitionTableDialog + + + Create Partition Table + + + + + Creating a new partition table will delete all existing data on the disk. + + + + + What kind of partition table do you want to create? + + + + + Master Boot Record (MBR) + + + + + GUID Partition Table (GPT) + + + + + CreatePartitionTableJob + + + Create new %1 partition table on %2. + + + + + Create new <strong>%1</strong> partition table on <strong>%2</strong> (%3). + + + + + Creating new %1 partition table on %2. + + + + + The installer failed to create a partition table on %1. + + + + + CreateUserJob + + + Create user %1 + + + + + Create user <strong>%1</strong>. + + + + + Creating user %1. + + + + + Sudoers dir is not writable. + + + + + Cannot create sudoers file for writing. + + + + + Cannot chmod sudoers file. + + + + + Cannot open groups file for reading. + + + + + CreateVolumeGroupDialog + + + Create Volume Group + + + + + CreateVolumeGroupJob + + + Create new volume group named %1. + + + + + Create new volume group named <strong>%1</strong>. + + + + + Creating new volume group named %1. + + + + + The installer failed to create a volume group named '%1'. + + + + + DeactivateVolumeGroupJob + + + + Deactivate volume group named %1. + + + + + Deactivate volume group named <strong>%1</strong>. + + + + + The installer failed to deactivate a volume group named %1. + + + + + DeletePartitionJob + + + Delete partition %1. + + + + + Delete partition <strong>%1</strong>. + + + + + Deleting partition %1. + + + + + The installer failed to delete partition %1. + + + + + DeviceInfoWidget + + + This device has a <strong>%1</strong> partition table. + + + + + This is a <strong>loop</strong> device.<br><br>It is a pseudo-device with no partition table that makes a file accessible as a block device. This kind of setup usually only contains a single filesystem. + + + + + This installer <strong>cannot detect a partition table</strong> on the selected storage device.<br><br>The device either has no partition table, or the partition table is corrupted or of an unknown type.<br>This installer can create a new partition table for you, either automatically, or through the manual partitioning page. + + + + + <br><br>This is the recommended partition table type for modern systems which start from an <strong>EFI</strong> boot environment. + + + + + <br><br>This partition table type is only advisable on older systems which start from a <strong>BIOS</strong> boot environment. GPT is recommended in most other cases.<br><br><strong>Warning:</strong> the MBR partition table is an obsolete MS-DOS era standard.<br>Only 4 <em>primary</em> partitions may be created, and of those 4, one can be an <em>extended</em> partition, which may in turn contain many <em>logical</em> partitions. + + + + + The type of <strong>partition table</strong> on the selected storage device.<br><br>The only way to change the partition table type is to erase and recreate the partition table from scratch, which destroys all data on the storage device.<br>This installer will keep the current partition table unless you explicitly choose otherwise.<br>If unsure, on modern systems GPT is preferred. + + + + + DeviceModel + + + %1 - %2 (%3) + device[name] - size[number] (device-node[name]) + + + + + %1 - (%2) + device[name] - (device-node[name]) + + + + + DracutLuksCfgJob + + + Write LUKS configuration for Dracut to %1 + + + + + Skip writing LUKS configuration for Dracut: "/" partition is not encrypted + + + + + Failed to open %1 + + + + + DummyCppJob + + + Dummy C++ Job + + + + + EditExistingPartitionDialog + + + Edit Existing Partition + + + + + Content: + + + + + &Keep + + + + + Format + + + + + Warning: Formatting the partition will erase all existing data. + + + + + &Mount Point: + + + + + Si&ze: + + + + + MiB + + + + + Fi&le System: + + + + + Flags: + + + + + Mountpoint already in use. Please select another one. + + + + + EncryptWidget + + + Form + + + + + En&crypt system + + + + + Passphrase + + + + + Confirm passphrase + + + + + Please enter the same passphrase in both boxes. + + + + + FillGlobalStorageJob + + + Set partition information + + + + + Install %1 on <strong>new</strong> %2 system partition. + + + + + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>. + + + + + Install %2 on %3 system partition <strong>%1</strong>. + + + + + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>. + + + + + Install boot loader on <strong>%1</strong>. + + + + + Setting up mount points. + + + + + FinishedPage + + + Form + + + + + &Restart now + + + + + <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> + + + + + <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> + + + + + <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. + + + + + <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. + + + + + FinishedViewStep + + + Finish + + + + + Setup Complete + + + + + Installation Complete + + + + + The setup of %1 is complete. + + + + + The installation of %1 is complete. + + + + + FormatPartitionJob + + + Format partition %1 (file system: %2, size: %3 MiB) on %4. + + + + + Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. + + + + + Formatting partition %1 with file system %2. + + + + + The installer failed to format partition %1 on disk '%2'. + + + + + GeneralRequirements + + + has at least %1 GiB available drive space + + + + + There is not enough drive space. At least %1 GiB is required. + + + + + has at least %1 GiB working memory + + + + + The system does not have enough working memory. At least %1 GiB is required. + + + + + is plugged in to a power source + + + + + The system is not plugged in to a power source. + + + + + is connected to the Internet + + + + + The system is not connected to the Internet. + + + + + is running the installer as an administrator (root) + + + + + The setup program is not running with administrator rights. + + + + + The installer is not running with administrator rights. + + + + + has a screen large enough to show the whole installer + + + + + The screen is too small to display the setup program. + + + + + The screen is too small to display the installer. + + + + + HostInfoJob + + + Collecting information about your machine. + + + + + IDJob + + + + + + OEM Batch Identifier + + + + + Could not create directories <code>%1</code>. + + + + + Could not open file <code>%1</code>. + + + + + Could not write to file <code>%1</code>. + + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + + + InteractiveTerminalPage + + + Konsole not installed + + + + + Please install KDE Konsole and try again! + + + + + Executing script: &nbsp;<code>%1</code> + + + + + InteractiveTerminalViewStep + + + Script + + + + + KeyboardPage + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + KeyboardQmlViewStep + + + Keyboard + + + + + KeyboardViewStep + + + Keyboard + + + + + LCLocaleDialog + + + System locale setting + + + + + The system locale setting affects the language and character set for some command line user interface elements.<br/>The current setting is <strong>%1</strong>. + + + + + &Cancel + + + + + &OK + + + + + LicensePage + + + Form + + + + + <h1>License Agreement</h1> + + + + + I accept the terms and conditions above. + + + + + Please review the End User License Agreements (EULAs). + + + + + This setup procedure will install proprietary software that is subject to licensing terms. + + + + + If you do not agree with the terms, the setup procedure cannot continue. + + + + + This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. + + + + + If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. + + + + + LicenseViewStep + + + License + + + + + LicenseWidget + + + URL: %1 + + + + + <strong>%1 driver</strong><br/>by %2 + %1 is an untranslatable product name, example: Creative Audigy driver + + + + + <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> + %1 is usually a vendor name, example: Nvidia graphics driver + + + + + <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 codec</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 package</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1</strong><br/><font color="Grey">by %2</font> + + + + + File: %1 + + + + + Hide license text + + + + + Show the license text + + + + + Open license agreement in browser. + + + + + LocalePage + + + Region: + + + + + Zone: + + + + + + &Change... + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + LocaleQmlViewStep + + + Location + + + + + LocaleViewStep + + + Location + + + + + LuksBootKeyFileJob + + + Configuring LUKS key file. + + + + + + No partitions are defined. + + + + + + + Encrypted rootfs setup error + + + + + Root partition %1 is LUKS but no passphrase has been set. + + + + + Could not create LUKS key file for root partition %1. + + + + + Could not configure LUKS key file on partition %1. + + + + + MachineIdJob + + + Generate machine-id. + + + + + Configuration Error + + + + + No root mount point is set for MachineId. + + + + + NetInstallViewStep + + + + Package selection + + + + + Office software + + + + + Office package + + + + + Browser software + + + + + Browser package + + + + + Web browser + + + + + Kernel + + + + + Services + + + + + Login + + + + + Desktop + + + + + Applications + + + + + Communication + + + + + Development + + + + + Office + + + + + Multimedia + + + + + Internet + + + + + Theming + + + + + Gaming + + + + + Utilities + + + + + NotesQmlViewStep + + + Notes + + + + + OEMPage + + + Ba&tch: + + + + + <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> + + + + + <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> + + + + + OEMViewStep + + + OEM Configuration + + + + + Set the OEM Batch Identifier to <code>%1</code>. + + + + + PWQ + + + Password is too short + + + + + Password is too long + + + + + Password is too weak + + + + + Memory allocation error when setting '%1' + + + + + Memory allocation error + + + + + The password is the same as the old one + + + + + The password is a palindrome + + + + + The password differs with case changes only + + + + + The password is too similar to the old one + + + + + The password contains the user name in some form + + + + + The password contains words from the real name of the user in some form + + + + + The password contains forbidden words in some form + + + + + The password contains less than %1 digits + + + + + The password contains too few digits + + + + + The password contains less than %1 uppercase letters + + + + + The password contains too few uppercase letters + + + + + The password contains less than %1 lowercase letters + + + + + The password contains too few lowercase letters + + + + + The password contains less than %1 non-alphanumeric characters + + + + + The password contains too few non-alphanumeric characters + + + + + The password is shorter than %1 characters + + + + + The password is too short + + + + + The password is just rotated old one + + + + + The password contains less than %1 character classes + + + + + The password does not contain enough character classes + + + + + The password contains more than %1 same characters consecutively + + + + + The password contains too many same characters consecutively + + + + + The password contains more than %1 characters of the same class consecutively + + + + + The password contains too many characters of the same class consecutively + + + + + The password contains monotonic sequence longer than %1 characters + + + + + The password contains too long of a monotonic character sequence + + + + + No password supplied + + + + + Cannot obtain random numbers from the RNG device + + + + + Password generation failed - required entropy too low for settings + + + + + The password fails the dictionary check - %1 + + + + + The password fails the dictionary check + + + + + Unknown setting - %1 + + + + + Unknown setting + + + + + Bad integer value of setting - %1 + + + + + Bad integer value + + + + + Setting %1 is not of integer type + + + + + Setting is not of integer type + + + + + Setting %1 is not of string type + + + + + Setting is not of string type + + + + + Opening the configuration file failed + + + + + The configuration file is malformed + + + + + Fatal failure + + + + + Unknown error + + + + + Password is empty + + + + + PackageChooserPage + + + Form + + + + + Product Name + + + + + TextLabel + + + + + Long Product Description + + + + + Package Selection + + + + + Please pick a product from the list. The selected product will be installed. + + + + + PackageChooserViewStep + + + Packages + + + + + PackageModel + + + Name + + + + + Description + + + + + Page_Keyboard + + + Form + + + + + Keyboard Model: + + + + + Type here to test your keyboard + + + + + Page_UserSetup + + + Form + + + + + What is your name? + + + + + Your Full Name + + + + + What name do you want to use to log in? + + + + + login + + + + + What is the name of this computer? + + + + + <small>This name will be used if you make the computer visible to others on a network.</small> + + + + + Computer Name + + + + + Choose a password to keep your account safe. + + + + + + <small>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.</small> + + + + + + Password + + + + + + Repeat Password + + + + + When this box is checked, password-strength checking is done and you will not be able to use a weak password. + + + + + Require strong passwords. + + + + + Log in automatically without asking for the password. + + + + + Use the same password for the administrator account. + + + + + Choose a password for the administrator account. + + + + + + <small>Enter the same password twice, so that it can be checked for typing errors.</small> + + + + + PartitionLabelsView + + + Root + + + + + Home + + + + + Boot + + + + + EFI system + + + + + Swap + + + + + New partition for %1 + + + + + New partition + + + + + %1 %2 + size[number] filesystem[name] + + + + + PartitionModel + + + + Free Space + + + + + + New partition + + + + + Name + + + + + File System + + + + + Mount Point + + + + + Size + + + + + PartitionPage + + + Form + + + + + Storage de&vice: + + + + + &Revert All Changes + + + + + New Partition &Table + + + + + Cre&ate + + + + + &Edit + + + + + &Delete + + + + + New Volume Group + + + + + Resize Volume Group + + + + + Deactivate Volume Group + + + + + Remove Volume Group + + + + + I&nstall boot loader on: + + + + + Are you sure you want to create a new partition table on %1? + + + + + Can not create new partition + + + + + The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. + + + + + PartitionViewStep + + + Gathering system information... + + + + + Partitions + + + + + Install %1 <strong>alongside</strong> another operating system. + + + + + <strong>Erase</strong> disk and install %1. + + + + + <strong>Replace</strong> a partition with %1. + + + + + <strong>Manual</strong> partitioning. + + + + + Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3). + + + + + <strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1. + + + + + <strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1. + + + + + <strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2). + + + + + Disk <strong>%1</strong> (%2) + + + + + Current: + + + + + After: + + + + + No EFI system partition configured + + + + + An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. + + + + + An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. + + + + + EFI system partition flag not set + + + + + Option to use GPT on BIOS + + + + + A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. + + + + + Boot partition not encrypted + + + + + A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. + + + + + has at least one disk device available. + + + + + There are no partitions to install on. + + + + + PlasmaLnfJob + + + Plasma Look-and-Feel Job + + + + + + Could not select KDE Plasma Look-and-Feel package + + + + + PlasmaLnfPage + + + Form + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is set up. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + PlasmaLnfViewStep + + + Look-and-Feel + + + + + PreserveFiles + + + Saving files for later ... + + + + + No files configured to save for later. + + + + + Not all of the configured files could be preserved. + + + + + ProcessResult + + + +There was no output from the command. + + + + + +Output: + + + + + + External command crashed. + + + + + Command <i>%1</i> crashed. + + + + + External command failed to start. + + + + + Command <i>%1</i> failed to start. + + + + + Internal error when starting command. + + + + + Bad parameters for process job call. + + + + + External command failed to finish. + + + + + Command <i>%1</i> failed to finish in %2 seconds. + + + + + External command finished with errors. + + + + + Command <i>%1</i> finished with exit code %2. + + + + + QObject + + + %1 (%2) + + + + + Requirements checking for module <i>%1</i> is complete. + + + + + unknown + + + + + extended + + + + + unformatted + + + + + swap + + + + + Default Keyboard Model + + + + + + Default + + + + + + + + File not found + + + + + Path <pre>%1</pre> must be an absolute path. + + + + + Could not create new random file <pre>%1</pre>. + + + + + No product + + + + + No description provided. + + + + + (no mount point) + + + + + Unpartitioned space or unknown partition table + + + + + RemoveUserJob + + + Remove live user from target system + + + + + RemoveVolumeGroupJob + + + + Remove Volume Group named %1. + + + + + Remove Volume Group named <strong>%1</strong>. + + + + + The installer failed to remove a volume group named '%1'. + + + + + ReplaceWidget + + + Form + + + + + Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. + + + + + The selected item does not appear to be a valid partition. + + + + + %1 cannot be installed on empty space. Please select an existing partition. + + + + + %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. + + + + + %1 cannot be installed on this partition. + + + + + Data partition (%1) + + + + + Unknown system partition (%1) + + + + + %1 system partition (%2) + + + + + <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. + + + + + <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + + + <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + ResizeFSJob + + + Resize Filesystem Job + + + + + Invalid configuration + + + + + The file-system resize job has an invalid configuration and will not run. + + + + + KPMCore not Available + + + + + Calamares cannot start KPMCore for the file-system resize job. + + + + + + + + + Resize Failed + + + + + The filesystem %1 could not be found in this system, and cannot be resized. + + + + + The device %1 could not be found in this system, and cannot be resized. + + + + + + The filesystem %1 cannot be resized. + + + + + + The device %1 cannot be resized. + + + + + The filesystem %1 must be resized, but cannot. + + + + + The device %1 must be resized, but cannot + + + + + ResizePartitionJob + + + Resize partition %1. + + + + + Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. + + + + + Resizing %2MiB partition %1 to %3MiB. + + + + + The installer failed to resize partition %1 on disk '%2'. + + + + + ResizeVolumeGroupDialog + + + Resize Volume Group + + + + + ResizeVolumeGroupJob + + + + Resize volume group named %1 from %2 to %3. + + + + + Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. + + + + + The installer failed to resize a volume group named '%1'. + + + + + ResultsListDialog + + + For best results, please ensure that this computer: + + + + + System requirements + + + + + ResultsListWidget + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + ScanningDialog + + + Scanning storage devices... + + + + + Partitioning + + + + + SetHostNameJob + + + Set hostname %1 + + + + + Set hostname <strong>%1</strong>. + + + + + Setting hostname %1. + + + + + + Internal Error + + + + + + Cannot write hostname to target system + + + + + SetKeyboardLayoutJob + + + Set keyboard model to %1, layout to %2-%3 + + + + + Failed to write keyboard configuration for the virtual console. + + + + + + + Failed to write to %1 + + + + + Failed to write keyboard configuration for X11. + + + + + Failed to write keyboard configuration to existing /etc/default directory. + + + + + SetPartFlagsJob + + + Set flags on partition %1. + + + + + Set flags on %1MiB %2 partition. + + + + + Set flags on new partition. + + + + + Clear flags on partition <strong>%1</strong>. + + + + + Clear flags on %1MiB <strong>%2</strong> partition. + + + + + Clear flags on new partition. + + + + + Flag partition <strong>%1</strong> as <strong>%2</strong>. + + + + + Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. + + + + + Flag new partition as <strong>%1</strong>. + + + + + Clearing flags on partition <strong>%1</strong>. + + + + + Clearing flags on %1MiB <strong>%2</strong> partition. + + + + + Clearing flags on new partition. + + + + + Setting flags <strong>%2</strong> on partition <strong>%1</strong>. + + + + + Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. + + + + + Setting flags <strong>%1</strong> on new partition. + + + + + The installer failed to set flags on partition %1. + + + + + SetPasswordJob + + + Set password for user %1 + + + + + Setting password for user %1. + + + + + Bad destination system path. + + + + + rootMountPoint is %1 + + + + + Cannot disable root account. + + + + + passwd terminated with error code %1. + + + + + Cannot set password for user %1. + + + + + usermod terminated with error code %1. + + + + + SetTimezoneJob + + + Set timezone to %1/%2 + + + + + Cannot access selected timezone path. + + + + + Bad path: %1 + + + + + Cannot set timezone. + + + + + Link creation failed, target: %1; link name: %2 + + + + + Cannot set timezone, + + + + + Cannot open /etc/timezone for writing + + + + + ShellProcessJob + + + Shell Processes Job + + + + + SlideCounter + + + %L1 / %L2 + slide counter, %1 of %2 (numeric) + + + + + SummaryPage + + + This is an overview of what will happen once you start the setup procedure. + + + + + This is an overview of what will happen once you start the install procedure. + + + + + SummaryViewStep + + + Summary + + + + + TrackingInstallJob + + + Installation feedback + + + + + Sending installation feedback. + + + + + Internal error in install-tracking. + + + + + HTTP request timed out. + + + + + TrackingMachineNeonJob + + + Machine feedback + + + + + Configuring machine feedback. + + + + + + Error in machine feedback configuration. + + + + + Could not configure machine feedback correctly, script error %1. + + + + + Could not configure machine feedback correctly, Calamares error %1. + + + + + TrackingPage + + + Form + + + + + Placeholder + + + + + <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + + + + + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> + + + + + Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with the last two options below), get continuous information about preferred applications. To see what will be sent, please click the help icon next to each area. + + + + + By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. + + + + + By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. + + + + + By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. + + + + + TrackingViewStep + + + Feedback + + + + + UsersPage + + + <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> + + + + + <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> + + + + + Your username is too long. + + + + + Your username must start with a lowercase letter or underscore. + + + + + Only lowercase letters, numbers, underscore and hyphen are allowed. + + + + + Your hostname is too short. + + + + + Your hostname is too long. + + + + + Only letters, numbers, underscore and hyphen are allowed. + + + + + Your passwords do not match! + + + + + UsersViewStep + + + Users + + + + + VariantModel + + + Key + + + + + Value + + + + + VolumeGroupBaseDialog + + + Create Volume Group + + + + + List of Physical Volumes + + + + + Volume Group Name: + + + + + Volume Group Type: + + + + + Physical Extent Size: + + + + + MiB + + + + + Total Size: + + + + + Used Size: + + + + + Total Sectors: + + + + + Quantity of LVs: + + + + + WelcomePage + + + Form + + + + + + Select application and system language + + + + + &About + + + + + Open donations website + + + + + &Donate + + + + + Open help and support website + + + + + &Support + + + + + Open issues and bug-tracking website + + + + + &Known issues + + + + + Open release notes website + + + + + &Release notes + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + %1 support + + + + + About %1 setup + + + + + About %1 installer + + + + + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. + + + + + WelcomeQmlViewStep + + + Welcome + + + + + WelcomeViewStep + + + Welcome + + + + + about + + + <h1>%1</h1><br/> + <strong>%2<br/> + for %3</strong><br/><br/> + Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + Thanks to <a href='https://calamares.io/team/'>the Calamares team</a> + and the <a href='https://www.transifex.com/calamares/calamares/'>Calamares + translators team</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + development is sponsored by <br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. + + + + + Back + + + + + keyboardq + + + Keyboard Model + + + + + Pick your preferred keyboard model or use the default one based on the detected hardware + + + + + Refresh + + + + + + Layouts + + + + + + Keyboard Layout + + + + + Models + + + + + Variants + + + + + Test your keyboard + + + + + notesqml + + + <h3>%1</h3> + <p>These are example release notes.</p> + + + + + release_notes + + + <h3>%1</h3> + <p>This an example QML file, showing options in RichText with Flickable content.</p> + + <p>QML with RichText can use HTML tags, Flickable content is useful for touchscreens.</p> + + <p><b>This is bold text</b></p> + <p><i>This is italic text</i></p> + <p><u>This is underlined text</u></p> + <p><center>This text will be center-aligned.</center></p> + <p><s>This is strikethrough</s></p> + + <p>Code example: + <code>ls -l /home</code></p> + + <p><b>Lists:</b></p> + <ul> + <li>Intel CPU systems</li> + <li>AMD CPU systems</li> + </ul> + + <p>The vertical scrollbar is adjustable, current width set to 10.</p> + + + + + Back + + + + + welcomeq + + + <h3>Welcome to the %1 <quote>%2</quote> installer</h3> + <p>This program will ask you some questions and set up %1 on your computer.</p> + + + + + About + + + + + Support + + + + + Known issues + + + + + Release notes + + + + + Donate + + + + diff --git a/lang/calamares_az_AZ.ts b/lang/calamares_az_AZ.ts new file mode 100644 index 000000000..65191f080 --- /dev/null +++ b/lang/calamares_az_AZ.ts @@ -0,0 +1,3827 @@ + + + + + BootInfoWidget + + + The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode. + + + + + This system was started with an <strong>EFI</strong> boot environment.<br><br>To configure startup from an EFI environment, this installer must deploy a boot loader application, like <strong>GRUB</strong> or <strong>systemd-boot</strong> on an <strong>EFI System Partition</strong>. This is automatic, unless you choose manual partitioning, in which case you must choose it or create it on your own. + + + + + This system was started with a <strong>BIOS</strong> boot environment.<br><br>To configure startup from a BIOS environment, this installer must install a boot loader, like <strong>GRUB</strong>, either at the beginning of a partition or on the <strong>Master Boot Record</strong> near the beginning of the partition table (preferred). This is automatic, unless you choose manual partitioning, in which case you must set it up on your own. + + + + + BootLoaderModel + + + Master Boot Record of %1 + + + + + Boot Partition + + + + + System Partition + + + + + Do not install a boot loader + + + + + %1 (%2) + + + + + Calamares::BlankViewStep + + + Blank Page + + + + + Calamares::DebugWindow + + + Form + + + + + GlobalStorage + + + + + JobQueue + + + + + Modules + + + + + Type: + + + + + + none + + + + + Interface: + + + + + Tools + + + + + Reload Stylesheet + + + + + Widget Tree + + + + + Debug information + + + + + Calamares::ExecutionViewStep + + + Set up + + + + + Install + + + + + Calamares::FailJob + + + Job failed (%1) + + + + + Programmed job failure was explicitly requested. + + + + + Calamares::JobThread + + + Done + + + + + Calamares::NamedJob + + + Example job (%1) + + + + + Calamares::ProcessJob + + + Run command '%1' in target system. + + + + + Run command '%1'. + + + + + Running command %1 %2 + + + + + Calamares::PythonJob + + + Running %1 operation. + + + + + Bad working directory path + + + + + Working directory %1 for python job %2 is not readable. + + + + + Bad main script file + + + + + Main script file %1 for python job %2 is not readable. + + + + + Boost.Python error in job "%1". + + + + + Calamares::QmlViewStep + + + Loading ... + + + + + QML Step <i>%1</i>. + + + + + Loading failed. + + + + + Calamares::RequirementsChecker + + + Waiting for %n module(s). + + + + + + + + (%n second(s)) + + + + + + + + System-requirements checking is complete. + + + + + Calamares::ViewManager + + + Setup Failed + + + + + Installation Failed + + + + + Would you like to paste the install log to the web? + + + + + Error + + + + + + &Yes + + + + + + &No + + + + + &Close + + + + + Install Log Paste URL + + + + + The upload was unsuccessful. No web-paste was done. + + + + + Calamares Initialization Failed + + + + + %1 can not be installed. Calamares was unable to load all of the configured modules. This is a problem with the way Calamares is being used by the distribution. + + + + + <br/>The following modules could not be loaded: + + + + + Continue with setup? + + + + + Continue with installation? + + + + + The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> + + + + + &Set up now + + + + + &Install now + + + + + Go &back + + + + + &Set up + + + + + &Install + + + + + Setup is complete. Close the setup program. + + + + + The installation is complete. Close the installer. + + + + + Cancel setup without changing the system. + + + + + Cancel installation without changing the system. + + + + + &Next + + + + + &Back + + + + + &Done + + + + + &Cancel + + + + + Cancel setup? + + + + + Cancel installation? + + + + + Do you really want to cancel the current setup process? +The setup program will quit and all changes will be lost. + + + + + Do you really want to cancel the current install process? +The installer will quit and all changes will be lost. + + + + + CalamaresPython::Helper + + + Unknown exception type + + + + + unparseable Python error + + + + + unparseable Python traceback + + + + + Unfetchable Python error. + + + + + CalamaresUtils + + + Install log posted to: +%1 + + + + + CalamaresWindow + + + Show debug information + + + + + &Back + + + + + &Next + + + + + &Cancel + + + + + %1 Setup Program + + + + + %1 Installer + + + + + CheckerContainer + + + Gathering system information... + + + + + ChoicePage + + + Form + + + + + Select storage de&vice: + + + + + + + + Current: + + + + + After: + + + + + <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. Having a GPT partition table and <strong>fat32 512Mb /boot partition is a must for UEFI installs</strong>, either use an existing without formatting or create one. + + + + + Reuse %1 as home partition for %2. + + + + + <strong>Select a partition to shrink, then drag the bottom bar to resize</strong> + + + + + %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. + + + + + Boot loader location: + + + + + <strong>Select a partition to install on</strong> + + + + + An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + + + + <strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device. + + + + + + + + <strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1. + + + + + + + + <strong>Replace a partition</strong><br/>Replaces a partition with %1. + + + + + This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device. + + + + + No Swap + + + + + Reuse Swap + + + + + Swap (no Hibernate) + + + + + Swap (with Hibernate) + + + + + Swap to file + + + + + ClearMountsJob + + + Clear mounts for partitioning operations on %1 + + + + + Clearing mounts for partitioning operations on %1. + + + + + Cleared all mounts for %1 + + + + + ClearTempMountsJob + + + Clear all temporary mounts. + + + + + Clearing all temporary mounts. + + + + + Cannot get list of temporary mounts. + + + + + Cleared all temporary mounts. + + + + + CommandList + + + + Could not run command. + + + + + The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. + + + + + The command needs to know the user's name, but no username is defined. + + + + + Config + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + Network Installation. (Disabled: Incorrect configuration) + + + + + Network Installation. (Disabled: Received invalid groups data) + + + + + Network Installation. (Disabled: internal error) + + + + + Network Installation. (Disabled: Unable to fetch package lists, check your network connection) + + + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + ContextualProcessJob + + + Contextual Processes Job + + + + + CreatePartitionDialog + + + Create a Partition + + + + + Si&ze: + + + + + MiB + + + + + Partition &Type: + + + + + &Primary + + + + + E&xtended + + + + + Fi&le System: + + + + + LVM LV name + + + + + &Mount Point: + + + + + Flags: + + + + + En&crypt + + + + + Logical + + + + + Primary + + + + + GPT + + + + + Mountpoint already in use. Please select another one. + + + + + CreatePartitionJob + + + Create new %2MiB partition on %4 (%3) with file system %1. + + + + + Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. + + + + + Creating new %1 partition on %2. + + + + + The installer failed to create partition on disk '%1'. + + + + + CreatePartitionTableDialog + + + Create Partition Table + + + + + Creating a new partition table will delete all existing data on the disk. + + + + + What kind of partition table do you want to create? + + + + + Master Boot Record (MBR) + + + + + GUID Partition Table (GPT) + + + + + CreatePartitionTableJob + + + Create new %1 partition table on %2. + + + + + Create new <strong>%1</strong> partition table on <strong>%2</strong> (%3). + + + + + Creating new %1 partition table on %2. + + + + + The installer failed to create a partition table on %1. + + + + + CreateUserJob + + + Create user %1 + + + + + Create user <strong>%1</strong>. + + + + + Creating user %1. + + + + + Sudoers dir is not writable. + + + + + Cannot create sudoers file for writing. + + + + + Cannot chmod sudoers file. + + + + + Cannot open groups file for reading. + + + + + CreateVolumeGroupDialog + + + Create Volume Group + + + + + CreateVolumeGroupJob + + + Create new volume group named %1. + + + + + Create new volume group named <strong>%1</strong>. + + + + + Creating new volume group named %1. + + + + + The installer failed to create a volume group named '%1'. + + + + + DeactivateVolumeGroupJob + + + + Deactivate volume group named %1. + + + + + Deactivate volume group named <strong>%1</strong>. + + + + + The installer failed to deactivate a volume group named %1. + + + + + DeletePartitionJob + + + Delete partition %1. + + + + + Delete partition <strong>%1</strong>. + + + + + Deleting partition %1. + + + + + The installer failed to delete partition %1. + + + + + DeviceInfoWidget + + + This device has a <strong>%1</strong> partition table. + + + + + This is a <strong>loop</strong> device.<br><br>It is a pseudo-device with no partition table that makes a file accessible as a block device. This kind of setup usually only contains a single filesystem. + + + + + This installer <strong>cannot detect a partition table</strong> on the selected storage device.<br><br>The device either has no partition table, or the partition table is corrupted or of an unknown type.<br>This installer can create a new partition table for you, either automatically, or through the manual partitioning page. + + + + + <br><br>This is the recommended partition table type for modern systems which start from an <strong>EFI</strong> boot environment. + + + + + <br><br>This partition table type is only advisable on older systems which start from a <strong>BIOS</strong> boot environment. GPT is recommended in most other cases.<br><br><strong>Warning:</strong> the MBR partition table is an obsolete MS-DOS era standard.<br>Only 4 <em>primary</em> partitions may be created, and of those 4, one can be an <em>extended</em> partition, which may in turn contain many <em>logical</em> partitions. + + + + + The type of <strong>partition table</strong> on the selected storage device.<br><br>The only way to change the partition table type is to erase and recreate the partition table from scratch, which destroys all data on the storage device.<br>This installer will keep the current partition table unless you explicitly choose otherwise.<br>If unsure, on modern systems GPT is preferred. + + + + + DeviceModel + + + %1 - %2 (%3) + device[name] - size[number] (device-node[name]) + + + + + %1 - (%2) + device[name] - (device-node[name]) + + + + + DracutLuksCfgJob + + + Write LUKS configuration for Dracut to %1 + + + + + Skip writing LUKS configuration for Dracut: "/" partition is not encrypted + + + + + Failed to open %1 + + + + + DummyCppJob + + + Dummy C++ Job + + + + + EditExistingPartitionDialog + + + Edit Existing Partition + + + + + Content: + + + + + &Keep + + + + + Format + + + + + Warning: Formatting the partition will erase all existing data. + + + + + &Mount Point: + + + + + Si&ze: + + + + + MiB + + + + + Fi&le System: + + + + + Flags: + + + + + Mountpoint already in use. Please select another one. + + + + + EncryptWidget + + + Form + + + + + En&crypt system + + + + + Passphrase + + + + + Confirm passphrase + + + + + Please enter the same passphrase in both boxes. + + + + + FillGlobalStorageJob + + + Set partition information + + + + + Install %1 on <strong>new</strong> %2 system partition. + + + + + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>. + + + + + Install %2 on %3 system partition <strong>%1</strong>. + + + + + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>. + + + + + Install boot loader on <strong>%1</strong>. + + + + + Setting up mount points. + + + + + FinishedPage + + + Form + + + + + &Restart now + + + + + <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> + + + + + <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. + + + + + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> + + + + + <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. + + + + + <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. + + + + + FinishedViewStep + + + Finish + + + + + Setup Complete + + + + + Installation Complete + + + + + The setup of %1 is complete. + + + + + The installation of %1 is complete. + + + + + FormatPartitionJob + + + Format partition %1 (file system: %2, size: %3 MiB) on %4. + + + + + Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. + + + + + Formatting partition %1 with file system %2. + + + + + The installer failed to format partition %1 on disk '%2'. + + + + + GeneralRequirements + + + has at least %1 GiB available drive space + + + + + There is not enough drive space. At least %1 GiB is required. + + + + + has at least %1 GiB working memory + + + + + The system does not have enough working memory. At least %1 GiB is required. + + + + + is plugged in to a power source + + + + + The system is not plugged in to a power source. + + + + + is connected to the Internet + + + + + The system is not connected to the Internet. + + + + + is running the installer as an administrator (root) + + + + + The setup program is not running with administrator rights. + + + + + The installer is not running with administrator rights. + + + + + has a screen large enough to show the whole installer + + + + + The screen is too small to display the setup program. + + + + + The screen is too small to display the installer. + + + + + HostInfoJob + + + Collecting information about your machine. + + + + + IDJob + + + + + + OEM Batch Identifier + + + + + Could not create directories <code>%1</code>. + + + + + Could not open file <code>%1</code>. + + + + + Could not write to file <code>%1</code>. + + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + + + InteractiveTerminalPage + + + Konsole not installed + + + + + Please install KDE Konsole and try again! + + + + + Executing script: &nbsp;<code>%1</code> + + + + + InteractiveTerminalViewStep + + + Script + + + + + KeyboardPage + + + Set keyboard model to %1.<br/> + + + + + Set keyboard layout to %1/%2. + + + + + KeyboardQmlViewStep + + + Keyboard + + + + + KeyboardViewStep + + + Keyboard + + + + + LCLocaleDialog + + + System locale setting + + + + + The system locale setting affects the language and character set for some command line user interface elements.<br/>The current setting is <strong>%1</strong>. + + + + + &Cancel + + + + + &OK + + + + + LicensePage + + + Form + + + + + <h1>License Agreement</h1> + + + + + I accept the terms and conditions above. + + + + + Please review the End User License Agreements (EULAs). + + + + + This setup procedure will install proprietary software that is subject to licensing terms. + + + + + If you do not agree with the terms, the setup procedure cannot continue. + + + + + This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. + + + + + If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. + + + + + LicenseViewStep + + + License + + + + + LicenseWidget + + + URL: %1 + + + + + <strong>%1 driver</strong><br/>by %2 + %1 is an untranslatable product name, example: Creative Audigy driver + + + + + <strong>%1 graphics driver</strong><br/><font color="Grey">by %2</font> + %1 is usually a vendor name, example: Nvidia graphics driver + + + + + <strong>%1 browser plugin</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 codec</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1 package</strong><br/><font color="Grey">by %2</font> + + + + + <strong>%1</strong><br/><font color="Grey">by %2</font> + + + + + File: %1 + + + + + Hide license text + + + + + Show the license text + + + + + Open license agreement in browser. + + + + + LocalePage + + + Region: + + + + + Zone: + + + + + + &Change... + + + + + The system language will be set to %1. + + + + + The numbers and dates locale will be set to %1. + + + + + Set timezone to %1/%2.<br/> + + + + + LocaleQmlViewStep + + + Location + + + + + LocaleViewStep + + + Location + + + + + LuksBootKeyFileJob + + + Configuring LUKS key file. + + + + + + No partitions are defined. + + + + + + + Encrypted rootfs setup error + + + + + Root partition %1 is LUKS but no passphrase has been set. + + + + + Could not create LUKS key file for root partition %1. + + + + + Could not configure LUKS key file on partition %1. + + + + + MachineIdJob + + + Generate machine-id. + + + + + Configuration Error + + + + + No root mount point is set for MachineId. + + + + + NetInstallViewStep + + + + Package selection + + + + + Office software + + + + + Office package + + + + + Browser software + + + + + Browser package + + + + + Web browser + + + + + Kernel + + + + + Services + + + + + Login + + + + + Desktop + + + + + Applications + + + + + Communication + + + + + Development + + + + + Office + + + + + Multimedia + + + + + Internet + + + + + Theming + + + + + Gaming + + + + + Utilities + + + + + NotesQmlViewStep + + + Notes + + + + + OEMPage + + + Ba&tch: + + + + + <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> + + + + + <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> + + + + + OEMViewStep + + + OEM Configuration + + + + + Set the OEM Batch Identifier to <code>%1</code>. + + + + + PWQ + + + Password is too short + + + + + Password is too long + + + + + Password is too weak + + + + + Memory allocation error when setting '%1' + + + + + Memory allocation error + + + + + The password is the same as the old one + + + + + The password is a palindrome + + + + + The password differs with case changes only + + + + + The password is too similar to the old one + + + + + The password contains the user name in some form + + + + + The password contains words from the real name of the user in some form + + + + + The password contains forbidden words in some form + + + + + The password contains less than %1 digits + + + + + The password contains too few digits + + + + + The password contains less than %1 uppercase letters + + + + + The password contains too few uppercase letters + + + + + The password contains less than %1 lowercase letters + + + + + The password contains too few lowercase letters + + + + + The password contains less than %1 non-alphanumeric characters + + + + + The password contains too few non-alphanumeric characters + + + + + The password is shorter than %1 characters + + + + + The password is too short + + + + + The password is just rotated old one + + + + + The password contains less than %1 character classes + + + + + The password does not contain enough character classes + + + + + The password contains more than %1 same characters consecutively + + + + + The password contains too many same characters consecutively + + + + + The password contains more than %1 characters of the same class consecutively + + + + + The password contains too many characters of the same class consecutively + + + + + The password contains monotonic sequence longer than %1 characters + + + + + The password contains too long of a monotonic character sequence + + + + + No password supplied + + + + + Cannot obtain random numbers from the RNG device + + + + + Password generation failed - required entropy too low for settings + + + + + The password fails the dictionary check - %1 + + + + + The password fails the dictionary check + + + + + Unknown setting - %1 + + + + + Unknown setting + + + + + Bad integer value of setting - %1 + + + + + Bad integer value + + + + + Setting %1 is not of integer type + + + + + Setting is not of integer type + + + + + Setting %1 is not of string type + + + + + Setting is not of string type + + + + + Opening the configuration file failed + + + + + The configuration file is malformed + + + + + Fatal failure + + + + + Unknown error + + + + + Password is empty + + + + + PackageChooserPage + + + Form + + + + + Product Name + + + + + TextLabel + + + + + Long Product Description + + + + + Package Selection + + + + + Please pick a product from the list. The selected product will be installed. + + + + + PackageChooserViewStep + + + Packages + + + + + PackageModel + + + Name + + + + + Description + + + + + Page_Keyboard + + + Form + + + + + Keyboard Model: + + + + + Type here to test your keyboard + + + + + Page_UserSetup + + + Form + + + + + What is your name? + + + + + Your Full Name + + + + + What name do you want to use to log in? + + + + + login + + + + + What is the name of this computer? + + + + + <small>This name will be used if you make the computer visible to others on a network.</small> + + + + + Computer Name + + + + + Choose a password to keep your account safe. + + + + + + <small>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.</small> + + + + + + Password + + + + + + Repeat Password + + + + + When this box is checked, password-strength checking is done and you will not be able to use a weak password. + + + + + Require strong passwords. + + + + + Log in automatically without asking for the password. + + + + + Use the same password for the administrator account. + + + + + Choose a password for the administrator account. + + + + + + <small>Enter the same password twice, so that it can be checked for typing errors.</small> + + + + + PartitionLabelsView + + + Root + + + + + Home + + + + + Boot + + + + + EFI system + + + + + Swap + + + + + New partition for %1 + + + + + New partition + + + + + %1 %2 + size[number] filesystem[name] + + + + + PartitionModel + + + + Free Space + + + + + + New partition + + + + + Name + + + + + File System + + + + + Mount Point + + + + + Size + + + + + PartitionPage + + + Form + + + + + Storage de&vice: + + + + + &Revert All Changes + + + + + New Partition &Table + + + + + Cre&ate + + + + + &Edit + + + + + &Delete + + + + + New Volume Group + + + + + Resize Volume Group + + + + + Deactivate Volume Group + + + + + Remove Volume Group + + + + + I&nstall boot loader on: + + + + + Are you sure you want to create a new partition table on %1? + + + + + Can not create new partition + + + + + The partition table on %1 already has %2 primary partitions, and no more can be added. Please remove one primary partition and add an extended partition, instead. + + + + + PartitionViewStep + + + Gathering system information... + + + + + Partitions + + + + + Install %1 <strong>alongside</strong> another operating system. + + + + + <strong>Erase</strong> disk and install %1. + + + + + <strong>Replace</strong> a partition with %1. + + + + + <strong>Manual</strong> partitioning. + + + + + Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3). + + + + + <strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1. + + + + + <strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1. + + + + + <strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2). + + + + + Disk <strong>%1</strong> (%2) + + + + + Current: + + + + + After: + + + + + No EFI system partition configured + + + + + An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. + + + + + An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. + + + + + EFI system partition flag not set + + + + + Option to use GPT on BIOS + + + + + A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. + + + + + Boot partition not encrypted + + + + + A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. + + + + + has at least one disk device available. + + + + + There are no partitions to install on. + + + + + PlasmaLnfJob + + + Plasma Look-and-Feel Job + + + + + + Could not select KDE Plasma Look-and-Feel package + + + + + PlasmaLnfPage + + + Form + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is set up. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed. Clicking on a look-and-feel selection will give you a live preview of that look-and-feel. + + + + + PlasmaLnfViewStep + + + Look-and-Feel + + + + + PreserveFiles + + + Saving files for later ... + + + + + No files configured to save for later. + + + + + Not all of the configured files could be preserved. + + + + + ProcessResult + + + +There was no output from the command. + + + + + +Output: + + + + + + External command crashed. + + + + + Command <i>%1</i> crashed. + + + + + External command failed to start. + + + + + Command <i>%1</i> failed to start. + + + + + Internal error when starting command. + + + + + Bad parameters for process job call. + + + + + External command failed to finish. + + + + + Command <i>%1</i> failed to finish in %2 seconds. + + + + + External command finished with errors. + + + + + Command <i>%1</i> finished with exit code %2. + + + + + QObject + + + %1 (%2) + + + + + Requirements checking for module <i>%1</i> is complete. + + + + + unknown + + + + + extended + + + + + unformatted + + + + + swap + + + + + Default Keyboard Model + + + + + + Default + + + + + + + + File not found + + + + + Path <pre>%1</pre> must be an absolute path. + + + + + Could not create new random file <pre>%1</pre>. + + + + + No product + + + + + No description provided. + + + + + (no mount point) + + + + + Unpartitioned space or unknown partition table + + + + + RemoveUserJob + + + Remove live user from target system + + + + + RemoveVolumeGroupJob + + + + Remove Volume Group named %1. + + + + + Remove Volume Group named <strong>%1</strong>. + + + + + The installer failed to remove a volume group named '%1'. + + + + + ReplaceWidget + + + Form + + + + + Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. + + + + + The selected item does not appear to be a valid partition. + + + + + %1 cannot be installed on empty space. Please select an existing partition. + + + + + %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. + + + + + %1 cannot be installed on this partition. + + + + + Data partition (%1) + + + + + Unknown system partition (%1) + + + + + %1 system partition (%2) + + + + + <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. + + + + + <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. + + + + + + + <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. + + + + + The EFI system partition at %1 will be used for starting %2. + + + + + EFI system partition: + + + + + ResizeFSJob + + + Resize Filesystem Job + + + + + Invalid configuration + + + + + The file-system resize job has an invalid configuration and will not run. + + + + + KPMCore not Available + + + + + Calamares cannot start KPMCore for the file-system resize job. + + + + + + + + + Resize Failed + + + + + The filesystem %1 could not be found in this system, and cannot be resized. + + + + + The device %1 could not be found in this system, and cannot be resized. + + + + + + The filesystem %1 cannot be resized. + + + + + + The device %1 cannot be resized. + + + + + The filesystem %1 must be resized, but cannot. + + + + + The device %1 must be resized, but cannot + + + + + ResizePartitionJob + + + Resize partition %1. + + + + + Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. + + + + + Resizing %2MiB partition %1 to %3MiB. + + + + + The installer failed to resize partition %1 on disk '%2'. + + + + + ResizeVolumeGroupDialog + + + Resize Volume Group + + + + + ResizeVolumeGroupJob + + + + Resize volume group named %1 from %2 to %3. + + + + + Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. + + + + + The installer failed to resize a volume group named '%1'. + + + + + ResultsListDialog + + + For best results, please ensure that this computer: + + + + + System requirements + + + + + ResultsListWidget + + + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> + + + + + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. + + + + + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. + + + + + This program will ask you some questions and set up %2 on your computer. + + + + + ScanningDialog + + + Scanning storage devices... + + + + + Partitioning + + + + + SetHostNameJob + + + Set hostname %1 + + + + + Set hostname <strong>%1</strong>. + + + + + Setting hostname %1. + + + + + + Internal Error + + + + + + Cannot write hostname to target system + + + + + SetKeyboardLayoutJob + + + Set keyboard model to %1, layout to %2-%3 + + + + + Failed to write keyboard configuration for the virtual console. + + + + + + + Failed to write to %1 + + + + + Failed to write keyboard configuration for X11. + + + + + Failed to write keyboard configuration to existing /etc/default directory. + + + + + SetPartFlagsJob + + + Set flags on partition %1. + + + + + Set flags on %1MiB %2 partition. + + + + + Set flags on new partition. + + + + + Clear flags on partition <strong>%1</strong>. + + + + + Clear flags on %1MiB <strong>%2</strong> partition. + + + + + Clear flags on new partition. + + + + + Flag partition <strong>%1</strong> as <strong>%2</strong>. + + + + + Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. + + + + + Flag new partition as <strong>%1</strong>. + + + + + Clearing flags on partition <strong>%1</strong>. + + + + + Clearing flags on %1MiB <strong>%2</strong> partition. + + + + + Clearing flags on new partition. + + + + + Setting flags <strong>%2</strong> on partition <strong>%1</strong>. + + + + + Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. + + + + + Setting flags <strong>%1</strong> on new partition. + + + + + The installer failed to set flags on partition %1. + + + + + SetPasswordJob + + + Set password for user %1 + + + + + Setting password for user %1. + + + + + Bad destination system path. + + + + + rootMountPoint is %1 + + + + + Cannot disable root account. + + + + + passwd terminated with error code %1. + + + + + Cannot set password for user %1. + + + + + usermod terminated with error code %1. + + + + + SetTimezoneJob + + + Set timezone to %1/%2 + + + + + Cannot access selected timezone path. + + + + + Bad path: %1 + + + + + Cannot set timezone. + + + + + Link creation failed, target: %1; link name: %2 + + + + + Cannot set timezone, + + + + + Cannot open /etc/timezone for writing + + + + + ShellProcessJob + + + Shell Processes Job + + + + + SlideCounter + + + %L1 / %L2 + slide counter, %1 of %2 (numeric) + + + + + SummaryPage + + + This is an overview of what will happen once you start the setup procedure. + + + + + This is an overview of what will happen once you start the install procedure. + + + + + SummaryViewStep + + + Summary + + + + + TrackingInstallJob + + + Installation feedback + + + + + Sending installation feedback. + + + + + Internal error in install-tracking. + + + + + HTTP request timed out. + + + + + TrackingMachineNeonJob + + + Machine feedback + + + + + Configuring machine feedback. + + + + + + Error in machine feedback configuration. + + + + + Could not configure machine feedback correctly, script error %1. + + + + + Could not configure machine feedback correctly, Calamares error %1. + + + + + TrackingPage + + + Form + + + + + Placeholder + + + + + <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + + + + + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> + + + + + Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with the last two options below), get continuous information about preferred applications. To see what will be sent, please click the help icon next to each area. + + + + + By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. + + + + + By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. + + + + + By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. + + + + + TrackingViewStep + + + Feedback + + + + + UsersPage + + + <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> + + + + + <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> + + + + + Your username is too long. + + + + + Your username must start with a lowercase letter or underscore. + + + + + Only lowercase letters, numbers, underscore and hyphen are allowed. + + + + + Your hostname is too short. + + + + + Your hostname is too long. + + + + + Only letters, numbers, underscore and hyphen are allowed. + + + + + Your passwords do not match! + + + + + UsersViewStep + + + Users + + + + + VariantModel + + + Key + + + + + Value + + + + + VolumeGroupBaseDialog + + + Create Volume Group + + + + + List of Physical Volumes + + + + + Volume Group Name: + + + + + Volume Group Type: + + + + + Physical Extent Size: + + + + + MiB + + + + + Total Size: + + + + + Used Size: + + + + + Total Sectors: + + + + + Quantity of LVs: + + + + + WelcomePage + + + Form + + + + + + Select application and system language + + + + + &About + + + + + Open donations website + + + + + &Donate + + + + + Open help and support website + + + + + &Support + + + + + Open issues and bug-tracking website + + + + + &Known issues + + + + + Open release notes website + + + + + &Release notes + + + + + <h1>Welcome to the Calamares setup program for %1.</h1> + + + + + <h1>Welcome to %1 setup.</h1> + + + + + <h1>Welcome to the Calamares installer for %1.</h1> + + + + + <h1>Welcome to the %1 installer.</h1> + + + + + %1 support + + + + + About %1 setup + + + + + About %1 installer + + + + + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. + + + + + WelcomeQmlViewStep + + + Welcome + + + + + WelcomeViewStep + + + Welcome + + + + + about + + + <h1>%1</h1><br/> + <strong>%2<br/> + for %3</strong><br/><br/> + Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + Thanks to <a href='https://calamares.io/team/'>the Calamares team</a> + and the <a href='https://www.transifex.com/calamares/calamares/'>Calamares + translators team</a>.<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + development is sponsored by <br/> + <a href='http://www.blue-systems.com/'>Blue Systems</a> - + Liberating Software. + + + + + Back + + + + + keyboardq + + + Keyboard Model + + + + + Pick your preferred keyboard model or use the default one based on the detected hardware + + + + + Refresh + + + + + + Layouts + + + + + + Keyboard Layout + + + + + Models + + + + + Variants + + + + + Test your keyboard + + + + + notesqml + + + <h3>%1</h3> + <p>These are example release notes.</p> + + + + + release_notes + + + <h3>%1</h3> + <p>This an example QML file, showing options in RichText with Flickable content.</p> + + <p>QML with RichText can use HTML tags, Flickable content is useful for touchscreens.</p> + + <p><b>This is bold text</b></p> + <p><i>This is italic text</i></p> + <p><u>This is underlined text</u></p> + <p><center>This text will be center-aligned.</center></p> + <p><s>This is strikethrough</s></p> + + <p>Code example: + <code>ls -l /home</code></p> + + <p><b>Lists:</b></p> + <ul> + <li>Intel CPU systems</li> + <li>AMD CPU systems</li> + </ul> + + <p>The vertical scrollbar is adjustable, current width set to 10.</p> + + + + + Back + + + + + welcomeq + + + <h3>Welcome to the %1 <quote>%2</quote> installer</h3> + <p>This program will ask you some questions and set up %1 on your computer.</p> + + + + + About + + + + + Support + + + + + Known issues + + + + + Release notes + + + + + Donate + + + + diff --git a/lang/calamares_hi.ts b/lang/calamares_hi.ts index 60121a630..2d47397e6 100644 --- a/lang/calamares_hi.ts +++ b/lang/calamares_hi.ts @@ -16,7 +16,7 @@ This system was started with a <strong>BIOS</strong> boot environment.<br><br>To configure startup from a BIOS environment, this installer must install a boot loader, like <strong>GRUB</strong>, either at the beginning of a partition or on the <strong>Master Boot Record</strong> near the beginning of the partition table (preferred). This is automatic, unless you choose manual partitioning, in which case you must set it up on your own. - यह सिस्टम <strong>BIOS</strong>बूट वातावरण के साथ शुरू किया गया।<br><br>BIOS वातावरण से स्टार्टअप विन्यस्त करने के लिए इंस्टॉलर को <strong>GRUB</strong> जैसे बूट लोडर को, या तो विभाजन की शुरुआत में या फिर <strong>मास्टर बूट रिकॉर्ड</strong> पर विभाजन तालिका की शुरुआत में इंस्टॉल (सुझाया जाता है) करना होगा। यह स्वत: होता है, परंतु अगर आप मैनुअल विभाजन करना चुनते है; तो आपको इसे खुद ही बनाना होगा। + यह सिस्टम <strong>BIOS</strong>बूट वातावरण के साथ शुरू किया गया।<br><br>BIOS वातावरण से स्टार्टअप विन्यस्त करने के लिए इंस्टॉलर को <strong>GRUB</strong> जैसे बूट लोडर को, या तो विभाजन की शुरुआत में या फिर <strong>Master Boot Record</strong> पर विभाजन तालिका की शुरुआत में इंस्टॉल (सुझाया जाता है) करना होगा। यह स्वत: होता है, परंतु अगर आप मैनुअल विभाजन करना चुनते है; तो आपको इसे खुद ही बनाना होगा। @@ -65,7 +65,7 @@ GlobalStorage - ग्लोबल स्टोरेज + GlobalStorage @@ -80,7 +80,7 @@ Type: - प्रकार : + प्रकार @@ -111,7 +111,7 @@ Debug information - डीबग जानकारी + डीबग संबंधी जानकारी @@ -145,7 +145,7 @@ Done - पूर्ण हुआ + पूर्ण @@ -161,7 +161,7 @@ Run command '%1' in target system. - लक्षित सिस्टम में कमांड '%1' चलाएँ। + लक्षित सिस्टम पर कमांड '%1' चलाएँ। @@ -189,17 +189,17 @@ Working directory %1 for python job %2 is not readable. - पाइथन कार्य %2 के लिए कार्यरत डायरेक्टरी %1 रीड करने योग्य नहीं है। + पाइथन कार्य %2 हेतु कार्यरत डायरेक्टरी %1 रीड योग्य नहीं है। Bad main script file - ख़राब मुख्य स्क्रिप्ट फ़ाइल + गलत मुख्य स्क्रिप्ट फ़ाइल Main script file %1 for python job %2 is not readable. - पाइथन कार्य %2 हेतु मुख्य स्क्रिप्ट फ़ाइल %1 रीड करने योग्य नहीं है। + पाइथन कार्य %2 हेतु मुख्य स्क्रिप्ट फ़ाइल %1 रीड योग्य नहीं है। @@ -212,17 +212,17 @@ Loading ... - + लोड हो रहा है ... QML Step <i>%1</i>. - + QML चरण <i>%1</i>। Loading failed. - + लोड करना विफल रहा। @@ -259,12 +259,12 @@ Installation Failed - इंस्टॉल विफल रहा + इंस्टॉल विफल रहा। Would you like to paste the install log to the web? - + क्या आप इंस्टॉल प्रक्रिया की लॉग फ़ाइल इंटरनेट पर पेस्ट करना चाहेंगे ? @@ -291,12 +291,12 @@ Install Log Paste URL - + इंस्टॉल प्रक्रिया की लॉग फ़ाइल पेस्ट करें The upload was unsuccessful. No web-paste was done. - अपलोड असफल रहा। कोई वेब-पेस्ट नही किया गया। + अपलोड विफल रहा। इंटरनेट पर पेस्ट नहीं हो सका। @@ -331,7 +331,7 @@ The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> - %2 इंस्टॉल करने हेतु %1 इंस्टॉलर आपकी डिस्क में बदलाव करने वाला है।<br/><strong>आप इन बदलावों को पूर्ववत नहीं कर पाएंगे।</strong> + %2 इंस्टॉल करने के लिए %1 इंस्टॉलर आपकी डिस्क में बदलाव करने वाला है।<br/><strong>आप इन बदलावों को पूर्ववत नहीं कर पाएंगे।</strong> @@ -428,7 +428,7 @@ The installer will quit and all changes will be lost. Unknown exception type - अपवाद का प्रकार अज्ञात + अपवाद का प्रकार अज्ञात है @@ -443,7 +443,7 @@ The installer will quit and all changes will be lost. Unfetchable Python error. - पहुँच से बाहर पाइथन त्रुटि। + अप्राप्य पाइथन त्रुटि। @@ -452,7 +452,8 @@ The installer will quit and all changes will be lost. Install log posted to: %1 - + इंस्टॉल प्रक्रिया की लॉग फ़ाइल, यहाँ पेस्ट की गई : +%1 @@ -460,7 +461,7 @@ The installer will quit and all changes will be lost. Show debug information - डीबग जानकारी दिखाएँ + डीबग संबंधी जानकारी दिखाएँ @@ -519,12 +520,12 @@ The installer will quit and all changes will be lost. After: - बाद में : + बाद में: <strong>Manual partitioning</strong><br/>You can create or resize partitions yourself. Having a GPT partition table and <strong>fat32 512Mb /boot partition is a must for UEFI installs</strong>, either use an existing without formatting or create one. - + <strong>मैनुअल विभाजन</strong><br/>आप स्वयं भी विभाजन बना व उनका आकार बदल सकते है। UEFI इंस्टॉल के लिए GPT विभाजन तालिका और <strong>fat32 512Mb का /boot विभाजन होना जरूरी है</strong>, या तो पहले से मौजूद को ही बिना फॉर्मेट किए इस्तेमाल करें या फिर नया बनाएँ। @@ -534,7 +535,7 @@ The installer will quit and all changes will be lost. <strong>Select a partition to shrink, then drag the bottom bar to resize</strong> - <strong>छोटा करने हेतु विभाजन चुनें, फिर नीचे bar से उसका आकर सेट करें</strong> + <strong>छोटा करने के लिए विभाजन चुनें, फिर नीचे bar से उसका आकर सेट करें</strong> @@ -544,12 +545,12 @@ The installer will quit and all changes will be lost. Boot loader location: - बूट लोडर का स्थान : + बूट लोडर का स्थान: <strong>Select a partition to install on</strong> - <strong>इंस्टॉल हेतु विभाजन चुनें</strong> + <strong>इंस्टॉल के लिए विभाजन चुनें</strong> @@ -651,7 +652,7 @@ The installer will quit and all changes will be lost. Cleared all mounts for %1 - %1 हेतु सभी माउंट हटा दिए गए + %1 के लिए सभी माउंट हटा दिए गए @@ -726,7 +727,7 @@ The installer will quit and all changes will be lost. Network Installation. (Disabled: Incorrect configuration) - + नेटवर्क इंस्टॉल। (निष्क्रिय : गलत विन्यास) @@ -736,7 +737,7 @@ The installer will quit and all changes will be lost. Network Installation. (Disabled: internal error) - + नेटवर्क इंस्टॉल। (निष्क्रिय : आंतरिक त्रुटि) @@ -746,27 +747,27 @@ The installer will quit and all changes will be lost. This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> - यह कंप्यूटर %1 को सेटअप करने की न्यूनतम आवश्यकताओं को पूरा नहीं करता।<br/>सेटअप जारी नहीं रखा जा सकता।<a href="#details">विवरण...</a> + यह कंप्यूटर %1 सेटअप करने की न्यूनतम आवश्यकताओं को पूरा नहीं करता।<br/>सेटअप जारी नहीं रखा जा सकता।<a href="#details">विवरण...</a> This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> - यह कंप्यूटर %1 को इंस्टॉल करने की न्यूनतम आवश्यकताओं को पूरा नहीं करता।<br/>इंस्टॉल जारी नहीं रखा जा सकता।<a href="#details">विवरण...</a> + यह कंप्यूटर %1 इंस्टॉल करने की न्यूनतम आवश्यकताओं को पूरा नहीं करता।<br/>इंस्टॉल जारी नहीं रखा जा सकता।<a href="#details">विवरण...</a> This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. - यह कंप्यूटर %1 को सेटअप करने हेतु सुझाई गई आवश्यकताओं को पूरा नहीं करता।<br/>सेटअप जारी रखा जा सकता है, लेकिन कुछ विशेषताएँ को निष्क्रिय किया जा सकता हैं। + यह कंप्यूटर %1 सेटअप करने हेतु सुझाई गई आवश्यकताओं को पूरा नहीं करता।<br/>सेटअप जारी रखा जा सकता है, लेकिन कुछ विशेषताएँ निष्क्रिय कर दी जाएँगी। This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. - यह कंप्यूटर %1 को इंस्टॉल करने हेतु सुझाई गई आवश्यकताओं को पूरा नहीं करता।<br/>इंस्टॉल जारी रखा जा सकता है, लेकिन कुछ विशेषताएँ को निष्क्रिय किया जा सकता हैं। + यह कंप्यूटर %1 इंस्टॉल करने हेतु सुझाई गई आवश्यकताओं को पूरा नहीं करता।<br/>इंस्टॉल जारी रखा जा सकता है, लेकिन कुछ विशेषताएँ निष्क्रिय कर दी जाएँगी। This program will ask you some questions and set up %2 on your computer. - यह प्रोग्राम एक प्रश्नावली के आधार पर आपके कंप्यूटर पर %2 को सेट करेगा। + यह प्रोग्राम प्रश्नावली के माध्यम से आपके कंप्यूटर पर %2 को सेट करेगा। @@ -781,7 +782,7 @@ The installer will quit and all changes will be lost. <h1>Welcome to the Calamares installer for %1.</h1> - <h1>%1 के लिए Calamares इंस्टॉलर में आपका स्वागत है।</h1> + <h1>%1 हेतु Calamares इंस्टॉलर में आपका स्वागत है।</h1> @@ -992,7 +993,7 @@ The installer will quit and all changes will be lost. Create Volume Group - वॉल्यूम समूह बनाएँ + वॉल्यूम समूह बनाएं @@ -1397,7 +1398,7 @@ The installer will quit and all changes will be lost. is running the installer as an administrator (root) - + इंस्टॉलर को प्रबंधक(रुट) के अंतर्गत चला रहा है @@ -1412,7 +1413,7 @@ The installer will quit and all changes will be lost. has a screen large enough to show the whole installer - + स्क्रीन का माप इंस्टॉलर को पूर्णतया प्रदर्शित करने में सक्षम हो @@ -1563,7 +1564,7 @@ The installer will quit and all changes will be lost. <h1>License Agreement</h1> - + <h1>लाइसेंस अनुबंध</h1> @@ -1573,27 +1574,27 @@ The installer will quit and all changes will be lost. Please review the End User License Agreements (EULAs). - + कृपया लक्षित उपयोक्ता लाइसेंस अनुबंधों (EULAs) की समीक्षा करें। This setup procedure will install proprietary software that is subject to licensing terms. - + यह सेटअप प्रक्रिया लाइसेंस शर्तों के अधीन अमुक्त सॉफ्टवेयर को इंस्टॉल करेगी। If you do not agree with the terms, the setup procedure cannot continue. - + यदि आप शर्तों से असहमत है, तो सेटअप प्रक्रिया जारी नहीं रखी जा सकती। This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. - + यह सेटअप प्रक्रिया अतिरिक्त सुविधाएँ प्रदान करने व उपयोक्ता अनुभव में वृद्धि हेतु लाइसेंस शर्तों के अधीन अमुक्त सॉफ्टवेयर को इंस्टॉल कर सकती है। If you do not agree with the terms, proprietary software will not be installed, and open source alternatives will be used instead. - + यदि आप शर्तों से असहमत है, तो अमुक्त सॉफ्टवेयर इंस्टाल नहीं किया जाएगा व उनके मुक्त विकल्प उपयोग किए जाएँगे। @@ -1609,7 +1610,7 @@ The installer will quit and all changes will be lost. URL: %1 - + यूआरएल : %1 @@ -1646,7 +1647,7 @@ The installer will quit and all changes will be lost. File: %1 - + फ़ाइल : %1 @@ -1656,12 +1657,12 @@ The installer will quit and all changes will be lost. Show the license text - + लाइसेंस लेख दिखाएँ Open license agreement in browser. - + लाइसेंस अनुबंध को ब्राउज़र में खोलें। @@ -1719,35 +1720,35 @@ The installer will quit and all changes will be lost. Configuring LUKS key file. - LUKS कुंजी फाइल विन्यस्त करना। + LUKS कुंजी फ़ाइल विन्यस्त करना। No partitions are defined. - कोई विभाजन परिभाषित नहीं हैं। + कोई विभाजन परिभाषित नहीं है। Encrypted rootfs setup error - एन्क्रिप्टेड rootfs सेटअप में त्रुटि + एन्क्रिप्टेड रुट फ़ाइल सिस्टम सेटअप करने में त्रुटि Root partition %1 is LUKS but no passphrase has been set. - रूट विभाजन %1 LUKS है, लेकिन कोई कूटशब्द सेट नहीं किया गया है। + रुट विभाजन %1, LUKS है परंतु कोई कूटशब्द सेट नहीं है। Could not create LUKS key file for root partition %1. - रूट विभाजन %1 हेतु LUKS कुंजी फाइल बनाने में विफल। + रुट विभाजन %1 हेतु LUKS कुंजी फ़ाइल बनाई नहीं जा सकी। Could not configure LUKS key file on partition %1. - + विभाजन %1 हेतु LUKS कुंजी फ़ाइल विन्यस्त नहीं हो सकी। @@ -1755,7 +1756,7 @@ The installer will quit and all changes will be lost. Generate machine-id. - मशीन-आईडी उत्पन्न करना। + मशीन-आईडी उत्पन्न करें। @@ -1765,7 +1766,7 @@ The installer will quit and all changes will be lost. No root mount point is set for MachineId. - + मशीन-आईडी हेतु कोई रुट माउंट पॉइंट सेट नहीं है। @@ -1779,92 +1780,92 @@ The installer will quit and all changes will be lost. Office software - + ऑफिस सॉफ्टवेयर Office package - + ऑफिस पैकेज Browser software - + ब्राउज़र सॉफ्टवेयर Browser package - + ब्राउज़र पैकेज Web browser - + वेब ब्राउज़र Kernel - + कर्नेल Services - + सेवाएँ Login - + लॉगिन Desktop - + डेस्कटॉप Applications - + अनुप्रयोग Communication - + संचार Development - + सॉफ्टवेयर विकास Office - + ऑफिस Multimedia - + मल्टीमीडिया Internet - + इंटरनेट Theming - + थीम Gaming - + खेल Utilities - + साधन @@ -1872,7 +1873,7 @@ The installer will quit and all changes will be lost. Notes - + नोट्स @@ -1911,17 +1912,17 @@ The installer will quit and all changes will be lost. Password is too short - कूटशब्द काफ़ी छोटा है + कूटशब्द बहुत छोटा है Password is too long - कूटशब्द काफ़ी लंबा है + कूटशब्द बहुत लंबा है Password is too weak - कूटशब्द काफ़ी कमज़ोर है + कूटशब्द बहुत कमज़ोर है @@ -2016,7 +2017,7 @@ The installer will quit and all changes will be lost. The password is too short - कूटशब्द काफ़ी छोटा है + कूटशब्द बहुत छोटा है @@ -2076,7 +2077,7 @@ The installer will quit and all changes will be lost. Password generation failed - required entropy too low for settings - कूटशब्द बनाना विफल रहा - सेटिंग्स के लिए आवश्यक एन्ट्रापी काफ़ी कम है + कूटशब्द बनाना विफल रहा - सेटिंग्स के लिए आवश्यक entropy बहुत कम है @@ -2151,7 +2152,7 @@ The installer will quit and all changes will be lost. Password is empty - पासवर्ड खाली है + कूटशब्द रिक्त है @@ -2164,7 +2165,7 @@ The installer will quit and all changes will be lost. Product Name - उत्पाद का नाम​ + वस्तु का नाम @@ -2174,7 +2175,7 @@ The installer will quit and all changes will be lost. Long Product Description - लंबा उत्पाद विवरण + वस्तु का विस्तृत विवरण @@ -2184,7 +2185,7 @@ The installer will quit and all changes will be lost. Please pick a product from the list. The selected product will be installed. - कृप्या सूची से उत्पाद का चुनाव करें। चयनित उत्पाद इंस्टॉल किया जायेगा। + सूची में से वस्तु विशेष का चयन करें। चयनित वस्तु इंस्टॉल कर दी जाएगी। @@ -2241,7 +2242,7 @@ The installer will quit and all changes will be lost. Your Full Name - आपका पूरा नाम​ + आपके पूरा नाम @@ -2266,18 +2267,18 @@ The installer will quit and all changes will be lost. Computer Name - कंप्यूटर का नाम​ + कंप्यूटर का नाम Choose a password to keep your account safe. - अपना अकाउंट सुरक्षित रखने हेतु कूटशब्द चुनें। + अपना अकाउंट सुरक्षित रखने के लिए पासवर्ड चुनें । <small>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.</small> - <small>एक ही कूटशब्द दो बार दर्ज़ करें, ताकि उसे टाइप त्रुटि के लिए जांचा जा सके। एक उचित कूटशब्द में अक्षर, अंक व विराम चिन्हों का मेल होता है, उसमें कम-से-कम आठ अक्षर होने चाहिए, और उसे नियमित अंतराल पर बदलते रहना चाहिए।</small> + <small>एक ही कूटशब्द दो बार दर्ज़ करें, ताकि उसे टाइप त्रुटि के लिए जांचा जा सके । एक अच्छे कूटशब्द में अक्षर, अंक व विराम चिन्हों का मेल होता है, उसमें कम-से-कम आठ अक्षर होने चाहिए, और उसे नियमित अंतराल पर बदलते रहना चाहिए।</small> @@ -2289,22 +2290,22 @@ The installer will quit and all changes will be lost. Repeat Password - कूटशब्द दोबारा दर्ज करें + कूटशब्द पुनः दर्ज करें When this box is checked, password-strength checking is done and you will not be able to use a weak password. - डब्बे को चिह्नित करने पर पासवर्ड की मज़बूती की जांच होगी ओर आप कमज़ोर पासवर्ड उपयोग नही कर पाएँगे। + यह बॉक्स टिक करने के परिणाम स्वरुप कूटशब्द-क्षमता की जाँच होगी व आप कमज़ोर कूटशब्द उपयोग नहीं कर पाएंगे। Require strong passwords. - मज़बूत पासवर्डस की आवश्यकता। + मज़बूत कूटशब्द आवश्यक हैं। Log in automatically without asking for the password. - कूटशब्द पूछे बिना स्वतः लॉग इन करें। + कूटशब्द बिना पूछे ही स्वतः लॉग इन करें। @@ -2314,7 +2315,7 @@ The installer will quit and all changes will be lost. Choose a password for the administrator account. - प्रबंधक अकाउंट हेतु कूटशब्द चुनें। + प्रबंधक अकाउंट के लिए कूटशब्द चुनें। @@ -2373,7 +2374,7 @@ The installer will quit and all changes will be lost. Free Space - रिक्त स्पेस + खाली स्पेस @@ -2412,7 +2413,7 @@ The installer will quit and all changes will be lost. Storage de&vice: - स्टोरेज डिवाइस (&v): + डिवाइस (&v): @@ -2545,7 +2546,7 @@ The installer will quit and all changes will be lost. After: - बाद में : + बाद में: @@ -2555,12 +2556,12 @@ The installer will quit and all changes will be lost. An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. - + %1 आरंभ करने हेतु EFI सिस्टम विभाजन ज़रूरी है।<br/><br/>EFI सिस्टम विभाजन को विन्यस्त करने के लिए, वापस जाएँ और चुनें या बनाएँ एक FAT32 फ़ाइल सिस्टम जिस पर <strong>%3</strong> flag चालू हो व माउंट पॉइंट <strong>%2</strong>हो।<br/><br/>आप बिना सेट करें भी आगे बढ़ सकते है पर सिस्टम चालू नहीं होगा। An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. - + %1 को शुरू करने हेतु EFI सिस्टम विभाजन ज़रूरी है।<br/><br/>विभाजन को माउंट पॉइंट <strong>%2</strong> के साथ विन्यस्त किया गया परंतु उसका <strong>%3</strong> फ्लैग सेट नहीं था।<br/> फ्लैग सेट करने के लिए, वापस जाएँ और विभाजन को edit करें।<br/><br/>आप बिना सेट करें भी आगे बढ़ सकते है पर सिस्टम चालू नहीं होगा। @@ -2570,12 +2571,12 @@ The installer will quit and all changes will be lost. Option to use GPT on BIOS - + BIOS पर GPT उपयोग करने के लिए विकल्प A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. - + GPT विभाजन तालिका सभी सिस्टम हेतु सबसे उत्तम विकल्प है। यह इंस्टॉलर BIOS सिस्टम के सेटअप को भी समर्थन करता है। <br/><br/>BIOS पर GPT विभाजन तालिका को विन्यस्त करने हेतु, (अगर अब तक नहीं करा है तो) वापस जाकर विभाजन तालिका GPT पर सेट करें, फिर एक 8 MB का बिना फॉर्मेट हुआ विभाजन बनाए जिस पर <strong>bios_grub</strong> का flag हो।<br/><br/>यह बिना फॉर्मेट हुआ 8 MB का विभाजन %1 को BIOS सिस्टम पर GPT के साथ शुरू करने के लिए आवश्यक है। @@ -2595,7 +2596,7 @@ The installer will quit and all changes will be lost. There are no partitions to install on. - + इंस्टॉल हेतु कोई विभाजन नहीं हैं। @@ -2671,7 +2672,7 @@ There was no output from the command. Output: -आउटपुट : +आउटपुट: @@ -2774,27 +2775,27 @@ Output: File not found - फाइल नहीं मिली + फ़ाइल नहीं मिली Path <pre>%1</pre> must be an absolute path. - + फ़ाइल पथ <pre>%1</pre> निरपेक्ष होना चाहिए। Could not create new random file <pre>%1</pre>. - + नवीन यादृच्छिक फ़ाइल <pre>%1</pre>नहीं बनाई जा सकी। No product - कोई उत्पाद नहीं + कोई वस्तु नहीं No description provided. - कोई विवरण मौजूद नहीं + कोई विवरण प्रदान नहीं किया गया। @@ -2844,7 +2845,7 @@ Output: Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. - चुनें कि %1 को कहाँ इंस्टॉल करना है।<br/><font color="red">चेतावनी : </font> यह चयनित विभाजन पर मौजूद सभी फ़ाइलों को हटा देगा। + चुनें कि %1 को कहाँ इंस्टॉल करना है।<br/><font color="red">चेतावनी: </font> यह चयनित विभाजन पर मौजूद सभी फ़ाइलों को हटा देगा। @@ -2854,7 +2855,7 @@ Output: %1 cannot be installed on empty space. Please select an existing partition. - %1 को खाली स्पेस पर इंस्टॉल नहीं किया जा सकता। कृपया कोई मौजूदा विभाजन चुनें। + %1 को खाली स्पेस पर इंस्टॉल नहीं किया जा सकता।कृपया कोई मौजूदा विभाजन चुनें। @@ -2884,7 +2885,7 @@ Output: <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. - <strong>%4</strong><br/><br/>%2 के लिए विभाजन %1 काफ़ी छोटा है। कृपया कम-से-कम %3 GiB की क्षमता वाला कोई विभाजन चुनें। + <strong>%4</strong><br/><br/>%2 के लिए विभाजन %1 बहुत छोटा है।कृपया कम-से-कम %3 GiB की क्षमता वाला कोई विभाजन चुनें । @@ -2906,7 +2907,7 @@ Output: EFI system partition: - EFI सिस्टम विभाजन : + EFI सिस्टम विभाजन: @@ -3260,7 +3261,7 @@ Output: Cannot set password for user %1. - उपयोक्ता %1 हेतु पासवर्ड सेट नहीं किया जा सकता। + उपयोक्ता %1 के लिए पासवर्ड सेट नहीं किया जा सकता। @@ -3298,12 +3299,12 @@ Output: Cannot set timezone, - समय क्षेत्र सेट नहीं हो सका, + समय क्षेत्र सेट नहीं हो सका। Cannot open /etc/timezone for writing - राइट करने हेतु /etc /timezone खोला नहीं जा सका + राइट करने हेतु /etc /timezone खोला नहीं जा सका। @@ -3462,32 +3463,32 @@ Output: Your username is too long. - आपका उपयोक्ता नाम काफ़ी लंबा है। + आपका उपयोक्ता नाम बहुत लंबा है। Your username must start with a lowercase letter or underscore. - + आपके उपयोक्ता नाम का आरंभ lowercase अक्षर या अंडरस्कोर(_) से ही होना चाहिए। Only lowercase letters, numbers, underscore and hyphen are allowed. - + केवल lowercase अक्षर, अंक, अंडरस्कोर(_) व हाइफ़न(-) का उपयोग ही मान्य है। Your hostname is too short. - आपका होस्ट नाम काफ़ी छोटा है। + आपका होस्ट नाम बहुत छोटा है। Your hostname is too long. - आपका होस्ट नाम काफ़ी लंबा है। + आपका होस्ट नाम बहुत लंबा है। Only letters, numbers, underscore and hyphen are allowed. - + केवल अक्षर, अंक, अंडरस्कोर(_) व हाइफ़न(-) का उपयोग ही मान्य है। @@ -3508,12 +3509,12 @@ Output: Key - + कुंजी Value - + मान @@ -3521,7 +3522,7 @@ Output: Create Volume Group - वॉल्यूम समूह बनाएँ + वॉल्यूम समूह बनाएं @@ -3580,7 +3581,7 @@ Output: Select application and system language - ऐप्लिकेशन व सिस्टम भाषा चुनें + अनुप्रयोग व सिस्टम भाषा चुनें @@ -3590,17 +3591,17 @@ Output: Open donations website - दान करने की वेबसाइट खोलें + दान हेतु वेबसाइट खोलें &Donate - &दान करें + दान करें (&D) Open help and support website - मदद व सहायता की वेबसाइट खोलें + सहायता हेतु वेबसाइट खोलें @@ -3620,7 +3621,7 @@ Output: Open release notes website - + प्रकाशन नोट्स हेतु वेबसाइट खोलें @@ -3665,7 +3666,7 @@ Output: <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. - + <h1>%1</h1><br/><strong>%2<br/>के लिए %3</strong><br/><br/>प्रतिलिप्याधिकार 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>प्रतिलिप्याधिकार 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/><a href="https://calamares.io/team/">Calamares टीम</a> व <a href="https://www.transifex.com/calamares/calamares/">Calamares अनुवादक टीम</a> का धन्यवाद।<br/><br/><a href="https://calamares.io/">Calamares</a> का विकास <br/><a href="http://www.blue-systems.com/">ब्लू सिस्टम्स</a> - लिब्रेटिंग सॉफ्टवेयर द्वारा प्रायोजित है। @@ -3700,12 +3701,23 @@ Output: development is sponsored by <br/> <a href='http://www.blue-systems.com/'>Blue Systems</a> - Liberating Software. - + <h1>%1</h1><br/> + <strong>%2<br/> + के लिए %3</strong><br/><br/> + प्रतिलिप्याधिकार 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/> + प्रतिलिप्याधिकार 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/> + <a href='https://calamares.io/team/'>the Calamares टीम</a> + व <a href='https://www.transifex.com/calamares/calamares/'>Calamares + अनुवादक टीम</a>को धन्यवाद।<br/><br/> + <a href='https://calamares.io/'>Calamares</a> + का विकास <br/> + <a href='http://www.blue-systems.com/'>ब्लू सिस्टम्स</a> - + लिब्रेटिंग सॉफ्टवेयर द्वारा प्रायोजित है। Back - + वापस @@ -3713,44 +3725,44 @@ Output: Keyboard Model - + कुंजीपटल मॉडल Pick your preferred keyboard model or use the default one based on the detected hardware - + अपना कुंजीपटल मॉडल चुनें या फिर हार्डवेयर आधारित डिफ़ॉल्ट मॉडल उपयोग करें Refresh - + रिफ्रेश करें Layouts - + अभिन्यास Keyboard Layout - + कुंजीपटल अभिन्यास Models - + मॉडल Variants - + भिन्न रूप Test your keyboard - + अपना कुंजीपटल जाँचें @@ -3759,7 +3771,8 @@ Output: <h3>%1</h3> <p>These are example release notes.</p> - + <h3>%1</h3> + <p>ये उदाहरण रिलीज़ नोट्स हैं।</p> @@ -3787,12 +3800,32 @@ Output: </ul> <p>The vertical scrollbar is adjustable, current width set to 10.</p> - + <h3>%1</h3> + <p>यह एक उदाहरण QML फ़ाइल है, जो फ्लिक योग्य सामग्री युक्त रिच टेक्स्ट के विकल्प प्रदर्शित करती है।</p> + + <p>रिच टेक्स्ट के साथ QML एचटीएमएल टैग उपयोग कर सकता है, फ्लिक योग्य सामग्री टचस्क्रीन में उपयोगी होती है।</p> + + <p><b>यह बोल्ड टेक्स्ट है</b></p> + <p><i>यह तिरछा टेक्स्ट है</i></p> + <p><u>यह रेखांकित टेक्स्ट है</u></p> + <p><center>यह टेक्स्ट केंद्र-संरेखित होगा।</center></p> + <p><s>यह स्ट्राइकथ्रू है</s></p> + + <p>कोड उदाहरण : + <code>ls -l /home</code></p> + + <p><b>सूचियाँ :</b></p> + <ul> + <li>इंटेल सीपीयू सिस्टम</li> + <li>एएमडी सीपीयू सिस्टम</li> + </ul> + + <p>ऊर्ध्वाधर स्क्रॉलबार समायोज्य है, वर्तमान चौड़ाई 10 पर सेट है।</p> Back - + वापस @@ -3801,32 +3834,33 @@ Output: <h3>Welcome to the %1 <quote>%2</quote> installer</h3> <p>This program will ask you some questions and set up %1 on your computer.</p> - + <h3>%1 <quote>%2</quote>इंस्टॉलर में आपका स्वागत है</h3> + <p>यह प्रोग्राम प्रश्नावली के माध्यम से आपके कंप्यूटर पर %1 को सेट करेगा।</p> About - + बारे में Support - + सहायता Known issues - + ज्ञात समस्याएँ Release notes - + रिलीज़ नोट्स Donate - + दान करें From 13d8b85de2b4794dba924ee280185af587aa012c Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Thu, 18 Jun 2020 14:54:45 +0200 Subject: [PATCH 101/105] i18n: [python] Automatic merge of Transifex translations --- lang/python/az/LC_MESSAGES/python.mo | Bin 0 -> 384 bytes lang/python/az/LC_MESSAGES/python.po | 336 ++++++++++++++++++++++++ lang/python/az_AZ/LC_MESSAGES/python.mo | Bin 0 -> 403 bytes lang/python/az_AZ/LC_MESSAGES/python.po | 336 ++++++++++++++++++++++++ lang/python/hi/LC_MESSAGES/python.mo | Bin 10929 -> 11474 bytes lang/python/hi/LC_MESSAGES/python.po | 12 +- 6 files changed, 678 insertions(+), 6 deletions(-) create mode 100644 lang/python/az/LC_MESSAGES/python.mo create mode 100644 lang/python/az/LC_MESSAGES/python.po create mode 100644 lang/python/az_AZ/LC_MESSAGES/python.mo create mode 100644 lang/python/az_AZ/LC_MESSAGES/python.po diff --git a/lang/python/az/LC_MESSAGES/python.mo b/lang/python/az/LC_MESSAGES/python.mo new file mode 100644 index 0000000000000000000000000000000000000000..e7b9aa3c33e09c98ab64184228fe1c71e327e34c GIT binary patch literal 384 zcmYL@!A=4(5QZ^&>d~`@ns|U{X%~$yC3`?z3{hl*EB9e3OUZ7#X^SB5;p_P%?>6x$>NPZalR@&(JTszScJfB}T7B=E!J4X2Mvh6~{?`@X~*d z@hqOck0x(uDk^Op8QWYg$m1rrB-I?FWJ0FmQ`R2x1Ws_=VZj4oAz@t{Fn)V?&AiYn zsC)ytAgO?o6&`<%Du1{i=KnCw7ij1xVGy*$RvmF8WA^Bs|{Lua?4)SY>)4RnBoZ nm+laiW7wml*cd3tP@B?ntg64!Mx7r1Z=, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"PO-Revision-Date: 2017-08-09 10:34+0000\n" +"Language-Team: Azerbaijani (https://www.transifex.com/calamares/teams/20061/az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/modules/packages/main.py:59 src/modules/packages/main.py:68 +#: src/modules/packages/main.py:78 +msgid "Install packages." +msgstr "" + +#: src/modules/packages/main.py:66 +#, python-format +msgid "Processing packages (%(count)d / %(total)d)" +msgstr "" + +#: src/modules/packages/main.py:71 +#, python-format +msgid "Installing one package." +msgid_plural "Installing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/packages/main.py:74 +#, python-format +msgid "Removing one package." +msgid_plural "Removing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/networkcfg/main.py:37 +msgid "Saving network configuration." +msgstr "" + +#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205 +#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144 +#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95 +#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332 +#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94 +#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171 +msgid "Configuration Error" +msgstr "" + +#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210 +#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145 +#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339 +#: src/modules/initramfscfg/main.py:99 +msgid "No root mount point is given for

{!s}
to use." +msgstr "" + +#: src/modules/umount/main.py:40 +msgid "Unmount file systems." +msgstr "" + +#: src/modules/initcpiocfg/main.py:37 +msgid "Configuring mkinitcpio." +msgstr "" + +#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79 +#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96 +#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95 +#: src/modules/rawfs/main.py:172 +msgid "No partitions are defined for
{!s}
to use." +msgstr "" + +#: src/modules/openrcdmcryptcfg/main.py:34 +msgid "Configuring OpenRC dmcrypt service." +msgstr "" + +#: src/modules/unpackfs/main.py:44 +msgid "Filling up filesystems." +msgstr "" + +#: src/modules/unpackfs/main.py:257 +msgid "rsync failed with error code {}." +msgstr "" + +#: src/modules/unpackfs/main.py:302 +msgid "Unpacking image {}/{}, file {}/{}" +msgstr "" + +#: src/modules/unpackfs/main.py:317 +msgid "Starting to unpack {}" +msgstr "" + +#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432 +msgid "Failed to unpack image \"{}\"" +msgstr "" + +#: src/modules/unpackfs/main.py:399 +msgid "No mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:400 +msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:405 +msgid "Bad mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:406 +msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426 +#: src/modules/unpackfs/main.py:446 +msgid "Bad unsquash configuration" +msgstr "" + +#: src/modules/unpackfs/main.py:423 +msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" +msgstr "" + +#: src/modules/unpackfs/main.py:427 +msgid "The source filesystem \"{}\" does not exist" +msgstr "" + +#: src/modules/unpackfs/main.py:433 +msgid "" +"Failed to find unsquashfs, make sure you have the squashfs-tools package " +"installed" +msgstr "" + +#: src/modules/unpackfs/main.py:447 +msgid "The destination \"{}\" in the target system is not a directory" +msgstr "" + +#: src/modules/services-systemd/main.py:35 +msgid "Configure systemd services" +msgstr "" + +#: src/modules/services-systemd/main.py:68 +#: src/modules/services-openrc/main.py:102 +msgid "Cannot modify service" +msgstr "" + +#: src/modules/services-systemd/main.py:69 +msgid "" +"systemctl {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:72 +#: src/modules/services-systemd/main.py:76 +msgid "Cannot enable systemd service {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:74 +msgid "Cannot enable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:78 +msgid "Cannot disable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:80 +msgid "Cannot mask systemd unit {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:82 +msgid "" +"Unknown systemd commands {command!s} and " +"{suffix!s} for unit {name!s}." +msgstr "" + +#: src/modules/dummypython/main.py:44 +msgid "Dummy python job." +msgstr "" + +#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102 +#: src/modules/dummypython/main.py:103 +msgid "Dummy python step {}" +msgstr "" + +#: src/modules/bootloader/main.py:51 +msgid "Install bootloader." +msgstr "" + +#: src/modules/localecfg/main.py:39 +msgid "Configuring locales." +msgstr "" + +#: src/modules/mount/main.py:38 +msgid "Mounting partitions." +msgstr "" + +#: src/modules/plymouthcfg/main.py:36 +msgid "Configure Plymouth theme" +msgstr "" + +#: src/modules/luksopenswaphookcfg/main.py:35 +msgid "Configuring encrypted swap." +msgstr "" + +#: src/modules/fstab/main.py:38 +msgid "Writing fstab." +msgstr "" + +#: src/modules/services-openrc/main.py:38 +msgid "Configure OpenRC services" +msgstr "" + +#: src/modules/services-openrc/main.py:66 +msgid "Cannot add service {name!s} to run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:68 +msgid "Cannot remove service {name!s} from run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:70 +msgid "" +"Unknown service-action {arg!s} for service {name!s} in run-" +"level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:103 +msgid "" +"rc-update {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:110 +msgid "Target runlevel does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:111 +msgid "" +"The path for runlevel {level!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/services-openrc/main.py:119 +msgid "Target service does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:120 +msgid "" +"The path for service {name!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/dracut/main.py:36 +msgid "Creating initramfs with dracut." +msgstr "" + +#: src/modules/dracut/main.py:58 +msgid "Failed to run dracut on the target" +msgstr "" + +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "" + +#: src/modules/grubcfg/main.py:37 +msgid "Configure GRUB." +msgstr "" + +#: src/modules/displaymanager/main.py:515 +msgid "Cannot write KDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:516 +msgid "KDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:577 +msgid "Cannot write LXDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:578 +msgid "LXDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:661 +msgid "Cannot write LightDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:662 +msgid "LightDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:736 +msgid "Cannot configure LightDM" +msgstr "" + +#: src/modules/displaymanager/main.py:737 +msgid "No LightDM greeter installed." +msgstr "" + +#: src/modules/displaymanager/main.py:768 +msgid "Cannot write SLIM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:769 +msgid "SLIM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:895 +msgid "No display managers selected for the displaymanager module." +msgstr "" + +#: src/modules/displaymanager/main.py:896 +msgid "" +"The displaymanagers list is empty or undefined in bothglobalstorage and " +"displaymanager.conf." +msgstr "" + +#: src/modules/displaymanager/main.py:978 +msgid "Display manager configuration was incomplete" +msgstr "" + +#: src/modules/initramfscfg/main.py:41 +msgid "Configuring initramfs." +msgstr "" + +#: src/modules/hwclock/main.py:35 +msgid "Setting hardware clock." +msgstr "" + +#: src/modules/rawfs/main.py:35 +msgid "Installing data." +msgstr "" diff --git a/lang/python/az_AZ/LC_MESSAGES/python.mo b/lang/python/az_AZ/LC_MESSAGES/python.mo new file mode 100644 index 0000000000000000000000000000000000000000..4c1bf9a19a2913f41a37517d2f12ed173aaf1c9a GIT binary patch literal 403 zcmYL@-%i3X6vi=nwM(zPI3`{|w6sH`qhuEoharkAI7#%zlu<^>XqUDK@*cjP&tiuO ze9158oSc8(@9D`;&FRQ-=D2ViJFXm+0>`^+wq2}d_DZx`@XVtA6pgtyLP-iq)P0H` zV;IMy*Z%Ou8}U+Uiv}haQ*^(|4N4USFBzf{{}R;>dSI4QXc7MokpPi4_=H~HToNbm znaO;`a*k5YmK35b*ApfdObVzUiU!o@)|Q51yk4)HRx@eDjBlEmTH=fqY{@h?*t#1A zw+OlQG24DdAGqNS`h)o3-ft4GtEA=9qV&6Twk+RRToz2o4rFtt4Y%Q2+C#x%uKG6P w8pSeGQz3H-!9>`-bqc#*UQ(, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"PO-Revision-Date: 2017-08-09 10:34+0000\n" +"Language-Team: Azerbaijani (Azerbaijan) (https://www.transifex.com/calamares/teams/20061/az_AZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az_AZ\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/modules/packages/main.py:59 src/modules/packages/main.py:68 +#: src/modules/packages/main.py:78 +msgid "Install packages." +msgstr "" + +#: src/modules/packages/main.py:66 +#, python-format +msgid "Processing packages (%(count)d / %(total)d)" +msgstr "" + +#: src/modules/packages/main.py:71 +#, python-format +msgid "Installing one package." +msgid_plural "Installing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/packages/main.py:74 +#, python-format +msgid "Removing one package." +msgid_plural "Removing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/networkcfg/main.py:37 +msgid "Saving network configuration." +msgstr "" + +#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205 +#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144 +#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95 +#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332 +#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94 +#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171 +msgid "Configuration Error" +msgstr "" + +#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210 +#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145 +#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339 +#: src/modules/initramfscfg/main.py:99 +msgid "No root mount point is given for
{!s}
to use." +msgstr "" + +#: src/modules/umount/main.py:40 +msgid "Unmount file systems." +msgstr "" + +#: src/modules/initcpiocfg/main.py:37 +msgid "Configuring mkinitcpio." +msgstr "" + +#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79 +#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96 +#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95 +#: src/modules/rawfs/main.py:172 +msgid "No partitions are defined for
{!s}
to use." +msgstr "" + +#: src/modules/openrcdmcryptcfg/main.py:34 +msgid "Configuring OpenRC dmcrypt service." +msgstr "" + +#: src/modules/unpackfs/main.py:44 +msgid "Filling up filesystems." +msgstr "" + +#: src/modules/unpackfs/main.py:257 +msgid "rsync failed with error code {}." +msgstr "" + +#: src/modules/unpackfs/main.py:302 +msgid "Unpacking image {}/{}, file {}/{}" +msgstr "" + +#: src/modules/unpackfs/main.py:317 +msgid "Starting to unpack {}" +msgstr "" + +#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432 +msgid "Failed to unpack image \"{}\"" +msgstr "" + +#: src/modules/unpackfs/main.py:399 +msgid "No mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:400 +msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:405 +msgid "Bad mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:406 +msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426 +#: src/modules/unpackfs/main.py:446 +msgid "Bad unsquash configuration" +msgstr "" + +#: src/modules/unpackfs/main.py:423 +msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" +msgstr "" + +#: src/modules/unpackfs/main.py:427 +msgid "The source filesystem \"{}\" does not exist" +msgstr "" + +#: src/modules/unpackfs/main.py:433 +msgid "" +"Failed to find unsquashfs, make sure you have the squashfs-tools package " +"installed" +msgstr "" + +#: src/modules/unpackfs/main.py:447 +msgid "The destination \"{}\" in the target system is not a directory" +msgstr "" + +#: src/modules/services-systemd/main.py:35 +msgid "Configure systemd services" +msgstr "" + +#: src/modules/services-systemd/main.py:68 +#: src/modules/services-openrc/main.py:102 +msgid "Cannot modify service" +msgstr "" + +#: src/modules/services-systemd/main.py:69 +msgid "" +"systemctl {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:72 +#: src/modules/services-systemd/main.py:76 +msgid "Cannot enable systemd service {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:74 +msgid "Cannot enable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:78 +msgid "Cannot disable systemd target {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:80 +msgid "Cannot mask systemd unit {name!s}." +msgstr "" + +#: src/modules/services-systemd/main.py:82 +msgid "" +"Unknown systemd commands {command!s} and " +"{suffix!s} for unit {name!s}." +msgstr "" + +#: src/modules/dummypython/main.py:44 +msgid "Dummy python job." +msgstr "" + +#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102 +#: src/modules/dummypython/main.py:103 +msgid "Dummy python step {}" +msgstr "" + +#: src/modules/bootloader/main.py:51 +msgid "Install bootloader." +msgstr "" + +#: src/modules/localecfg/main.py:39 +msgid "Configuring locales." +msgstr "" + +#: src/modules/mount/main.py:38 +msgid "Mounting partitions." +msgstr "" + +#: src/modules/plymouthcfg/main.py:36 +msgid "Configure Plymouth theme" +msgstr "" + +#: src/modules/luksopenswaphookcfg/main.py:35 +msgid "Configuring encrypted swap." +msgstr "" + +#: src/modules/fstab/main.py:38 +msgid "Writing fstab." +msgstr "" + +#: src/modules/services-openrc/main.py:38 +msgid "Configure OpenRC services" +msgstr "" + +#: src/modules/services-openrc/main.py:66 +msgid "Cannot add service {name!s} to run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:68 +msgid "Cannot remove service {name!s} from run-level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:70 +msgid "" +"Unknown service-action {arg!s} for service {name!s} in run-" +"level {level!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:103 +msgid "" +"rc-update {arg!s} call in chroot returned error code {num!s}." +msgstr "" + +#: src/modules/services-openrc/main.py:110 +msgid "Target runlevel does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:111 +msgid "" +"The path for runlevel {level!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/services-openrc/main.py:119 +msgid "Target service does not exist" +msgstr "" + +#: src/modules/services-openrc/main.py:120 +msgid "" +"The path for service {name!s} is {path!s}, which does not " +"exist." +msgstr "" + +#: src/modules/dracut/main.py:36 +msgid "Creating initramfs with dracut." +msgstr "" + +#: src/modules/dracut/main.py:58 +msgid "Failed to run dracut on the target" +msgstr "" + +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "" + +#: src/modules/grubcfg/main.py:37 +msgid "Configure GRUB." +msgstr "" + +#: src/modules/displaymanager/main.py:515 +msgid "Cannot write KDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:516 +msgid "KDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:577 +msgid "Cannot write LXDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:578 +msgid "LXDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:661 +msgid "Cannot write LightDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:662 +msgid "LightDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:736 +msgid "Cannot configure LightDM" +msgstr "" + +#: src/modules/displaymanager/main.py:737 +msgid "No LightDM greeter installed." +msgstr "" + +#: src/modules/displaymanager/main.py:768 +msgid "Cannot write SLIM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:769 +msgid "SLIM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:895 +msgid "No display managers selected for the displaymanager module." +msgstr "" + +#: src/modules/displaymanager/main.py:896 +msgid "" +"The displaymanagers list is empty or undefined in bothglobalstorage and " +"displaymanager.conf." +msgstr "" + +#: src/modules/displaymanager/main.py:978 +msgid "Display manager configuration was incomplete" +msgstr "" + +#: src/modules/initramfscfg/main.py:41 +msgid "Configuring initramfs." +msgstr "" + +#: src/modules/hwclock/main.py:35 +msgid "Setting hardware clock." +msgstr "" + +#: src/modules/rawfs/main.py:35 +msgid "Installing data." +msgstr "" diff --git a/lang/python/hi/LC_MESSAGES/python.mo b/lang/python/hi/LC_MESSAGES/python.mo index 2732db6edb9ccc6419583a2b8ef473ca77c0a4b6..8b12ae6dcc5a26193270026013bc989f3e606943 100644 GIT binary patch delta 1781 zcmY+?drVtZ9Ki9@hPrjiHkg0~Mh~wE4g!HqC!k}K4YzE;Igu@6LD)(|SSj{lg0(60 zwHf9kT*)K>634BZB$AEBS6ooDXrll4NSIlS=HfzPG$#6w$zptbf4yDInp{5Tcev;G zJLh-LrOs~;Cw|P$no#`Od5U=+b1Kz~XR`RiZ~bjb?Zupo-B?C^9t-hHY{V733q7lp z+JX%k{V4yR!aDpK^H8l;YMW9CmCvA@xC1LNjCbQ3nfMdjK)izM@CJI&?Y0Y+qim!F zB~KR?VGQ%}EZ&LpSb$g1i{E1n_0?Yta+s)EW53vhj}mvFob((@!p~3=ETe4b2FkkZ z+vyT|QBGcuvJoH3fnGv6&^*dUuHr`g6`QHA+;=Edio0+t`jOVCY21ugu^ye-cEU!K z1cy*I^b|@DMX_Bin<%DV41(ElidV*1jFr+ zOvsKlbCZtaFgD>5K8)+R01_X@E%-W0;V)1URTkR?dvJ#MGPdIpzSBOO#X9^QTTt_z zw&KwQg9Zi$&f(|SflqpsdIUekgP5!B_xe#bIEnA$Kj_Ez_%6?32{-mlJcrWyHg2MH z^gK$wnhJY;9JdoEe#%UgRVuZIiBtFxeuF15Z#M9`!$Id&3gTzb7ztj$HHu>*WgAAsb_zidCSdCH+bn-~6;tM zR*_?yF_~3fDyJyT%nR(3toHYoxXt(>t0-p&qh=ner+>Q)x2wo4pN=b{+KpOQL3S%6 zIXW9q_ZbIV<&GvJ>Z)_>Hj=JJ#{;Qrt`}D29gOsbA_GHy9SQ2_&~WduK^==5N3;KE z?H@Sd3y*{&zJTrzhICmhUZ$&J@oGH~)bNUK%m#}BY9mcUZW+sJx(pJ+vjjL)Tiol0;^NAo@;BovADL( z53S@W%QUUzNrDe7^I6NBvy!7$a?1FssI2@&%e7-< zeQVC-jIn>Cx0^h3mN`K&mc1)Ek}peHbKWu+E%O4i6E|lsq_?!d)LZGdc%4_My2un; zWQn~zX_+6B#JE&Zkm}pC=rsN=Em delta 1334 zcmXZbTSyd97{Ku}>#mp0^_G`(tzA>oys(w6x~ZutR%>DymXei5P?#bKQJA?&7kUV~ zOukr2LHSTb*dS892ti;9mC;40$f&4?ZV1ssLH}>Z12ez#&Fp;VobQ~SZXRh2yo<9A zC|WgFDp#pRsWxn}a-+SsDdor6dGkV*T1tEfQ*aOqa1aNm4<4i^%SVl+-*GR~k3IEONk$Otn}7CMP*F%kD-JoaG{ z>gd8-n8)~Pl1?lS{-FHOZda-ST_`Kcm_e#uYe?k}$+!CdfvaPz^4@o%7F+Vkz+@ zY{Azk1AC*Csz*Q8;UET<)A>TD3FD}5EAB_xqbcN-`heB=3rnz&<+`yOdo)UlyNRRX z%(HUFq;jO_!w@--zY0;VA;Fy z4oV!&LCD4q%*O#N$A{>{5DrWQmSHXS;U0XPO#Ro;@o<7RU^_}|pzP&$l!4QoW}*Pf zfcJ0+6H}F1kE6H=|Dgx{Y;Y;|pclt*6@J5;=w`p_aWX(>GaaW(sV&%n^22eI8P4Gt zHn};;7{ft1j)(CY{zWPM5GPeis_|Ene5X*pe}&~(nxWK2?8Pd4g#8$>XHsrDXV8u1 z%gg~*koUWO?TLwv9c!FD6$9JI^Ab;MikR$%T=|$!>$55O bMpueq*Pmr37?(4jXhuTzxW%Z, YEAR. # # Translators: -# Panwar108 , 2019 +# Panwar108 , 2020 # #, fuzzy msgid "" @@ -13,7 +13,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2020-04-30 23:13+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Panwar108 , 2019\n" +"Last-Translator: Panwar108 , 2020\n" "Language-Team: Hindi (https://www.transifex.com/calamares/teams/20061/hi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -84,7 +84,7 @@ msgstr "
{!s}
के उपयोग हेतु कोई विभ #: src/modules/openrcdmcryptcfg/main.py:34 msgid "Configuring OpenRC dmcrypt service." -msgstr "OpenRC dmcrypt सेवा को विन्यस्त करना।" +msgstr "OpenRC dmcrypt सेवा विन्यस्त करना।" #: src/modules/unpackfs/main.py:44 msgid "Filling up filesystems." @@ -96,11 +96,11 @@ msgstr "rsync त्रुटि कोड {} के साथ विफल।" #: src/modules/unpackfs/main.py:302 msgid "Unpacking image {}/{}, file {}/{}" -msgstr "" +msgstr "इमेज फ़ाइल {}/{}, फ़ाइल {}/{} सम्पीड़ित की जा रही है" #: src/modules/unpackfs/main.py:317 msgid "Starting to unpack {}" -msgstr "" +msgstr "{} हेतु संपीड़न प्रक्रिया आरंभ हो रही है " #: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432 msgid "Failed to unpack image \"{}\"" @@ -129,7 +129,7 @@ msgstr "ख़राब unsquash विन्यास सेटिंग्स" #: src/modules/unpackfs/main.py:423 msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" -msgstr "" +msgstr "\"{}\" ({}) हेतु फ़ाइल सिस्टम आपके वर्तमान कर्नेल द्वारा समर्थित नहीं है" #: src/modules/unpackfs/main.py:427 msgid "The source filesystem \"{}\" does not exist" From c284024b0eb28c616c1699377ad5213571585819 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Jun 2020 15:47:18 +0200 Subject: [PATCH 102/105] i18n: Update English translations --- lang/calamares_en.ts | 544 +++++++++++------- lang/python.pot | 486 ++++++++-------- .../dummypythonqt/lang/dummypythonqt.pot | 18 +- 3 files changed, 575 insertions(+), 473 deletions(-) diff --git a/lang/calamares_en.ts b/lang/calamares_en.ts index 08ff2436c..ec80837bd 100644 --- a/lang/calamares_en.ts +++ b/lang/calamares_en.ts @@ -117,12 +117,12 @@ Calamares::ExecutionViewStep - + Set up Set up - + Install Install @@ -130,12 +130,12 @@ Calamares::FailJob - + Job failed (%1) Job failed (%1) - + Programmed job failure was explicitly requested. Programmed job failure was explicitly requested. @@ -143,7 +143,7 @@ Calamares::JobThread - + Done Done @@ -151,7 +151,7 @@ Calamares::NamedJob - + Example job (%1) Example job (%1) @@ -159,17 +159,17 @@ Calamares::ProcessJob - + Run command '%1' in target system. Run command '%1' in target system. - + Run command '%1'. Run command '%1'. - + Running command %1 %2 Running command %1 %2 @@ -177,32 +177,32 @@ Calamares::PythonJob - + Running %1 operation. Running %1 operation. - + Bad working directory path Bad working directory path - + Working directory %1 for python job %2 is not readable. Working directory %1 for python job %2 is not readable. - + Bad main script file Bad main script file - + Main script file %1 for python job %2 is not readable. Main script file %1 for python job %2 is not readable. - + Boost.Python error in job "%1". Boost.Python error in job "%1". @@ -227,8 +227,13 @@ Calamares::RequirementsChecker + + + Requirements checking for module <i>%1</i> is complete. + Requirements checking for module <i>%1</i> is complete. + - + Waiting for %n module(s). Waiting for %n module(s). @@ -236,7 +241,7 @@ - + (%n second(s)) (%n second(s)) @@ -244,7 +249,7 @@ - + System-requirements checking is complete. System-requirements checking is complete. @@ -273,13 +278,13 @@ - + &Yes &Yes - + &No &No @@ -314,109 +319,109 @@ <br/>The following modules could not be loaded: - + Continue with setup? Continue with setup? - + Continue with installation? Continue with installation? - + The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> The %1 setup program is about to make changes to your disk in order to set up %2.<br/><strong>You will not be able to undo these changes.</strong> - + The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> The %1 installer is about to make changes to your disk in order to install %2.<br/><strong>You will not be able to undo these changes.</strong> - + &Set up now &Set up now - + &Install now &Install now - + Go &back Go &back - + &Set up &Set up - + &Install &Install - + Setup is complete. Close the setup program. Setup is complete. Close the setup program. - + The installation is complete. Close the installer. The installation is complete. Close the installer. - + Cancel setup without changing the system. Cancel setup without changing the system. - + Cancel installation without changing the system. Cancel installation without changing the system. - + &Next &Next - + &Back &Back - + &Done &Done - + &Cancel &Cancel - + Cancel setup? Cancel setup? - + Cancel installation? Cancel installation? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Do you really want to cancel the current install process? @@ -426,22 +431,22 @@ The installer will quit and all changes will be lost. CalamaresPython::Helper - + Unknown exception type Unknown exception type - + unparseable Python error unparseable Python error - + unparseable Python traceback unparseable Python traceback - + Unfetchable Python error. Unfetchable Python error. @@ -459,32 +464,32 @@ The installer will quit and all changes will be lost. CalamaresWindow - + Show debug information Show debug information - + &Back &Back - + &Next &Next - + &Cancel &Cancel - + %1 Setup Program %1 Setup Program - + %1 Installer %1 Installer @@ -681,18 +686,18 @@ The installer will quit and all changes will be lost. CommandList - - + + Could not run command. Could not run command. - + The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. - + The command needs to know the user's name, but no username is defined. The command needs to know the user's name, but no username is defined. @@ -745,49 +750,49 @@ The installer will quit and all changes will be lost. Network Installation. (Disabled: Unable to fetch package lists, check your network connection) - + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> - + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> - + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. - + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. - + This program will ask you some questions and set up %2 on your computer. This program will ask you some questions and set up %2 on your computer. - - <h1>Welcome to the Calamares setup program for %1.</h1> - <h1>Welcome to the Calamares setup program for %1.</h1> + + <h1>Welcome to the Calamares setup program for %1</h1> + - - <h1>Welcome to %1 setup.</h1> - <h1>Welcome to %1 setup.</h1> + + <h1>Welcome to %1 setup</h1> + - - <h1>Welcome to the Calamares installer for %1.</h1> - <h1>Welcome to the Calamares installer for %1.</h1> + + <h1>Welcome to the Calamares installer for %1</h1> + - - <h1>Welcome to the %1 installer.</h1> - <h1>Welcome to the %1 installer.</h1> + + <h1>Welcome to the %1 installer</h1> + @@ -1224,37 +1229,37 @@ The installer will quit and all changes will be lost. FillGlobalStorageJob - + Set partition information Set partition information - + Install %1 on <strong>new</strong> %2 system partition. Install %1 on <strong>new</strong> %2 system partition. - + Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>. Set up <strong>new</strong> %2 partition with mount point <strong>%1</strong>. - + Install %2 on %3 system partition <strong>%1</strong>. Install %2 on %3 system partition <strong>%1</strong>. - + Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>. Set up %3 partition <strong>%1</strong> with mount point <strong>%2</strong>. - + Install boot loader on <strong>%1</strong>. Install boot loader on <strong>%1</strong>. - + Setting up mount points. Setting up mount points. @@ -1272,32 +1277,32 @@ The installer will quit and all changes will be lost. &Restart now - + <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. - + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the setup program.</p></body></html> - + <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. <h1>All done.</h1><br/>%1 has been installed on your computer.<br/>You may now restart into your new system, or continue using the %2 Live environment. - + <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> <html><head/><body><p>When this box is checked, your system will restart immediately when you click on <span style="font-style:italic;">Done</span> or close the installer.</p></body></html> - + <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. - + <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. <h1>Installation Failed</h1><br/>%1 has not been installed on your computer.<br/>The error message was: %2. @@ -1305,27 +1310,27 @@ The installer will quit and all changes will be lost. FinishedViewStep - + Finish Finish - + Setup Complete Setup Complete - + Installation Complete Installation Complete - + The setup of %1 is complete. The setup of %1 is complete. - + The installation of %1 is complete. The installation of %1 is complete. @@ -1356,72 +1361,72 @@ The installer will quit and all changes will be lost. GeneralRequirements - + has at least %1 GiB available drive space has at least %1 GiB available drive space - + There is not enough drive space. At least %1 GiB is required. There is not enough drive space. At least %1 GiB is required. - + has at least %1 GiB working memory has at least %1 GiB working memory - + The system does not have enough working memory. At least %1 GiB is required. The system does not have enough working memory. At least %1 GiB is required. - + is plugged in to a power source is plugged in to a power source - + The system is not plugged in to a power source. The system is not plugged in to a power source. - + is connected to the Internet is connected to the Internet - + The system is not connected to the Internet. The system is not connected to the Internet. - + is running the installer as an administrator (root) is running the installer as an administrator (root) - + The setup program is not running with administrator rights. The setup program is not running with administrator rights. - + The installer is not running with administrator rights. The installer is not running with administrator rights. - + has a screen large enough to show the whole installer has a screen large enough to show the whole installer - + The screen is too small to display the setup program. The screen is too small to display the setup program. - + The screen is too small to display the installer. The screen is too small to display the installer. @@ -1769,6 +1774,16 @@ The installer will quit and all changes will be lost. No root mount point is set for MachineId. + + Map + + + Please select your preferred location on the map so the installer can suggest the locale + and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging + to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming. + + + NetInstallViewStep @@ -1907,6 +1922,19 @@ The installer will quit and all changes will be lost. Set the OEM Batch Identifier to <code>%1</code>. + + Offline + + + Timezone: %1 + + + + + To be able to select a timezone, make sure you are connected to the internet. Restart the installer after connecting. You can fine-tune Language and Locale settings below. + + + PWQ @@ -2494,107 +2522,107 @@ The installer will quit and all changes will be lost. Partitions - + Install %1 <strong>alongside</strong> another operating system. Install %1 <strong>alongside</strong> another operating system. - + <strong>Erase</strong> disk and install %1. <strong>Erase</strong> disk and install %1. - + <strong>Replace</strong> a partition with %1. <strong>Replace</strong> a partition with %1. - + <strong>Manual</strong> partitioning. <strong>Manual</strong> partitioning. - + Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3). Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3). - + <strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1. <strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1. - + <strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1. <strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1. - + <strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2). <strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2). - + Disk <strong>%1</strong> (%2) Disk <strong>%1</strong> (%2) - + Current: Current: - + After: After: - + No EFI system partition configured No EFI system partition configured - + An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start. - + An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start. - + EFI system partition flag not set EFI system partition flag not set - + Option to use GPT on BIOS Option to use GPT on BIOS - + A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT. - + Boot partition not encrypted Boot partition not encrypted - + A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window. - + has at least one disk device available. has at least one disk device available. - + There are no partitions to install on. There are no partitions to install on. @@ -2660,14 +2688,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. There was no output from the command. - + Output: @@ -2676,52 +2704,52 @@ Output: - + External command crashed. External command crashed. - + Command <i>%1</i> crashed. Command <i>%1</i> crashed. - + External command failed to start. External command failed to start. - + Command <i>%1</i> failed to start. Command <i>%1</i> failed to start. - + Internal error when starting command. Internal error when starting command. - + Bad parameters for process job call. Bad parameters for process job call. - + External command failed to finish. External command failed to finish. - + Command <i>%1</i> failed to finish in %2 seconds. Command <i>%1</i> failed to finish in %2 seconds. - + External command finished with errors. External command finished with errors. - + Command <i>%1</i> finished with exit code %2. Command <i>%1</i> finished with exit code %2. @@ -2729,32 +2757,27 @@ Output: QObject - + %1 (%2) %1 (%2) - - Requirements checking for module <i>%1</i> is complete. - Requirements checking for module <i>%1</i> is complete. - - - + unknown unknown - + extended extended - + unformatted unformatted - + swap swap @@ -2808,6 +2831,15 @@ Output: Unpartitioned space or unknown partition table + + Recommended + + + <p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/> + Setup can continue, but some features might be disabled.</p> + + + RemoveUserJob @@ -2843,73 +2875,88 @@ Output: Form - + Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. Select where to install %1.<br/><font color="red">Warning: </font>this will delete all files on the selected partition. - + The selected item does not appear to be a valid partition. The selected item does not appear to be a valid partition. - + %1 cannot be installed on empty space. Please select an existing partition. %1 cannot be installed on empty space. Please select an existing partition. - + %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. - + %1 cannot be installed on this partition. %1 cannot be installed on this partition. - + Data partition (%1) Data partition (%1) - + Unknown system partition (%1) Unknown system partition (%1) - + %1 system partition (%2) %1 system partition (%2) - + <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. <strong>%4</strong><br/><br/>The partition %1 is too small for %2. Please select a partition with capacity at least %3 GiB. - + <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. <strong>%2</strong><br/><br/>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1. - - - + + + <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. <strong>%3</strong><br/><br/>%1 will be installed on %2.<br/><font color="red">Warning: </font>all data on partition %2 will be lost. - + The EFI system partition at %1 will be used for starting %2. The EFI system partition at %1 will be used for starting %2. - + EFI system partition: EFI system partition: + + Requirements + + + <p>This computer does not satisfy the minimum requirements for installing %1.<br/> + Installation cannot continue.</p> + + + + + <p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/> + Setup can continue, but some features might be disabled.</p> + + + ResizeFSJob @@ -3032,12 +3079,12 @@ Output: ResultsListDialog - + For best results, please ensure that this computer: For best results, please ensure that this computer: - + System requirements System requirements @@ -3045,27 +3092,27 @@ Output: ResultsListWidget - + This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> This computer does not satisfy the minimum requirements for setting up %1.<br/>Setup cannot continue. <a href="#details">Details...</a> - + This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> This computer does not satisfy the minimum requirements for installing %1.<br/>Installation cannot continue. <a href="#details">Details...</a> - + This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. This computer does not satisfy some of the recommended requirements for setting up %1.<br/>Setup can continue, but some features might be disabled. - + This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. This computer does not satisfy some of the recommended requirements for installing %1.<br/>Installation can continue, but some features might be disabled. - + This program will ask you some questions and set up %2 on your computer. This program will ask you some questions and set up %2 on your computer. @@ -3348,53 +3395,82 @@ Output: TrackingInstallJob - + Installation feedback Installation feedback - + Sending installation feedback. Sending installation feedback. - + Internal error in install-tracking. Internal error in install-tracking. - + HTTP request timed out. HTTP request timed out. - TrackingMachineNeonJob + TrackingKUserFeedbackJob - + + KDE user feedback + + + + + Configuring KDE user feedback. + + + + + + Error in KDE user feedback configuration. + + + + + Could not configure KDE user feedback correctly, script error %1. + + + + + Could not configure KDE user feedback correctly, Calamares error %1. + + + + + TrackingMachineUpdateManagerJob + + Machine feedback - Machine feedback + Machine feedback - + Configuring machine feedback. - Configuring machine feedback. + Configuring machine feedback. - - + + Error in machine feedback configuration. - Error in machine feedback configuration. + Error in machine feedback configuration. - + Could not configure machine feedback correctly, script error %1. - Could not configure machine feedback correctly, script error %1. + Could not configure machine feedback correctly, script error %1. - + Could not configure machine feedback correctly, Calamares error %1. - Could not configure machine feedback correctly, Calamares error %1. + Could not configure machine feedback correctly, Calamares error %1. @@ -3411,8 +3487,8 @@ Output: - <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> - <html><head/><body><p>By selecting this, you will send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + <html><head/><body><p>Click here to send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> + @@ -3420,30 +3496,30 @@ Output: <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> - - Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with the last two options below), get continuous information about preferred applications. To see what will be sent, please click the help icon next to each area. - Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with the last two options below), get continuous information about preferred applications. To see what will be sent, please click the help icon next to each area. + + Tracking helps %1 to see how often it is installed, what hardware it is installed on and which applications are used. To see what will be sent, please click the help icon next to each area. + - - By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. - By selecting this you will send information about your installation and hardware. This information will <b>only be sent once</b> after the installation finishes. + + By selecting this you will send information about your installation and hardware. This information will only be sent <b>once</b> after the installation finishes. + - - By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. - By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. + + By selecting this you will periodically send information about your <b>machine</b> installation, hardware and applications, to %1. + - - By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. - By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. + + By selecting this you will regularly send information about your <b>user</b> installation, hardware, applications and application usage patterns, to %1. + TrackingViewStep - + Feedback Feedback @@ -3629,42 +3705,42 @@ Output: &Release notes - + <h1>Welcome to the Calamares setup program for %1.</h1> <h1>Welcome to the Calamares setup program for %1.</h1> - + <h1>Welcome to %1 setup.</h1> <h1>Welcome to %1 setup.</h1> - + <h1>Welcome to the Calamares installer for %1.</h1> <h1>Welcome to the Calamares installer for %1.</h1> - + <h1>Welcome to the %1 installer.</h1> <h1>Welcome to the %1 installer.</h1> - + %1 support %1 support - + About %1 setup About %1 setup - + About %1 installer About %1 installer - + <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. <h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software. @@ -3672,7 +3748,7 @@ Output: WelcomeQmlViewStep - + Welcome Welcome @@ -3680,7 +3756,7 @@ Output: WelcomeViewStep - + Welcome Welcome @@ -3720,6 +3796,26 @@ Output: Back + + i18n + + + <h1>Languages</h1> </br> + The system locale setting affects the language and character set for some command line user interface elements. The current setting is <strong>%1</strong>. + + + + + <h1>Locales</h1> </br> + The system locale setting affects the language and character set for some command line user interface elements. The current setting is <strong>%1</strong>. + + + + + Back + Back + + keyboardq @@ -3765,6 +3861,24 @@ Output: Test your keyboard + + localeq + + + System language set to %1 + + + + + Numbers and dates locale set to %1 + + + + + Change + + + notesqml @@ -3838,27 +3952,27 @@ Output: <p>This program will ask you some questions and set up %1 on your computer.</p> - + About About - + Support Support - + Known issues Known issues - + Release notes Release notes - + Donate Donate diff --git a/lang/python.pot b/lang/python.pot index 633f658fb..893f3d17f 100644 --- a/lang/python.pot +++ b/lang/python.pot @@ -2,350 +2,338 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"POT-Creation-Date: 2020-06-18 15:42+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: \n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: src/modules/packages/main.py:59 src/modules/packages/main.py:68 -#: src/modules/packages/main.py:78 -msgid "Install packages." -msgstr "Install packages." - -#: src/modules/packages/main.py:66 -#, python-format -msgid "Processing packages (%(count)d / %(total)d)" -msgstr "Processing packages (%(count)d / %(total)d)" - -#: src/modules/packages/main.py:71 -#, python-format -msgid "Installing one package." -msgid_plural "Installing %(num)d packages." -msgstr[0] "Installing one package." -msgstr[1] "Installing %(num)d packages." - -#: src/modules/packages/main.py:74 -#, python-format -msgid "Removing one package." -msgid_plural "Removing %(num)d packages." -msgstr[0] "Removing one package." -msgstr[1] "Removing %(num)d packages." - -#: src/modules/networkcfg/main.py:37 -msgid "Saving network configuration." -msgstr "Saving network configuration." - -#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205 -#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78 -#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144 -#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95 -#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332 -#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94 -#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171 -msgid "Configuration Error" -msgstr "Configuration Error" - -#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210 -#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145 -#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339 -#: src/modules/initramfscfg/main.py:99 -msgid "No root mount point is given for
{!s}
to use." -msgstr "No root mount point is given for
{!s}
to use." - -#: src/modules/umount/main.py:40 -msgid "Unmount file systems." -msgstr "Unmount file systems." - -#: src/modules/initcpiocfg/main.py:37 -msgid "Configuring mkinitcpio." -msgstr "Configuring mkinitcpio." - -#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96 -#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95 -#: src/modules/rawfs/main.py:172 -msgid "No partitions are defined for
{!s}
to use." -msgstr "No partitions are defined for
{!s}
to use." - -#: src/modules/openrcdmcryptcfg/main.py:34 -msgid "Configuring OpenRC dmcrypt service." -msgstr "Configuring OpenRC dmcrypt service." - -#: src/modules/unpackfs/main.py:44 -msgid "Filling up filesystems." -msgstr "Filling up filesystems." - -#: src/modules/unpackfs/main.py:257 -msgid "rsync failed with error code {}." -msgstr "rsync failed with error code {}." - -#: src/modules/unpackfs/main.py:302 -msgid "Unpacking image {}/{}, file {}/{}" -msgstr "Unpacking image {}/{}, file {}/{}" - -#: src/modules/unpackfs/main.py:317 -msgid "Starting to unpack {}" -msgstr "Starting to unpack {}" - -#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432 -msgid "Failed to unpack image \"{}\"" -msgstr "Failed to unpack image \"{}\"" - -#: src/modules/unpackfs/main.py:399 -msgid "No mount point for root partition" -msgstr "No mount point for root partition" - -#: src/modules/unpackfs/main.py:400 -msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" -msgstr "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" - -#: src/modules/unpackfs/main.py:405 -msgid "Bad mount point for root partition" -msgstr "Bad mount point for root partition" - -#: src/modules/unpackfs/main.py:406 -msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" -msgstr "rootMountPoint is \"{}\", which does not exist, doing nothing" - -#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426 -#: src/modules/unpackfs/main.py:446 -msgid "Bad unsquash configuration" -msgstr "Bad unsquash configuration" - -#: src/modules/unpackfs/main.py:423 -msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" -msgstr "The filesystem for \"{}\" ({}) is not supported by your current kernel" - -#: src/modules/unpackfs/main.py:427 -msgid "The source filesystem \"{}\" does not exist" -msgstr "The source filesystem \"{}\" does not exist" - -#: src/modules/unpackfs/main.py:433 -msgid "" -"Failed to find unsquashfs, make sure you have the squashfs-tools package " -"installed" +#: src/modules/grubcfg/main.py:37 +msgid "Configure GRUB." msgstr "" -"Failed to find unsquashfs, make sure you have the squashfs-tools package " -"installed" -#: src/modules/unpackfs/main.py:447 -msgid "The destination \"{}\" in the target system is not a directory" -msgstr "The destination \"{}\" in the target system is not a directory" +#: src/modules/mount/main.py:38 +msgid "Mounting partitions." +msgstr "" + +#: src/modules/mount/main.py:150 src/modules/initcpiocfg/main.py:205 +#: src/modules/initcpiocfg/main.py:209 +#: src/modules/luksopenswaphookcfg/main.py:95 +#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:173 +#: src/modules/initramfscfg/main.py:94 src/modules/initramfscfg/main.py:98 +#: src/modules/openrcdmcryptcfg/main.py:78 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:332 +#: src/modules/fstab/main.py:338 src/modules/localecfg/main.py:144 +#: src/modules/networkcfg/main.py:48 +msgid "Configuration Error" +msgstr "" + +#: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:206 +#: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:174 +#: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 +#: src/modules/fstab/main.py:333 +msgid "No partitions are defined for
{!s}
to use." +msgstr "" #: src/modules/services-systemd/main.py:35 msgid "Configure systemd services" -msgstr "Configure systemd services" +msgstr "" #: src/modules/services-systemd/main.py:68 #: src/modules/services-openrc/main.py:102 msgid "Cannot modify service" -msgstr "Cannot modify service" +msgstr "" #: src/modules/services-systemd/main.py:69 msgid "" "systemctl {arg!s} call in chroot returned error code {num!s}." msgstr "" -"systemctl {arg!s} call in chroot returned error code {num!s}." #: src/modules/services-systemd/main.py:72 #: src/modules/services-systemd/main.py:76 msgid "Cannot enable systemd service {name!s}." -msgstr "Cannot enable systemd service {name!s}." +msgstr "" #: src/modules/services-systemd/main.py:74 msgid "Cannot enable systemd target {name!s}." -msgstr "Cannot enable systemd target {name!s}." +msgstr "" #: src/modules/services-systemd/main.py:78 msgid "Cannot disable systemd target {name!s}." -msgstr "Cannot disable systemd target {name!s}." +msgstr "" #: src/modules/services-systemd/main.py:80 msgid "Cannot mask systemd unit {name!s}." -msgstr "Cannot mask systemd unit {name!s}." +msgstr "" #: src/modules/services-systemd/main.py:82 msgid "" -"Unknown systemd commands {command!s} and " -"{suffix!s} for unit {name!s}." +"Unknown systemd commands {command!s} and {suffix!s} for unit {name!s}." msgstr "" -"Unknown systemd commands {command!s} and " -"{suffix!s} for unit {name!s}." -#: src/modules/dummypython/main.py:44 -msgid "Dummy python job." -msgstr "Dummy python job." +#: src/modules/umount/main.py:40 +msgid "Unmount file systems." +msgstr "" -#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102 -#: src/modules/dummypython/main.py:103 -msgid "Dummy python step {}" -msgstr "Dummy python step {}" +#: src/modules/unpackfs/main.py:44 +msgid "Filling up filesystems." +msgstr "" -#: src/modules/bootloader/main.py:51 -msgid "Install bootloader." -msgstr "Install bootloader." +#: src/modules/unpackfs/main.py:257 +msgid "rsync failed with error code {}." +msgstr "" -#: src/modules/localecfg/main.py:39 -msgid "Configuring locales." -msgstr "Configuring locales." +#: src/modules/unpackfs/main.py:302 +msgid "Unpacking image {}/{}, file {}/{}" +msgstr "" -#: src/modules/mount/main.py:38 -msgid "Mounting partitions." -msgstr "Mounting partitions." +#: src/modules/unpackfs/main.py:317 +msgid "Starting to unpack {}" +msgstr "" -#: src/modules/plymouthcfg/main.py:36 -msgid "Configure Plymouth theme" -msgstr "Configure Plymouth theme" +#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:448 +msgid "Failed to unpack image \"{}\"" +msgstr "" + +#: src/modules/unpackfs/main.py:415 +msgid "No mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:416 +msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:421 +msgid "Bad mount point for root partition" +msgstr "" + +#: src/modules/unpackfs/main.py:422 +msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" +msgstr "" + +#: src/modules/unpackfs/main.py:438 src/modules/unpackfs/main.py:442 +#: src/modules/unpackfs/main.py:462 +msgid "Bad unsquash configuration" +msgstr "" + +#: src/modules/unpackfs/main.py:439 +msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel" +msgstr "" + +#: src/modules/unpackfs/main.py:443 +msgid "The source filesystem \"{}\" does not exist" +msgstr "" + +#: src/modules/unpackfs/main.py:449 +msgid "" +"Failed to find unsquashfs, make sure you have the squashfs-tools package " +"installed" +msgstr "" + +#: src/modules/unpackfs/main.py:463 +msgid "The destination \"{}\" in the target system is not a directory" +msgstr "" + +#: src/modules/displaymanager/main.py:523 +msgid "Cannot write KDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:524 +msgid "KDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:585 +msgid "Cannot write LXDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:586 +msgid "LXDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:669 +msgid "Cannot write LightDM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:670 +msgid "LightDM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:744 +msgid "Cannot configure LightDM" +msgstr "" + +#: src/modules/displaymanager/main.py:745 +msgid "No LightDM greeter installed." +msgstr "" + +#: src/modules/displaymanager/main.py:776 +msgid "Cannot write SLIM configuration file" +msgstr "" + +#: src/modules/displaymanager/main.py:777 +msgid "SLIM config file {!s} does not exist" +msgstr "" + +#: src/modules/displaymanager/main.py:903 +msgid "No display managers selected for the displaymanager module." +msgstr "" + +#: src/modules/displaymanager/main.py:904 +msgid "" +"The displaymanagers list is empty or undefined in bothglobalstorage and " +"displaymanager.conf." +msgstr "" + +#: src/modules/displaymanager/main.py:986 +msgid "Display manager configuration was incomplete" +msgstr "" + +#: src/modules/initcpiocfg/main.py:37 +msgid "Configuring mkinitcpio." +msgstr "" + +#: src/modules/initcpiocfg/main.py:210 +#: src/modules/luksopenswaphookcfg/main.py:100 +#: src/modules/initramfscfg/main.py:99 src/modules/openrcdmcryptcfg/main.py:83 +#: src/modules/fstab/main.py:339 src/modules/localecfg/main.py:145 +#: src/modules/networkcfg/main.py:49 +msgid "No root mount point is given for
{!s}
to use." +msgstr "" #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." -msgstr "Configuring encrypted swap." +msgstr "" -#: src/modules/fstab/main.py:38 -msgid "Writing fstab." -msgstr "Writing fstab." +#: src/modules/rawfs/main.py:35 +msgid "Installing data." +msgstr "" #: src/modules/services-openrc/main.py:38 msgid "Configure OpenRC services" -msgstr "Configure OpenRC services" +msgstr "" #: src/modules/services-openrc/main.py:66 msgid "Cannot add service {name!s} to run-level {level!s}." -msgstr "Cannot add service {name!s} to run-level {level!s}." +msgstr "" #: src/modules/services-openrc/main.py:68 msgid "Cannot remove service {name!s} from run-level {level!s}." -msgstr "Cannot remove service {name!s} from run-level {level!s}." +msgstr "" #: src/modules/services-openrc/main.py:70 msgid "" "Unknown service-action {arg!s} for service {name!s} in run-" "level {level!s}." msgstr "" -"Unknown service-action {arg!s} for service {name!s} in run-" -"level {level!s}." #: src/modules/services-openrc/main.py:103 msgid "" "rc-update {arg!s} call in chroot returned error code {num!s}." msgstr "" -"rc-update {arg!s} call in chroot returned error code {num!s}." #: src/modules/services-openrc/main.py:110 msgid "Target runlevel does not exist" -msgstr "Target runlevel does not exist" +msgstr "" #: src/modules/services-openrc/main.py:111 msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." msgstr "" -"The path for runlevel {level!s} is {path!s}, which does not " -"exist." #: src/modules/services-openrc/main.py:119 msgid "Target service does not exist" -msgstr "Target service does not exist" +msgstr "" #: src/modules/services-openrc/main.py:120 msgid "" -"The path for service {name!s} is {path!s}, which does not " -"exist." +"The path for service {name!s} is {path!s}, which does not exist." msgstr "" -"The path for service {name!s} is {path!s}, which does not " -"exist." -#: src/modules/dracut/main.py:36 -msgid "Creating initramfs with dracut." -msgstr "Creating initramfs with dracut." - -#: src/modules/dracut/main.py:58 -msgid "Failed to run dracut on the target" -msgstr "Failed to run dracut on the target" - -#: src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "The exit code was {}" - -#: src/modules/grubcfg/main.py:37 -msgid "Configure GRUB." -msgstr "Configure GRUB." - -#: src/modules/displaymanager/main.py:515 -msgid "Cannot write KDM configuration file" -msgstr "Cannot write KDM configuration file" - -#: src/modules/displaymanager/main.py:516 -msgid "KDM config file {!s} does not exist" -msgstr "KDM config file {!s} does not exist" - -#: src/modules/displaymanager/main.py:577 -msgid "Cannot write LXDM configuration file" -msgstr "Cannot write LXDM configuration file" - -#: src/modules/displaymanager/main.py:578 -msgid "LXDM config file {!s} does not exist" -msgstr "LXDM config file {!s} does not exist" - -#: src/modules/displaymanager/main.py:661 -msgid "Cannot write LightDM configuration file" -msgstr "Cannot write LightDM configuration file" - -#: src/modules/displaymanager/main.py:662 -msgid "LightDM config file {!s} does not exist" -msgstr "LightDM config file {!s} does not exist" - -#: src/modules/displaymanager/main.py:736 -msgid "Cannot configure LightDM" -msgstr "Cannot configure LightDM" - -#: src/modules/displaymanager/main.py:737 -msgid "No LightDM greeter installed." -msgstr "No LightDM greeter installed." - -#: src/modules/displaymanager/main.py:768 -msgid "Cannot write SLIM configuration file" -msgstr "Cannot write SLIM configuration file" - -#: src/modules/displaymanager/main.py:769 -msgid "SLIM config file {!s} does not exist" -msgstr "SLIM config file {!s} does not exist" - -#: src/modules/displaymanager/main.py:895 -msgid "No display managers selected for the displaymanager module." -msgstr "No display managers selected for the displaymanager module." - -#: src/modules/displaymanager/main.py:896 -msgid "" -"The displaymanagers list is empty or undefined in bothglobalstorage and " -"displaymanager.conf." +#: src/modules/plymouthcfg/main.py:36 +msgid "Configure Plymouth theme" msgstr "" -"The displaymanagers list is empty or undefined in bothglobalstorage and " -"displaymanager.conf." -#: src/modules/displaymanager/main.py:978 -msgid "Display manager configuration was incomplete" -msgstr "Display manager configuration was incomplete" +#: src/modules/packages/main.py:59 src/modules/packages/main.py:68 +#: src/modules/packages/main.py:78 +msgid "Install packages." +msgstr "" -#: src/modules/initramfscfg/main.py:41 -msgid "Configuring initramfs." -msgstr "Configuring initramfs." +#: src/modules/packages/main.py:66 +#, python-format +msgid "Processing packages (%(count)d / %(total)d)" +msgstr "" + +#: src/modules/packages/main.py:71 +#, python-format +msgid "Installing one package." +msgid_plural "Installing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/packages/main.py:74 +#, python-format +msgid "Removing one package." +msgid_plural "Removing %(num)d packages." +msgstr[0] "" +msgstr[1] "" + +#: src/modules/bootloader/main.py:51 +msgid "Install bootloader." +msgstr "" #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." -msgstr "Setting hardware clock." +msgstr "" -#: src/modules/rawfs/main.py:35 -msgid "Installing data." -msgstr "Installing data." +#: src/modules/dracut/main.py:36 +msgid "Creating initramfs with dracut." +msgstr "" + +#: src/modules/dracut/main.py:58 +msgid "Failed to run dracut on the target" +msgstr "" + +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "" + +#: src/modules/initramfscfg/main.py:41 +msgid "Configuring initramfs." +msgstr "" + +#: src/modules/openrcdmcryptcfg/main.py:34 +msgid "Configuring OpenRC dmcrypt service." +msgstr "" + +#: src/modules/fstab/main.py:38 +msgid "Writing fstab." +msgstr "" + +#: src/modules/dummypython/main.py:44 +msgid "Dummy python job." +msgstr "" + +#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102 +#: src/modules/dummypython/main.py:103 +msgid "Dummy python step {}" +msgstr "" + +#: src/modules/localecfg/main.py:39 +msgid "Configuring locales." +msgstr "" + +#: src/modules/networkcfg/main.py:37 +msgid "Saving network configuration." +msgstr "" diff --git a/src/modules/dummypythonqt/lang/dummypythonqt.pot b/src/modules/dummypythonqt/lang/dummypythonqt.pot index 59be66f7e..13cc7ada3 100644 --- a/src/modules/dummypythonqt/lang/dummypythonqt.pot +++ b/src/modules/dummypythonqt/lang/dummypythonqt.pot @@ -2,41 +2,41 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 23:13+0200\n" +"POT-Creation-Date: 2020-06-18 15:42+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: \n" #: src/modules/dummypythonqt/main.py:84 msgid "Click me!" -msgstr "Click me!" +msgstr "" #: src/modules/dummypythonqt/main.py:94 msgid "A new QLabel." -msgstr "A new QLabel." +msgstr "" #: src/modules/dummypythonqt/main.py:97 msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" +msgstr "" #: src/modules/dummypythonqt/main.py:183 msgid "The Dummy PythonQt Job" -msgstr "The Dummy PythonQt Job" +msgstr "" #: src/modules/dummypythonqt/main.py:186 msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "This is the Dummy PythonQt Job. The dummy job says: {}" +msgstr "" #: src/modules/dummypythonqt/main.py:190 msgid "A status message for Dummy PythonQt Job." -msgstr "A status message for Dummy PythonQt Job." +msgstr "" From 665c425633a5c66f2e110fb8af0ccc4f82610c03 Mon Sep 17 00:00:00 2001 From: demmm Date: Thu, 18 Jun 2020 15:53:38 +0200 Subject: [PATCH 103/105] [CHANGES] add localeq & welcomeq additions --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 82b70f9af..d50207086 100644 --- a/CHANGES +++ b/CHANGES @@ -25,9 +25,13 @@ This release contains contributions from (alphabetically by first name): - *locale* put some more places into the correct timezone **visually**; for instance Norfolk Island gave up UTC+11.5 in 2015 and is now UTC+11, but Calamares still showed it in a zone separate from UTC+11. + - *localeq* can now properly switch between on & offline mode, + it detects internet status through js. - *packages* gained support for the Void Linux package manager, *xbps*. (thanks Pablo) - *tracking* now supports kuserfeedback configuration. + - *welcomeq* added the GEOIP configuration option, so locale can be + initially set according to IP address. # 3.2.25 (2020-06-06) # From 463545290e1586b0055e73b6471fc9692b93f764 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Jun 2020 16:12:12 +0200 Subject: [PATCH 104/105] [users] Fix up schema syntax - Remove schema items *availableShells* and *avatarFilePath* because those have no implementation. --- src/modules/users/users.conf | 2 +- src/modules/users/users.schema.yaml | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/modules/users/users.conf b/src/modules/users/users.conf index 174a60142..32f74978a 100644 --- a/src/modules/users/users.conf +++ b/src/modules/users/users.conf @@ -124,7 +124,7 @@ allowWeakPasswordsDefault: false # and rely on a correct configuration file in /etc/default/useradd # - set, non-empty, use that path as shell. No validation is done # that the shell actually exists or is executable. -# userShell: /bin/bash +userShell: /bin/bash # Hostname setting # diff --git a/src/modules/users/users.schema.yaml b/src/modules/users/users.schema.yaml index b667df7f6..a3bba5078 100644 --- a/src/modules/users/users.schema.yaml +++ b/src/modules/users/users.schema.yaml @@ -4,15 +4,15 @@ $id: https://calamares.io/schemas/users additionalProperties: false type: object properties: - "defaultGroups": - required: true - type: seq - sequence: - - { type: str } - "autologinGroup": { type: string, required: true } - "doAutologin": { type: boolean, default: true } - "sudoersGroup": { type: string, required: true } - "setRootPassword": { type: boolean, default: true } - "availableShells": { type: str } - "avatarFilePath": { type: str } - "doReusePassword": { type: boolean, default: true } + defaultGroups: + type: array + items: { type: string } + autologinGroup: { type: string } + doAutologin: { type: boolean, default: true } + sudoersGroup: { type: string } + setRootPassword: { type: boolean, default: true } + doReusePassword: { type: boolean, default: true } +required: + - defaultGroups + - autologinGroup + - sudoersGroup From 5da201246554e739ec2771773b1b72464035ff19 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 18 Jun 2020 16:23:32 +0200 Subject: [PATCH 105/105] [users] Expand schema to support the keys documented in users.conf - Now the documentation in the file and the source is leading to update the schema, but in future those should go hand-in-hand --- src/modules/users/users.schema.yaml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/modules/users/users.schema.yaml b/src/modules/users/users.schema.yaml index a3bba5078..44cb9f71c 100644 --- a/src/modules/users/users.schema.yaml +++ b/src/modules/users/users.schema.yaml @@ -4,14 +4,34 @@ $id: https://calamares.io/schemas/users additionalProperties: false type: object properties: + # User shell, should be path to /bin/sh or so + userShell: { type: string } + # Group settings defaultGroups: type: array items: { type: string } autologinGroup: { type: string } - doAutologin: { type: boolean, default: true } sudoersGroup: { type: string } + # Skip login (depends on displaymanager support) + doAutologin: { type: boolean, default: true } + # Root password separate from user password? setRootPassword: { type: boolean, default: true } doReusePassword: { type: boolean, default: true } + # Passwords that don't pass a quality test + allowWeakPasswords: { type: boolean, default: false } + allowWeakPasswordsDefault: { type: boolean, default: false } + passwordRequirements: + additionalProperties: false + type: object + properties: + nonempty: { type: boolean, default: true } + minLength: { type: number } + maxLength: { type: number } + libpwquality: { type: array, items: { type: string } } # Don't know what libpwquality supports + # Hostname setting + setHostname: { type: string, enum: [ None, EtcFile, Hostnamed ] } + writeHostsFile: { type: boolean, default: true } + required: - defaultGroups - autologinGroup